From d4b8fd9f5a43b05af9fdb882e0f7941af78266eb Mon Sep 17 00:00:00 2001 From: rerion Date: Fri, 6 Jan 2017 21:59:35 +0100 Subject: [PATCH] Add methods allowing creation of X11 window with specified visual and screen --- src/api/x11/window.rs | 33 +++++++++++++++++++++++------- src/os/unix.rs | 18 +++++++++++++++- src/platform/linux/api_dispatch.rs | 10 ++++++--- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs index cdc2d62b..276a2415 100644 --- a/src/api/x11/window.rs +++ b/src/api/x11/window.rs @@ -14,6 +14,7 @@ use std::time::Duration; use CursorState; use WindowAttributes; +use platform::PlatformSpecificWindowBuilderAttributes; use platform::MonitorId as PlatformMonitorId; @@ -282,7 +283,8 @@ pub struct Window { } impl Window { - pub fn new(display: &Arc, window_attrs: &WindowAttributes) + pub fn new(display: &Arc, window_attrs: &WindowAttributes, + pl_attribs: &PlatformSpecificWindowBuilderAttributes) -> Result { let dimensions = { @@ -303,9 +305,12 @@ impl Window { }; - let screen_id = match window_attrs.monitor { - Some(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32, - _ => unsafe { (display.xlib.XDefaultScreen)(display.display) }, + let screen_id = match pl_attribs.screen_id { + Some(id) => id, + None => match window_attrs.monitor { + Some(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32, + _ => unsafe { (display.xlib.XDefaultScreen)(display.display) }, + } }; // finding the mode to switch to if necessary @@ -347,7 +352,12 @@ impl Window { // creating let mut set_win_attr = { let mut swa: ffi::XSetWindowAttributes = unsafe { mem::zeroed() }; - swa.colormap = 0; + swa.colormap = if let Some(vi) = pl_attribs.visual_infos { + unsafe { + let visual = vi.visual; + (display.xlib.XCreateColormap)(display.display, root, visual, ffi::AllocNone) + } + } else { 0 }; swa.event_mask = ffi::ExposureMask | ffi::StructureNotifyMask | ffi::VisibilityChangeMask | ffi::KeyPressMask | ffi::PointerMotionMask | ffi::KeyReleaseMask | ffi::ButtonPressMask | @@ -369,8 +379,17 @@ impl Window { // finally creating the window let window = unsafe { let win = (display.xlib.XCreateWindow)(display.display, root, 0, 0, dimensions.0 as libc::c_uint, - dimensions.1 as libc::c_uint, 0, ffi::CopyFromParent, ffi::InputOutput as libc::c_uint, - ffi::CopyFromParent as *mut _, window_attributes, + dimensions.1 as libc::c_uint, 0, + match pl_attribs.visual_infos { + Some(vi) => vi.depth, + None => ffi::CopyFromParent + }, + ffi::InputOutput as libc::c_uint, + match pl_attribs.visual_infos { + Some(vi) => vi.visual, + None => ffi::CopyFromParent as *mut _ + }, + window_attributes, &mut set_win_attr); display.check_errors().expect("Failed to call XCreateWindow"); win diff --git a/src/os/unix.rs b/src/os/unix.rs index d325f135..f983925f 100644 --- a/src/os/unix.rs +++ b/src/os/unix.rs @@ -1,11 +1,13 @@ #![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] use std::sync::Arc; +use std::ptr; use libc; use Window; use platform::Window as LinuxWindow; use WindowBuilder; use api::x11::XConnection; +use api::x11::ffi::XVisualInfo; use wayland_client::protocol::wl_display::WlDisplay; use wayland_client::protocol::wl_surface::WlSurface; @@ -142,8 +144,22 @@ impl WindowExt for Window { /// Additional methods on `WindowBuilder` that are specific to Unix. pub trait WindowBuilderExt { - + fn with_visual(self, visual_infos: *const XVisualInfo) -> WindowBuilder; + fn with_screen(self, screen_id: i32) -> WindowBuilder; } impl WindowBuilderExt for WindowBuilder { + #[inline] + fn with_visual(mut self, visual_infos: *const XVisualInfo) -> WindowBuilder { + self.platform_specific.visual_infos = Some( + unsafe { ptr::read(visual_infos) } + ); + self + } + + #[inline] + fn with_screen(mut self, screen_id: i32) -> WindowBuilder { + self.platform_specific.screen_id = Some(screen_id); + self + } } diff --git a/src/platform/linux/api_dispatch.rs b/src/platform/linux/api_dispatch.rs index 7b14c265..66deb688 100644 --- a/src/platform/linux/api_dispatch.rs +++ b/src/platform/linux/api_dispatch.rs @@ -13,9 +13,13 @@ use api::x11; use api::x11::XConnection; use api::x11::XError; use api::x11::XNotSupported; +use api::x11::ffi::XVisualInfo; #[derive(Clone, Default)] -pub struct PlatformSpecificWindowBuilderAttributes; +pub struct PlatformSpecificWindowBuilderAttributes { + pub visual_infos: Option, + pub screen_id: Option, +} enum Backend { X(Arc), @@ -165,7 +169,7 @@ impl<'a> Iterator for WaitEventsIterator<'a> { impl Window { #[inline] - pub fn new(window: &WindowAttributes, _: &PlatformSpecificWindowBuilderAttributes) + pub fn new(window: &WindowAttributes, pl_attribs: &PlatformSpecificWindowBuilderAttributes) -> Result { match *BACKEND { @@ -174,7 +178,7 @@ impl Window { }, Backend::X(ref connec) => { - x11::Window::new(connec, window).map(Window::X) + x11::Window::new(connec, window, pl_attribs).map(Window::X) }, Backend::Error(ref error) => {