From a4052b8693a648142e12de623f46215da96da708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Mon, 28 Aug 2017 00:19:26 +0100 Subject: [PATCH 1/8] Add window maximization API Implement a simple API to set a window to maximized. Implement it only for the X11 backend. --- src/lib.rs | 6 ++ src/platform/linux/mod.rs | 8 +++ src/platform/linux/x11/window.rs | 105 ++++++++++++++++++------------- src/window.rs | 13 ++++ 4 files changed, 90 insertions(+), 42 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 89e37f1f..0121365e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -402,6 +402,11 @@ pub struct WindowAttributes { /// The default is `"winit window"`. pub title: String, + /// Whether the window should be maximized upon creation. + /// + /// The default is `false`. + pub maximized: bool, + /// Whether the window should be immediately visible upon creation. /// /// The default is `true`. @@ -432,6 +437,7 @@ impl Default for WindowAttributes { max_dimensions: None, monitor: None, title: "winit window".to_owned(), + maximized: false, visible: true, transparent: false, decorations: true, diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index af431a10..03e5ae4c 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -309,6 +309,14 @@ impl Window2 { &Window2::Wayland(ref w) => w.get_surface().ptr() as *mut _ } } + + #[inline] + pub fn set_maximized(&self, maximized: bool) { + match self { + &Window2::X(ref w) => w.set_maximized(maximized), + &Window2::Wayland(ref _w) => {}, + } + } } unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent) diff --git a/src/platform/linux/x11/window.rs b/src/platform/linux/x11/window.rs index 7e2ddfe1..f7b1e8d1 100644 --- a/src/platform/linux/x11/window.rs +++ b/src/platform/linux/x11/window.rs @@ -35,6 +35,7 @@ unsafe impl Send for WindowProxyData {} pub struct XWindow { display: Arc, window: ffi::Window, + root: ffi::Window, is_fullscreen: bool, screen_id: libc::c_int, xf86_desk_mode: Option, @@ -227,6 +228,12 @@ impl Window { }); } + // set maximization + if window_attrs.maximized { + Window::set_netwm(display, window, root, "_NET_WM_STATE_MAXIMIZED_HORZ", true); + Window::set_netwm(display, window, root, "_NET_WM_STATE_MAXIMIZED_VERT", true); + } + // set visibility if window_attrs.visible { unsafe { @@ -257,48 +264,7 @@ impl Window { let is_fullscreen = window_attrs.monitor.is_some(); if is_fullscreen { - let state_atom = unsafe { - with_c_str("_NET_WM_STATE", |state| - (display.xlib.XInternAtom)(display.display, state, 0) - ) - }; - display.check_errors().expect("Failed to call XInternAtom"); - let fullscreen_atom = unsafe { - with_c_str("_NET_WM_STATE_FULLSCREEN", |state_fullscreen| - (display.xlib.XInternAtom)(display.display, state_fullscreen, 0) - ) - }; - display.check_errors().expect("Failed to call XInternAtom"); - - let client_message_event = ffi::XClientMessageEvent { - type_: ffi::ClientMessage, - serial: 0, - send_event: 1, // true because we are sending this through `XSendEvent` - display: display.display, - window: window, - message_type: state_atom, // the _NET_WM_STATE atom is sent to change the state of a window - format: 32, // view `data` as `c_long`s - data: { - let mut data = ffi::ClientMessageData::new(); - // This first `long` is the action; `1` means add/set following property. - data.set_long(0, 1); - // This second `long` is the property to set (fullscreen) - data.set_long(1, fullscreen_atom as c_long); - data - } - }; - let mut x_event = ffi::XEvent::from(client_message_event); - - unsafe { - (display.xlib.XSendEvent)( - display.display, - root, - 0, - ffi::SubstructureRedirectMask | ffi::SubstructureNotifyMask, - &mut x_event as *mut _ - ); - display.check_errors().expect("Failed to call XSendEvent"); - } + Window::set_netwm(display, window, root, "_NET_WM_STATE_FULLSCREEN", true); if let Some(mut mode_to_switch_to) = mode_to_switch_to { unsafe { @@ -375,6 +341,7 @@ impl Window { x: Arc::new(XWindow { display: display.clone(), window: window, + root: root, screen_id: screen_id, is_fullscreen: is_fullscreen, xf86_desk_mode: xf86_desk_mode, @@ -418,6 +385,60 @@ impl Window { Ok(window) } + fn set_netwm(display: &Arc, window: u64, root: u64, property: &str, val: bool) { + let state_atom = unsafe { + with_c_str("_NET_WM_STATE", |state| + (display.xlib.XInternAtom)(display.display, state, 0) + ) + }; + display.check_errors().expect("Failed to call XInternAtom"); + let atom = unsafe { + with_c_str(property, |state| + (display.xlib.XInternAtom)(display.display, state, 0) + ) + }; + display.check_errors().expect("Failed to call XInternAtom"); + + let client_message_event = ffi::XClientMessageEvent { + type_: ffi::ClientMessage, + serial: 0, + send_event: 1, // true because we are sending this through `XSendEvent` + display: display.display, + window: window, + message_type: state_atom, // the _NET_WM_STATE atom is sent to change the state of a window + format: 32, // view `data` as `c_long`s + data: { + let mut data = ffi::ClientMessageData::new(); + // This first `long` is the action; `1` means add/set following property. + data.set_long(0, val as i64); + // This second `long` is the property to set (fullscreen) + data.set_long(1, atom as c_long); + data + } + }; + let mut x_event = ffi::XEvent::from(client_message_event); + + unsafe { + (display.xlib.XSendEvent)( + display.display, + root, + 0, + ffi::SubstructureRedirectMask | ffi::SubstructureNotifyMask, + &mut x_event as *mut _ + ); + display.check_errors().expect("Failed to call XSendEvent"); + } + } + + pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", fullscreen); + } + + pub fn set_maximized(&self, maximized: bool) { + Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_MAXIMIZED_HORZ", maximized); + Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_MAXIMIZED_VERT", maximized); + } + pub fn set_title(&self, title: &str) { let wm_name = unsafe { (self.x.display.xlib.XInternAtom)(self.x.display.display, b"_NET_WM_NAME\0".as_ptr() as *const _, 0) diff --git a/src/window.rs b/src/window.rs index c499eaf6..c81f58ce 100644 --- a/src/window.rs +++ b/src/window.rs @@ -66,6 +66,13 @@ impl WindowBuilder { self } + /// Requests maximized mode. + #[inline] + pub fn with_maximized(mut self, maximized: bool) -> WindowBuilder { + self.window.maximized = maximized; + self + } + /// Sets whether the window will be initially hidden or visible. #[inline] pub fn with_visibility(mut self, visible: bool) -> WindowBuilder { @@ -292,6 +299,12 @@ impl Window { self.window.set_cursor_state(state) } + /// Sets the window to maximized or back + #[inline] + pub fn set_maximized(&self, maximized: bool) { + self.window.set_maximized(maximized) + } + #[inline] pub fn id(&self) -> WindowId { WindowId(self.window.id()) From 1d97a2a506ae29ea4cb19088ac18966537003cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Mon, 28 Aug 2017 00:22:26 +0100 Subject: [PATCH 2/8] Implement Windowed Fullscreen There are two kinds of fullscreen. One where you take over the whole output the other where you just set the window size to the screen size and get rid of decorations. The first one already existed, implement the second which is more common for normal desktop apps. Use an enum to consolidate all the fullscreen states. --- src/lib.rs | 24 +++++++++++++++++++--- src/platform/android/mod.rs | 4 ++++ src/platform/linux/mod.rs | 10 ++++++++- src/platform/linux/wayland/context.rs | 6 ++++++ src/platform/linux/wayland/window.rs | 2 +- src/platform/linux/x11/monitor.rs | 5 +++++ src/platform/linux/x11/window.rs | 15 +++++++++----- src/window.rs | 29 +++++++++++++++++++++++---- 8 files changed, 81 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0121365e..bb72c979 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -356,6 +356,24 @@ pub enum MouseCursor { RowResize, } +/// Describes if the Window is in one of the fullscreen modes +#[derive(Clone, PartialEq)] +pub enum FullScreenState { + None, + Windowed, + Exclusive(platform::MonitorId), +} + +impl FullScreenState { + pub fn get_monitor(&self) -> Option { + if let FullScreenState::Exclusive(ref monitor) = *self { + Some(monitor.clone()) + } else { + None + } + } +} + /// Describes how winit handles the cursor. #[derive(Debug, Copy, Clone, PartialEq)] pub enum CursorState { @@ -392,10 +410,10 @@ pub struct WindowAttributes { /// The default is `None`. pub max_dimensions: Option<(u32, u32)>, - /// If `Some`, the window will be in fullscreen mode with the given monitor. + /// Whether the window should be set as fullscreen upon creation. /// /// The default is `None`. - pub monitor: Option, + pub fullscreen: FullScreenState, /// The title of the window in the title bar. /// @@ -435,9 +453,9 @@ impl Default for WindowAttributes { dimensions: None, min_dimensions: None, max_dimensions: None, - monitor: None, title: "winit window".to_owned(), maximized: false, + fullscreen: FullScreenState::None, visible: true, transparent: false, decorations: true, diff --git a/src/platform/android/mod.rs b/src/platform/android/mod.rs index 09c9cb14..61a3adb9 100644 --- a/src/platform/android/mod.rs +++ b/src/platform/android/mod.rs @@ -260,6 +260,10 @@ impl Window { pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { unimplemented!(); } + + #[inline] + pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + } } unsafe impl Send for Window {} diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 03e5ae4c..5db5818d 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -97,7 +97,7 @@ pub enum DeviceId { Wayland(wayland::DeviceId) } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum MonitorId { #[doc(hidden)] X(x11::MonitorId), @@ -317,6 +317,14 @@ impl Window2 { &Window2::Wayland(ref _w) => {}, } } + + #[inline] + pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + match self { + &Window2::X(ref w) => w.set_fullscreen_windowed(fullscreen), + &Window2::Wayland(ref _w) => {}, + } + } } unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent) diff --git a/src/platform/linux/wayland/context.rs b/src/platform/linux/wayland/context.rs index 98367bbf..90aad34e 100644 --- a/src/platform/linux/wayland/context.rs +++ b/src/platform/linux/wayland/context.rs @@ -359,6 +359,12 @@ pub struct MonitorId { ctxt: Arc } +impl PartialEq for MonitorId { + fn eq(&self, other: &MonitorId) -> bool { + self.id == other.id + } +} + impl MonitorId { pub fn get_name(&self) -> Option { let mut guard = self.ctxt.evq.lock().unwrap(); diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index b67d77f2..98e56e0e 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -54,7 +54,7 @@ impl Window { *(decorated.handler()) = Some(DecoratedHandler::new()); // set fullscreen if necessary - if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor { + if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.fullscreen.get_monitor() { ctxt.with_output(monitor_id.clone(), |output| { decorated.set_fullscreen(Some(output)) }); diff --git a/src/platform/linux/x11/monitor.rs b/src/platform/linux/x11/monitor.rs index d6479c91..392f0a4f 100644 --- a/src/platform/linux/x11/monitor.rs +++ b/src/platform/linux/x11/monitor.rs @@ -6,6 +6,11 @@ use native_monitor::NativeMonitorId; #[derive(Clone)] pub struct MonitorId(pub Arc, pub u32); +impl PartialEq for MonitorId { + fn eq(&self, other: &MonitorId) -> bool { + self.1 == other.1 + } +} pub fn get_available_monitors(x: &Arc) -> VecDeque { let nb_monitors = unsafe { (x.xlib.XScreenCount)(x.display) }; diff --git a/src/platform/linux/x11/window.rs b/src/platform/linux/x11/window.rs index f7b1e8d1..b588bf33 100644 --- a/src/platform/linux/x11/window.rs +++ b/src/platform/linux/x11/window.rs @@ -11,6 +11,7 @@ use std::time::Duration; use CursorState; use WindowAttributes; +use FullScreenState; use platform::PlatformSpecificWindowBuilderAttributes; use platform::MonitorId as PlatformMonitorId; @@ -128,12 +129,14 @@ impl Window { let screen_id = match pl_attribs.screen_id { Some(id) => id, - None => match window_attrs.monitor { - Some(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32, + None => match window_attrs.fullscreen { + FullScreenState::Exclusive(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32, _ => unsafe { (display.xlib.XDefaultScreen)(display.display) }, } }; + let is_fullscreen = window_attrs.fullscreen.get_monitor().is_some(); + // finding the mode to switch to if necessary let (mode_to_switch_to, xf86_desk_mode) = unsafe { let mut mode_num: libc::c_int = mem::uninitialized(); @@ -142,7 +145,7 @@ impl Window { (None, None) } else { let xf86_desk_mode: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(0)); - let mode_to_switch_to = if window_attrs.monitor.is_some() { + let mode_to_switch_to = if is_fullscreen { let matching_mode = (0 .. mode_num).map(|i| { let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m }).find(|m| m.hdisplay == dimensions.0 as u16 && m.vdisplay == dimensions.1 as u16); @@ -234,6 +237,10 @@ impl Window { Window::set_netwm(display, window, root, "_NET_WM_STATE_MAXIMIZED_VERT", true); } + if window_attrs.fullscreen == FullScreenState::Windowed { + Window::set_netwm(display, window, root, "_NET_WM_STATE_FULLSCREEN", true); + } + // set visibility if window_attrs.visible { unsafe { @@ -261,8 +268,6 @@ impl Window { } } - let is_fullscreen = window_attrs.monitor.is_some(); - if is_fullscreen { Window::set_netwm(display, window, root, "_NET_WM_STATE_FULLSCREEN", true); diff --git a/src/window.rs b/src/window.rs index c81f58ce..a64a7f6e 100644 --- a/src/window.rs +++ b/src/window.rs @@ -7,6 +7,7 @@ use MouseCursor; use Window; use WindowBuilder; use WindowId; +use FullScreenState; use native_monitor::NativeMonitorId; use libc; @@ -59,10 +60,22 @@ impl WindowBuilder { /// Requests fullscreen mode. /// /// If you don't specify dimensions for the window, it will match the monitor's. + /// Disables fullscreen windowed mode if set. #[inline] pub fn with_fullscreen(mut self, monitor: MonitorId) -> WindowBuilder { let MonitorId(monitor) = monitor; - self.window.monitor = Some(monitor); + self.window.fullscreen = FullScreenState::Exclusive(monitor); + self + } + + /// Requests fullscreen windowed mode. + /// + /// Disables the non-windowed fullscreen mode if set + #[inline] + pub fn with_fullscreen_windowed(mut self, fullscreen: bool) -> WindowBuilder { + if fullscreen { + self.window.fullscreen = FullScreenState::Windowed; + } self } @@ -107,8 +120,10 @@ impl WindowBuilder { /// out of memory, etc. pub fn build(mut self, events_loop: &EventsLoop) -> Result { // resizing the window to the dimensions of the monitor when fullscreen - if self.window.dimensions.is_none() && self.window.monitor.is_some() { - self.window.dimensions = Some(self.window.monitor.as_ref().unwrap().get_dimensions()) + if self.window.dimensions.is_none() { + if let Some(monitor) = self.window.fullscreen.get_monitor() { + self.window.dimensions = Some(monitor.get_dimensions()); + } } // default dimensions @@ -305,6 +320,12 @@ impl Window { self.window.set_maximized(maximized) } + /// Sets the window to fullscreen or back + #[inline] + pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + self.window.set_fullscreen_windowed(fullscreen) + } + #[inline] pub fn id(&self) -> WindowId { WindowId(self.window.id()) @@ -362,7 +383,7 @@ pub fn get_primary_monitor() -> MonitorId { } /// Identifier for a monitor. -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub struct MonitorId(platform::MonitorId); impl MonitorId { From eff04394c9664692198a7853e2df92de3a4dbfe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Mon, 28 Aug 2017 01:21:31 +0100 Subject: [PATCH 3/8] Slight maximize/fullscreen X11 cleanup --- src/platform/linux/x11/window.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/platform/linux/x11/window.rs b/src/platform/linux/x11/window.rs index b588bf33..6bf81247 100644 --- a/src/platform/linux/x11/window.rs +++ b/src/platform/linux/x11/window.rs @@ -231,16 +231,6 @@ impl Window { }); } - // set maximization - if window_attrs.maximized { - Window::set_netwm(display, window, root, "_NET_WM_STATE_MAXIMIZED_HORZ", true); - Window::set_netwm(display, window, root, "_NET_WM_STATE_MAXIMIZED_VERT", true); - } - - if window_attrs.fullscreen == FullScreenState::Windowed { - Window::set_netwm(display, window, root, "_NET_WM_STATE_FULLSCREEN", true); - } - // set visibility if window_attrs.visible { unsafe { @@ -357,6 +347,8 @@ impl Window { window.set_title(&window_attrs.title); window.set_decorations(window_attrs.decorations); + window.set_maximized(window_attrs.maximized); + window.set_fullscreen_windowed(window_attrs.fullscreen == FullScreenState::Windowed); if window_attrs.visible { unsafe { From b35c4a5ee51e03882c807db4d5be42808df85501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Mon, 28 Aug 2017 01:43:34 +0100 Subject: [PATCH 4/8] maximized/fullscreen as noops for other platforms --- src/platform/android/mod.rs | 6 +++++- src/platform/ios/mod.rs | 9 ++++++++- src/platform/macos/monitor.rs | 2 +- src/platform/macos/window.rs | 10 +++++++++- src/platform/windows/monitor.rs | 6 ++++++ src/platform/windows/window.rs | 21 +++++++++++++++------ 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/platform/android/mod.rs b/src/platform/android/mod.rs index 61a3adb9..98f6d76b 100644 --- a/src/platform/android/mod.rs +++ b/src/platform/android/mod.rs @@ -24,7 +24,7 @@ pub struct Window { event_rx: Receiver, } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub struct MonitorId; mod ffi; @@ -261,6 +261,10 @@ impl Window { unimplemented!(); } + #[inline] + pub fn set_maximized(&self, maximized: bool) { + } + #[inline] pub fn set_fullscreen_windowed(&self, fullscreen: bool) { } diff --git a/src/platform/ios/mod.rs b/src/platform/ios/mod.rs index 187154c9..716adcb1 100644 --- a/src/platform/ios/mod.rs +++ b/src/platform/ios/mod.rs @@ -94,7 +94,7 @@ use self::ffi::{ static mut jmpbuf: [c_int;27] = [0;27]; -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub struct MonitorId; pub struct Window { @@ -449,6 +449,13 @@ impl Window { WindowProxy } + #[inline] + pub fn set_maximized(&self, maximized: bool) { + } + + #[inline] + pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + } } impl WindowProxy { diff --git a/src/platform/macos/monitor.rs b/src/platform/macos/monitor.rs index 22df205c..fa4f3b65 100644 --- a/src/platform/macos/monitor.rs +++ b/src/platform/macos/monitor.rs @@ -2,7 +2,7 @@ use core_graphics::display; use std::collections::VecDeque; use native_monitor::NativeMonitorId; -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub struct MonitorId(u32); pub fn get_available_monitors() -> VecDeque { diff --git a/src/platform/macos/window.rs b/src/platform/macos/window.rs index c8d8fdfa..a3e2beb2 100644 --- a/src/platform/macos/window.rs +++ b/src/platform/macos/window.rs @@ -383,7 +383,7 @@ impl Window { fn create_window(attrs: &WindowAttributes) -> Option { unsafe { - let screen = match attrs.monitor { + let screen = match attrs.fullscreen.get_monitor() { Some(ref monitor_id) => { let native_id = match monitor_id.get_native_identifier() { NativeMonitorId::Numeric(num) => num, @@ -637,6 +637,14 @@ impl Window { Ok(()) } + + #[inline] + pub fn set_maximized(&self, maximized: bool) { + } + + #[inline] + pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + } } // Convert the `cocoa::base::id` associated with a window to a usize to use as a unique identifier diff --git a/src/platform/windows/monitor.rs b/src/platform/windows/monitor.rs index 297e8261..07094524 100644 --- a/src/platform/windows/monitor.rs +++ b/src/platform/windows/monitor.rs @@ -34,6 +34,12 @@ pub struct MonitorId { dimensions: (u32, u32), } +impl PartialEq for MonitorId { + fn eq(&self, other: &MonitorId) -> bool { + self.monitor_name == other.monitor_name + } +} + struct DeviceEnumerator { parent_device: *const winapi::WCHAR, current_index: u32, diff --git a/src/platform/windows/window.rs b/src/platform/windows/window.rs index d737a36b..65373323 100644 --- a/src/platform/windows/window.rs +++ b/src/platform/windows/window.rs @@ -276,6 +276,14 @@ impl Window { pub fn id(&self) -> WindowId { WindowId(self.window.0) } + + #[inline] + pub fn set_maximized(&self, maximized: bool) { + } + + #[inline] + pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + } } impl Drop for Window { @@ -319,13 +327,14 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild // switching to fullscreen if necessary // this means adjusting the window's position so that it overlaps the right monitor, // and change the monitor's resolution if necessary - if window.monitor.is_some() { - let monitor = window.monitor.as_ref().unwrap(); + if let Some(ref monitor) = window.fullscreen.get_monitor() { try!(switch_to_fullscreen(&mut rect, monitor)); } + let fullscreen = window.fullscreen.get_monitor().is_some(); + // computing the style and extended style of the window - let (ex_style, style) = if window.monitor.is_some() || !window.decorations { + let (ex_style, style) = if fullscreen || !window.decorations { (winapi::WS_EX_APPWINDOW, //winapi::WS_POPUP is incompatible with winapi::WS_CHILD if pl_attribs.parent.is_some() { @@ -345,13 +354,13 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild // creating the real window this time, by using the functions in `extra_functions` let real_window = { - let (width, height) = if window.monitor.is_some() || window.dimensions.is_some() { + let (width, height) = if fullscreen || window.dimensions.is_some() { (Some(rect.right - rect.left), Some(rect.bottom - rect.top)) } else { (None, None) }; - let (x, y) = if window.monitor.is_some() { + let (x, y) = if fullscreen { (Some(rect.left), Some(rect.top)) } else { (None, None) @@ -425,7 +434,7 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild } // calling SetForegroundWindow if fullscreen - if window.monitor.is_some() { + if fullscreen { user32::SetForegroundWindow(real_window.0); } From 1382adbf114086930cf7aed5558e8c5443f22b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Tue, 29 Aug 2017 01:36:24 +0100 Subject: [PATCH 5/8] Unify fullscreen and fullscreen_windowed APIs Use the enum to make a single fullscreen API that's much more consistent. Both set_fullscreen() and with_fullscreen() take the same enum and support all the variations so you can build the window however you want and switch between the modes at runtime. --- src/lib.rs | 6 +- src/platform/linux/mod.rs | 6 +- src/platform/linux/x11/window.rs | 267 ++++++++++++++++++------------- src/window.rs | 25 +-- 4 files changed, 170 insertions(+), 134 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bb72c979..cf605faf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -357,17 +357,17 @@ pub enum MouseCursor { } /// Describes if the Window is in one of the fullscreen modes -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub enum FullScreenState { None, Windowed, - Exclusive(platform::MonitorId), + Exclusive(MonitorId), } impl FullScreenState { pub fn get_monitor(&self) -> Option { if let FullScreenState::Exclusive(ref monitor) = *self { - Some(monitor.clone()) + Some(monitor.0.clone()) } else { None } diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 5db5818d..3cb2c814 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -4,7 +4,7 @@ use std::collections::VecDeque; use std::sync::Arc; use std::env; -use {CreationError, CursorState, EventsLoopClosed, MouseCursor, ControlFlow}; +use {CreationError, CursorState, EventsLoopClosed, MouseCursor, ControlFlow, FullScreenState}; use libc; use self::x11::XConnection; @@ -319,9 +319,9 @@ impl Window2 { } #[inline] - pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + pub fn set_fullscreen(&self, state: FullScreenState) { match self { - &Window2::X(ref w) => w.set_fullscreen_windowed(fullscreen), + &Window2::X(ref w) => w.set_fullscreen(state), &Window2::Wayland(ref _w) => {}, } } diff --git a/src/platform/linux/x11/window.rs b/src/platform/linux/x11/window.rs index 6bf81247..36366879 100644 --- a/src/platform/linux/x11/window.rs +++ b/src/platform/linux/x11/window.rs @@ -15,9 +15,12 @@ use FullScreenState; use platform::PlatformSpecificWindowBuilderAttributes; use platform::MonitorId as PlatformMonitorId; +use window::MonitorId as RootMonitorId; use super::{ffi}; -use super::{MonitorId, XConnection, WindowId, EventsLoop}; +use super::{XConnection, WindowId, EventsLoop}; + +use super::MonitorId as X11MonitorId; // TODO: remove me fn with_c_str(s: &str, f: F) -> T where F: FnOnce(*const libc::c_char) -> T { @@ -37,9 +40,8 @@ pub struct XWindow { display: Arc, window: ffi::Window, root: ffi::Window, - is_fullscreen: bool, - screen_id: libc::c_int, - xf86_desk_mode: Option, + // screen we're using, original screen mode if we've switched + fullscreen: Arc)>>, window_proxy_data: Arc>>, } @@ -49,22 +51,105 @@ unsafe impl Sync for XWindow {} unsafe impl Send for Window {} unsafe impl Sync for Window {} +impl XWindow { + fn switch_to_fullscreen_mode(&self, monitor: i32, width: u16, height: u16) { + let original_monitor = { + let fullscreen = self.fullscreen.lock().unwrap(); + fullscreen.0 + }; + if monitor != original_monitor { + // We're setting fullscreen on a new screen so first revert the original screen + self.switch_from_fullscreen_mode(); + } + + let current_mode = unsafe { + let mut mode_num: libc::c_int = mem::uninitialized(); + let mut modes: *mut *mut ffi::XF86VidModeModeInfo = mem::uninitialized(); + if (self.display.xf86vmode.XF86VidModeGetAllModeLines)(self.display.display, monitor, &mut mode_num, &mut modes) == 0 { + eprintln!("[winit] Couldn't get current resolution mode"); + return + } + ptr::read(*modes.offset(0)) + }; + + let new_mode = unsafe { + let mut mode_num: libc::c_int = mem::uninitialized(); + let mut modes: *mut *mut ffi::XF86VidModeModeInfo = mem::uninitialized(); + if (self.display.xf86vmode.XF86VidModeGetAllModeLines)(self.display.display, monitor, &mut mode_num, &mut modes) == 0 { + // There are no modes, mighty weird + eprintln!("[winit] X has no valid modes"); + return + } else { + let matching_mode = (0 .. mode_num).map(|i| { + let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m + }).find(|m| m.hdisplay == width && m.vdisplay == height); + + if let Some(matching_mode) = matching_mode { + matching_mode + } else { + let m = (0 .. mode_num).map(|i| { + let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m + }).find(|m| m.hdisplay >= width && m.vdisplay >= height); + + match m { + Some(m) => m, + None => { + eprintln!("[winit] Could not find a suitable graphics mode"); + return + } + } + } + } + }; + + if new_mode != current_mode { + // We actually need to change modes + self.set_mode(monitor, new_mode); + let mut fullscreen = self.fullscreen.lock().unwrap(); + if fullscreen.1.is_none() { + // It's our first mode switch, save the original mode + fullscreen.1 = Some(current_mode); + } + } + } + + fn switch_from_fullscreen_mode(&self) { + let (monitor, mode) = { + let fullscreen = self.fullscreen.lock().unwrap(); + (fullscreen.0, fullscreen.1) + }; + + if let Some(mode) = mode { + self.set_mode(monitor, mode); + let mut fullscreen = self.fullscreen.lock().unwrap(); + fullscreen.1 = None; + } + } + + pub fn set_mode(&self, monitor: i32, mode: ffi::XF86VidModeModeInfo) { + unsafe { + let mut mode_to_switch_to = mode; + (self.display.xf86vmode.XF86VidModeSwitchToMode)( + self.display.display, + monitor, + &mut mode_to_switch_to + ); + self.display.check_errors().expect("Failed to call XF86VidModeSwitchToMode"); + + (self.display.xf86vmode.XF86VidModeSetViewPort)(self.display.display, monitor, 0, 0); + self.display.check_errors().expect("Failed to call XF86VidModeSetViewPort"); + } + } +} + impl Drop for XWindow { fn drop(&mut self) { - unsafe { - // Clear out the window proxy data arc, so that any window proxy objects - // are no longer able to send messages to this window. - *self.window_proxy_data.lock().unwrap() = None; + // Clear out the window proxy data arc, so that any window proxy objects + // are no longer able to send messages to this window. + *self.window_proxy_data.lock().unwrap() = None; - if self.is_fullscreen { - if let Some(mut xf86_desk_mode) = self.xf86_desk_mode { - (self.display.xf86vmode.XF86VidModeSwitchToMode)(self.display.display, self.screen_id, &mut xf86_desk_mode); - } - (self.display.xf86vmode.XF86VidModeSetViewPort)(self.display.display, self.screen_id, 0, 0); - } - - (self.display.xlib.XDestroyWindow)(self.display.display, self.window); - } + // Make sure we return the display to the original resolution if we've changed it + self.switch_from_fullscreen_mode(); } } @@ -130,45 +215,11 @@ impl Window { let screen_id = match pl_attribs.screen_id { Some(id) => id, None => match window_attrs.fullscreen { - FullScreenState::Exclusive(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32, + FullScreenState::Exclusive(RootMonitorId(PlatformMonitorId::X(X11MonitorId(_, monitor)))) => monitor as i32, _ => unsafe { (display.xlib.XDefaultScreen)(display.display) }, } }; - let is_fullscreen = window_attrs.fullscreen.get_monitor().is_some(); - - // finding the mode to switch to if necessary - let (mode_to_switch_to, xf86_desk_mode) = unsafe { - let mut mode_num: libc::c_int = mem::uninitialized(); - let mut modes: *mut *mut ffi::XF86VidModeModeInfo = mem::uninitialized(); - if (display.xf86vmode.XF86VidModeGetAllModeLines)(display.display, screen_id, &mut mode_num, &mut modes) == 0 { - (None, None) - } else { - let xf86_desk_mode: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(0)); - let mode_to_switch_to = if is_fullscreen { - let matching_mode = (0 .. mode_num).map(|i| { - let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m - }).find(|m| m.hdisplay == dimensions.0 as u16 && m.vdisplay == dimensions.1 as u16); - if let Some(matching_mode) = matching_mode { - Some(matching_mode) - } else { - let m = (0 .. mode_num).map(|i| { - let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m - }).find(|m| m.hdisplay >= dimensions.0 as u16 && m.vdisplay >= dimensions.1 as u16); - - match m { - Some(m) => Some(m), - None => return Err(OsError(format!("Could not find a suitable graphics mode"))) - } - } - } else { - None - }; - (display.xlib.XFree)(modes as *mut _); - (mode_to_switch_to, Some(xf86_desk_mode)) - } - }; - // getting the root window let root = ctx.root; @@ -258,52 +309,24 @@ impl Window { } } - if is_fullscreen { - Window::set_netwm(display, window, root, "_NET_WM_STATE_FULLSCREEN", true); - - if let Some(mut mode_to_switch_to) = mode_to_switch_to { - unsafe { - (display.xf86vmode.XF86VidModeSwitchToMode)( - display.display, - screen_id, - &mut mode_to_switch_to - ); - display.check_errors().expect("Failed to call XF86VidModeSwitchToMode"); - } - } - else { - println!("[glutin] Unexpected state: `mode` is None creating fullscreen window"); - } - unsafe { - (display.xf86vmode.XF86VidModeSetViewPort)(display.display, screen_id, 0, 0); - display.check_errors().expect("Failed to call XF86VidModeSetViewPort"); - } - - } else { - - // set size hints - let mut size_hints: ffi::XSizeHints = unsafe { mem::zeroed() }; - size_hints.flags = ffi::PSize; - size_hints.width = dimensions.0 as i32; - size_hints.height = dimensions.1 as i32; - - if let Some(dimensions) = window_attrs.min_dimensions { - size_hints.flags |= ffi::PMinSize; - size_hints.min_width = dimensions.0 as i32; - size_hints.min_height = dimensions.1 as i32; - } - - if let Some(dimensions) = window_attrs.max_dimensions { - size_hints.flags |= ffi::PMaxSize; - size_hints.max_width = dimensions.0 as i32; - size_hints.max_height = dimensions.1 as i32; - } - - unsafe { - (display.xlib.XSetNormalHints)(display.display, window, &mut size_hints); - display.check_errors().expect("Failed to call XSetNormalHints"); - } - + // set size hints + let mut size_hints: ffi::XSizeHints = unsafe { mem::zeroed() }; + size_hints.flags = ffi::PSize; + size_hints.width = dimensions.0 as i32; + size_hints.height = dimensions.1 as i32; + if let Some(dimensions) = window_attrs.min_dimensions { + size_hints.flags |= ffi::PMinSize; + size_hints.min_width = dimensions.0 as i32; + size_hints.min_height = dimensions.1 as i32; + } + if let Some(dimensions) = window_attrs.max_dimensions { + size_hints.flags |= ffi::PMaxSize; + size_hints.max_width = dimensions.0 as i32; + size_hints.max_height = dimensions.1 as i32; + } + unsafe { + (display.xlib.XSetNormalHints)(display.display, window, &mut size_hints); + display.check_errors().expect("Failed to call XSetNormalHints"); } // Select XInput2 events @@ -337,9 +360,7 @@ impl Window { display: display.clone(), window: window, root: root, - screen_id: screen_id, - is_fullscreen: is_fullscreen, - xf86_desk_mode: xf86_desk_mode, + fullscreen: Arc::new(Mutex::new((screen_id, None))), window_proxy_data: window_proxy_data, }), cursor_state: Mutex::new(CursorState::Normal), @@ -348,7 +369,7 @@ impl Window { window.set_title(&window_attrs.title); window.set_decorations(window_attrs.decorations); window.set_maximized(window_attrs.maximized); - window.set_fullscreen_windowed(window_attrs.fullscreen == FullScreenState::Windowed); + window.set_fullscreen(window_attrs.fullscreen.clone()); if window_attrs.visible { unsafe { @@ -427,8 +448,26 @@ impl Window { } } - pub fn set_fullscreen_windowed(&self, fullscreen: bool) { - Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", fullscreen); + pub fn set_fullscreen(&self, state: FullScreenState) { + match state { + FullScreenState::None => { + self.x.switch_from_fullscreen_mode(); + Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", false); + }, + FullScreenState::Windowed => { + self.x.switch_from_fullscreen_mode(); + Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", true); + }, + FullScreenState::Exclusive(RootMonitorId(PlatformMonitorId::X(X11MonitorId(_, monitor)))) => { + if let Some(dimensions) = self.get_inner_size() { + self.x.switch_to_fullscreen_mode(monitor as i32, dimensions.0 as u16, dimensions.1 as u16); + Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", true); + } else { + eprintln!("[winit] Couldn't get window dimensions to go fullscreen"); + } + } + _ => (), + } } pub fn set_maximized(&self, maximized: bool) { @@ -581,7 +620,12 @@ impl Window { #[inline] pub fn get_xlib_screen_id(&self) -> *mut libc::c_void { - self.x.screen_id as *mut libc::c_void + let screen_id = { + let fullscreen = self.x.fullscreen.lock().unwrap(); + fullscreen.0 + }; + + screen_id as *mut libc::c_void } #[inline] @@ -792,11 +836,16 @@ impl Window { } pub fn hidpi_factor(&self) -> f32 { + let screen_id = { + let fullscreen = self.x.fullscreen.lock().unwrap(); + fullscreen.0 + }; + unsafe { - let x_px = (self.x.display.xlib.XDisplayWidth)(self.x.display.display, self.x.screen_id); - let y_px = (self.x.display.xlib.XDisplayHeight)(self.x.display.display, self.x.screen_id); - let x_mm = (self.x.display.xlib.XDisplayWidthMM)(self.x.display.display, self.x.screen_id); - let y_mm = (self.x.display.xlib.XDisplayHeightMM)(self.x.display.display, self.x.screen_id); + let x_px = (self.x.display.xlib.XDisplayWidth)(self.x.display.display, screen_id); + let y_px = (self.x.display.xlib.XDisplayHeight)(self.x.display.display, screen_id); + let x_mm = (self.x.display.xlib.XDisplayWidthMM)(self.x.display.display, screen_id); + let y_mm = (self.x.display.xlib.XDisplayHeightMM)(self.x.display.display, screen_id); let ppmm = ((x_px as f32 * y_px as f32) / (x_mm as f32 * y_mm as f32)).sqrt(); ((ppmm * (12.0 * 25.4 / 96.0)).round() / 12.0).max(1.0) // quantize with 1/12 step size. } diff --git a/src/window.rs b/src/window.rs index a64a7f6e..36b94859 100644 --- a/src/window.rs +++ b/src/window.rs @@ -57,25 +57,12 @@ impl WindowBuilder { self } - /// Requests fullscreen mode. + /// Sets the fullscreen mode. /// /// If you don't specify dimensions for the window, it will match the monitor's. - /// Disables fullscreen windowed mode if set. #[inline] - pub fn with_fullscreen(mut self, monitor: MonitorId) -> WindowBuilder { - let MonitorId(monitor) = monitor; - self.window.fullscreen = FullScreenState::Exclusive(monitor); - self - } - - /// Requests fullscreen windowed mode. - /// - /// Disables the non-windowed fullscreen mode if set - #[inline] - pub fn with_fullscreen_windowed(mut self, fullscreen: bool) -> WindowBuilder { - if fullscreen { - self.window.fullscreen = FullScreenState::Windowed; - } + pub fn with_fullscreen(mut self, state: FullScreenState) -> WindowBuilder { + self.window.fullscreen = state; self } @@ -322,8 +309,8 @@ impl Window { /// Sets the window to fullscreen or back #[inline] - pub fn set_fullscreen_windowed(&self, fullscreen: bool) { - self.window.set_fullscreen_windowed(fullscreen) + pub fn set_fullscreen(&self, state: FullScreenState) { + self.window.set_fullscreen(state) } #[inline] @@ -384,7 +371,7 @@ pub fn get_primary_monitor() -> MonitorId { /// Identifier for a monitor. #[derive(Clone, PartialEq)] -pub struct MonitorId(platform::MonitorId); +pub struct MonitorId(pub platform::MonitorId); impl MonitorId { /// Returns a human-readable name of the monitor. From 9693f7caa9b21d55da8f2b04171e3b64c92fe748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Tue, 29 Aug 2017 01:46:03 +0100 Subject: [PATCH 6/8] Convert new fullscreen API in all platforms --- src/platform/android/mod.rs | 5 +++-- src/platform/ios/mod.rs | 6 +++--- src/platform/linux/mod.rs | 2 +- src/platform/linux/wayland/context.rs | 6 ------ src/platform/linux/x11/monitor.rs | 5 ----- src/platform/macos/monitor.rs | 2 +- src/platform/macos/window.rs | 3 ++- src/platform/windows/monitor.rs | 6 ------ src/platform/windows/window.rs | 5 +++-- src/window.rs | 2 +- 10 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/platform/android/mod.rs b/src/platform/android/mod.rs index 98f6d76b..ec08713d 100644 --- a/src/platform/android/mod.rs +++ b/src/platform/android/mod.rs @@ -15,6 +15,7 @@ use std::collections::VecDeque; use CursorState; use WindowAttributes; +use FullScreenState; use native_monitor::NativeMonitorId; gen_api_transition!(); @@ -24,7 +25,7 @@ pub struct Window { event_rx: Receiver, } -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub struct MonitorId; mod ffi; @@ -266,7 +267,7 @@ impl Window { } #[inline] - pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + pub fn set_fullscreen(&self, state: FullScreenState) { } } diff --git a/src/platform/ios/mod.rs b/src/platform/ios/mod.rs index 716adcb1..5235451f 100644 --- a/src/platform/ios/mod.rs +++ b/src/platform/ios/mod.rs @@ -71,7 +71,7 @@ use objc::runtime::{Class, Object, Sel, BOOL, YES }; use objc::declare::{ ClassDecl }; use native_monitor::NativeMonitorId; -use { CreationError, CursorState, MouseCursor, WindowAttributes }; +use { CreationError, CursorState, MouseCursor, WindowAttributes, FullScreenState }; use WindowEvent as Event; use events::{ Touch, TouchPhase }; @@ -94,7 +94,7 @@ use self::ffi::{ static mut jmpbuf: [c_int;27] = [0;27]; -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub struct MonitorId; pub struct Window { @@ -454,7 +454,7 @@ impl Window { } #[inline] - pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + pub fn set_fullscreen(&self, state: FullScreenState) { } } diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 3cb2c814..a88d7f81 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -97,7 +97,7 @@ pub enum DeviceId { Wayland(wayland::DeviceId) } -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub enum MonitorId { #[doc(hidden)] X(x11::MonitorId), diff --git a/src/platform/linux/wayland/context.rs b/src/platform/linux/wayland/context.rs index 90aad34e..98367bbf 100644 --- a/src/platform/linux/wayland/context.rs +++ b/src/platform/linux/wayland/context.rs @@ -359,12 +359,6 @@ pub struct MonitorId { ctxt: Arc } -impl PartialEq for MonitorId { - fn eq(&self, other: &MonitorId) -> bool { - self.id == other.id - } -} - impl MonitorId { pub fn get_name(&self) -> Option { let mut guard = self.ctxt.evq.lock().unwrap(); diff --git a/src/platform/linux/x11/monitor.rs b/src/platform/linux/x11/monitor.rs index 392f0a4f..d6479c91 100644 --- a/src/platform/linux/x11/monitor.rs +++ b/src/platform/linux/x11/monitor.rs @@ -6,11 +6,6 @@ use native_monitor::NativeMonitorId; #[derive(Clone)] pub struct MonitorId(pub Arc, pub u32); -impl PartialEq for MonitorId { - fn eq(&self, other: &MonitorId) -> bool { - self.1 == other.1 - } -} pub fn get_available_monitors(x: &Arc) -> VecDeque { let nb_monitors = unsafe { (x.xlib.XScreenCount)(x.display) }; diff --git a/src/platform/macos/monitor.rs b/src/platform/macos/monitor.rs index fa4f3b65..22df205c 100644 --- a/src/platform/macos/monitor.rs +++ b/src/platform/macos/monitor.rs @@ -2,7 +2,7 @@ use core_graphics::display; use std::collections::VecDeque; use native_monitor::NativeMonitorId; -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub struct MonitorId(u32); pub fn get_available_monitors() -> VecDeque { diff --git a/src/platform/macos/window.rs b/src/platform/macos/window.rs index a3e2beb2..f6131d43 100644 --- a/src/platform/macos/window.rs +++ b/src/platform/macos/window.rs @@ -3,6 +3,7 @@ use CreationError::OsError; use libc; use WindowAttributes; +use FullScreenState; use native_monitor::NativeMonitorId; use os::macos::ActivationPolicy; use os::macos::WindowExt; @@ -643,7 +644,7 @@ impl Window { } #[inline] - pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + pub fn set_fullscreen(&self, state: FullScreenState) { } } diff --git a/src/platform/windows/monitor.rs b/src/platform/windows/monitor.rs index 07094524..297e8261 100644 --- a/src/platform/windows/monitor.rs +++ b/src/platform/windows/monitor.rs @@ -34,12 +34,6 @@ pub struct MonitorId { dimensions: (u32, u32), } -impl PartialEq for MonitorId { - fn eq(&self, other: &MonitorId) -> bool { - self.monitor_name == other.monitor_name - } -} - struct DeviceEnumerator { parent_device: *const winapi::WCHAR, current_index: u32, diff --git a/src/platform/windows/window.rs b/src/platform/windows/window.rs index 65373323..89221ade 100644 --- a/src/platform/windows/window.rs +++ b/src/platform/windows/window.rs @@ -20,6 +20,7 @@ use CreationError; use CursorState; use MouseCursor; use WindowAttributes; +use FullScreenState; use dwmapi; use kernel32; @@ -282,7 +283,7 @@ impl Window { } #[inline] - pub fn set_fullscreen_windowed(&self, fullscreen: bool) { + pub fn set_fullscreen(&self, state: FullScreenState) { } } @@ -329,7 +330,7 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild // and change the monitor's resolution if necessary if let Some(ref monitor) = window.fullscreen.get_monitor() { try!(switch_to_fullscreen(&mut rect, monitor)); - } + }; let fullscreen = window.fullscreen.get_monitor().is_some(); diff --git a/src/window.rs b/src/window.rs index 36b94859..19ebc753 100644 --- a/src/window.rs +++ b/src/window.rs @@ -370,7 +370,7 @@ pub fn get_primary_monitor() -> MonitorId { } /// Identifier for a monitor. -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub struct MonitorId(pub platform::MonitorId); impl MonitorId { From b3ef9c8b22d600877c6cf62247e75718b2abe70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Tue, 29 Aug 2017 01:50:11 +0100 Subject: [PATCH 7/8] Use new fullscreen API in example --- examples/fullscreen.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index daeb68b6..2da143d1 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -1,7 +1,7 @@ extern crate winit; use std::io::{self, Write}; -use winit::{ControlFlow, Event, WindowEvent}; +use winit::{ControlFlow, Event, WindowEvent, FullScreenState}; fn main() { // enumerating monitors @@ -27,7 +27,7 @@ fn main() { let _window = winit::WindowBuilder::new() .with_title("Hello world!") - .with_fullscreen(monitor) + .with_fullscreen(FullScreenState::Exclusive(monitor)) .build(&events_loop) .unwrap(); From 60b575a7c1aac2b8edcdb3d1a1d23626c2597813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Tue, 29 Aug 2017 02:08:12 +0100 Subject: [PATCH 8/8] Get rid of FullScreenState::get_monitor() --- src/lib.rs | 10 ---------- src/platform/linux/wayland/window.rs | 6 ++++-- src/platform/macos/window.rs | 6 +++--- src/platform/windows/window.rs | 8 +++++--- src/window.rs | 2 +- 5 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cf605faf..2ca8e9fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -364,16 +364,6 @@ pub enum FullScreenState { Exclusive(MonitorId), } -impl FullScreenState { - pub fn get_monitor(&self) -> Option { - if let FullScreenState::Exclusive(ref monitor) = *self { - Some(monitor.0.clone()) - } else { - None - } - } -} - /// Describes how winit handles the cursor. #[derive(Debug, Copy, Clone, PartialEq)] pub enum CursorState { diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index 98e56e0e..95ea44a8 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -4,8 +4,10 @@ use std::sync::atomic::AtomicBool; use wayland_client::{EventQueue, EventQueueHandle, Proxy}; use wayland_client::protocol::{wl_display,wl_surface}; -use {CreationError, MouseCursor, CursorState, WindowAttributes}; +use {CreationError, MouseCursor, CursorState, WindowAttributes, FullScreenState}; use platform::MonitorId as PlatformMonitorId; +use window::MonitorId as RootMonitorId; +use super::context::MonitorId as WaylandMonitorId; use super::{WaylandContext, EventsLoop}; use super::wayland_window; @@ -54,7 +56,7 @@ impl Window { *(decorated.handler()) = Some(DecoratedHandler::new()); // set fullscreen if necessary - if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.fullscreen.get_monitor() { + if let FullScreenState::Exclusive(RootMonitorId(PlatformMonitorId::Wayland(ref monitor_id))) = attributes.fullscreen { ctxt.with_output(monitor_id.clone(), |output| { decorated.set_fullscreen(Some(output)) }); diff --git a/src/platform/macos/window.rs b/src/platform/macos/window.rs index f6131d43..98c64d77 100644 --- a/src/platform/macos/window.rs +++ b/src/platform/macos/window.rs @@ -384,8 +384,8 @@ impl Window { fn create_window(attrs: &WindowAttributes) -> Option { unsafe { - let screen = match attrs.fullscreen.get_monitor() { - Some(ref monitor_id) => { + let screen = match attrs.fullscreen { + FullScreenState::Exclusive(ref monitor_id) => { let native_id = match monitor_id.get_native_identifier() { NativeMonitorId::Numeric(num) => num, _ => panic!("OS X monitors should always have a numeric native ID") @@ -411,7 +411,7 @@ impl Window { }; Some(matching_screen.unwrap_or(appkit::NSScreen::mainScreen(nil))) }, - None => None + _ => None, }; let frame = match screen { Some(screen) => appkit::NSScreen::frame(screen), diff --git a/src/platform/windows/window.rs b/src/platform/windows/window.rs index 89221ade..e98f6a8b 100644 --- a/src/platform/windows/window.rs +++ b/src/platform/windows/window.rs @@ -21,6 +21,7 @@ use CursorState; use MouseCursor; use WindowAttributes; use FullScreenState; +use MonitorId as RootMonitorId; use dwmapi; use kernel32; @@ -328,12 +329,13 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild // switching to fullscreen if necessary // this means adjusting the window's position so that it overlaps the right monitor, // and change the monitor's resolution if necessary - if let Some(ref monitor) = window.fullscreen.get_monitor() { + let fullscreen = if let FullScreenState::Exclusive(RootMonitorId(ref monitor)) = window.fullscreen { try!(switch_to_fullscreen(&mut rect, monitor)); + true + } else { + false }; - let fullscreen = window.fullscreen.get_monitor().is_some(); - // computing the style and extended style of the window let (ex_style, style) = if fullscreen || !window.decorations { (winapi::WS_EX_APPWINDOW, diff --git a/src/window.rs b/src/window.rs index 19ebc753..7e046e22 100644 --- a/src/window.rs +++ b/src/window.rs @@ -108,7 +108,7 @@ impl WindowBuilder { pub fn build(mut self, events_loop: &EventsLoop) -> Result { // resizing the window to the dimensions of the monitor when fullscreen if self.window.dimensions.is_none() { - if let Some(monitor) = self.window.fullscreen.get_monitor() { + if let FullScreenState::Exclusive(ref monitor) = self.window.fullscreen { self.window.dimensions = Some(monitor.get_dimensions()); } }