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(); diff --git a/src/lib.rs b/src/lib.rs index 89e37f1f..2ca8e9fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -356,6 +356,14 @@ pub enum MouseCursor { RowResize, } +/// Describes if the Window is in one of the fullscreen modes +#[derive(Clone)] +pub enum FullScreenState { + None, + Windowed, + Exclusive(MonitorId), +} + /// Describes how winit handles the cursor. #[derive(Debug, Copy, Clone, PartialEq)] pub enum CursorState { @@ -392,16 +400,21 @@ 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. /// /// 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`. @@ -430,8 +443,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..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!(); @@ -260,6 +261,14 @@ impl Window { pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { unimplemented!(); } + + #[inline] + pub fn set_maximized(&self, maximized: bool) { + } + + #[inline] + pub fn set_fullscreen(&self, state: FullScreenState) { + } } unsafe impl Send for Window {} diff --git a/src/platform/ios/mod.rs b/src/platform/ios/mod.rs index 187154c9..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 }; @@ -449,6 +449,13 @@ impl Window { WindowProxy } + #[inline] + pub fn set_maximized(&self, maximized: bool) { + } + + #[inline] + pub fn set_fullscreen(&self, state: FullScreenState) { + } } impl WindowProxy { diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index af431a10..a88d7f81 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; @@ -309,6 +309,22 @@ 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) => {}, + } + } + + #[inline] + pub fn set_fullscreen(&self, state: FullScreenState) { + match self { + &Window2::X(ref w) => w.set_fullscreen(state), + &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/window.rs b/src/platform/linux/wayland/window.rs index b67d77f2..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.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/linux/x11/window.rs b/src/platform/linux/x11/window.rs index 7e2ddfe1..36366879 100644 --- a/src/platform/linux/x11/window.rs +++ b/src/platform/linux/x11/window.rs @@ -11,12 +11,16 @@ use std::time::Duration; use CursorState; use WindowAttributes; +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 { @@ -35,9 +39,9 @@ unsafe impl Send for WindowProxyData {} pub struct XWindow { display: Arc, window: ffi::Window, - is_fullscreen: bool, - screen_id: libc::c_int, - xf86_desk_mode: Option, + root: ffi::Window, + // screen we're using, original screen mode if we've switched + fullscreen: Arc)>>, window_proxy_data: Arc>>, } @@ -47,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(); } } @@ -127,44 +214,12 @@ 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(RootMonitorId(PlatformMonitorId::X(X11MonitorId(_, monitor)))) => monitor as i32, _ => unsafe { (display.xlib.XDefaultScreen)(display.display) }, } }; - // 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 window_attrs.monitor.is_some() { - 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; @@ -254,95 +309,24 @@ 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"); - } - - 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 @@ -375,9 +359,8 @@ impl Window { x: Arc::new(XWindow { display: display.clone(), window: window, - screen_id: screen_id, - is_fullscreen: is_fullscreen, - xf86_desk_mode: xf86_desk_mode, + root: root, + fullscreen: Arc::new(Mutex::new((screen_id, None))), window_proxy_data: window_proxy_data, }), cursor_state: Mutex::new(CursorState::Normal), @@ -385,6 +368,8 @@ impl Window { window.set_title(&window_attrs.title); window.set_decorations(window_attrs.decorations); + window.set_maximized(window_attrs.maximized); + window.set_fullscreen(window_attrs.fullscreen.clone()); if window_attrs.visible { unsafe { @@ -418,6 +403,78 @@ 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(&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) { + 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) @@ -563,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] @@ -774,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/platform/macos/window.rs b/src/platform/macos/window.rs index c8d8fdfa..98c64d77 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; @@ -383,8 +384,8 @@ impl Window { fn create_window(attrs: &WindowAttributes) -> Option { unsafe { - let screen = match attrs.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") @@ -410,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), @@ -637,6 +638,14 @@ impl Window { Ok(()) } + + #[inline] + pub fn set_maximized(&self, maximized: bool) { + } + + #[inline] + pub fn set_fullscreen(&self, state: FullScreenState) { + } } // Convert the `cocoa::base::id` associated with a window to a usize to use as a unique identifier diff --git a/src/platform/windows/window.rs b/src/platform/windows/window.rs index d737a36b..e98f6a8b 100644 --- a/src/platform/windows/window.rs +++ b/src/platform/windows/window.rs @@ -20,6 +20,8 @@ use CreationError; use CursorState; use MouseCursor; use WindowAttributes; +use FullScreenState; +use MonitorId as RootMonitorId; use dwmapi; use kernel32; @@ -276,6 +278,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(&self, state: FullScreenState) { + } } impl Drop for Window { @@ -319,13 +329,15 @@ 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(); + let fullscreen = if let FullScreenState::Exclusive(RootMonitorId(ref monitor)) = window.fullscreen { try!(switch_to_fullscreen(&mut rect, monitor)); - } + true + } else { + false + }; // 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 +357,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 +437,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); } diff --git a/src/window.rs b/src/window.rs index c499eaf6..7e046e22 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; @@ -56,13 +57,19 @@ 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. #[inline] - pub fn with_fullscreen(mut self, monitor: MonitorId) -> WindowBuilder { - let MonitorId(monitor) = monitor; - self.window.monitor = Some(monitor); + pub fn with_fullscreen(mut self, state: FullScreenState) -> WindowBuilder { + self.window.fullscreen = state; + self + } + + /// Requests maximized mode. + #[inline] + pub fn with_maximized(mut self, maximized: bool) -> WindowBuilder { + self.window.maximized = maximized; self } @@ -100,8 +107,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 FullScreenState::Exclusive(ref monitor) = self.window.fullscreen { + self.window.dimensions = Some(monitor.get_dimensions()); + } } // default dimensions @@ -292,6 +301,18 @@ 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) + } + + /// Sets the window to fullscreen or back + #[inline] + pub fn set_fullscreen(&self, state: FullScreenState) { + self.window.set_fullscreen(state) + } + #[inline] pub fn id(&self) -> WindowId { WindowId(self.window.id()) @@ -350,7 +371,7 @@ pub fn get_primary_monitor() -> MonitorId { /// Identifier for a monitor. #[derive(Clone)] -pub struct MonitorId(platform::MonitorId); +pub struct MonitorId(pub platform::MonitorId); impl MonitorId { /// Returns a human-readable name of the monitor.