From 71e3d254226b47d8cbdb1d9432f11e4cdc659a46 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 22 Sep 2020 04:54:47 +0300 Subject: [PATCH] Rework 'Fullscreen::Borderless' enum variant This changes 'Fullscreen::Borderless' enum variant from 'Fullscreen::Borderless(MonitorHandle)' to 'Fullscreen::Borderless(Option)'. Providing 'None' to it will result in picking the current monitor. --- CHANGELOG.md | 1 + examples/fullscreen.rs | 2 +- examples/multithreaded.rs | 4 +- examples/window_debug.rs | 10 ++++- src/platform_impl/ios/view.rs | 10 ++++- src/platform_impl/ios/window.rs | 12 ++++-- src/platform_impl/linux/wayland/window.rs | 45 +++++++++++++--------- src/platform_impl/linux/x11/window.rs | 9 +++-- src/platform_impl/macos/window.rs | 12 ++++-- src/platform_impl/macos/window_delegate.rs | 2 +- src/platform_impl/web/window.rs | 2 +- src/platform_impl/windows/event_loop.rs | 11 ++++-- src/platform_impl/windows/window.rs | 9 +++-- src/window.rs | 6 ++- 14 files changed, 89 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc065828..41362067 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ - On Web, the event handler closure passed to `EventLoop::run` now gets dropped after the event loop is destroyed. - **Breaking:** On Web, the canvas element associated to a `Window` is no longer removed from the DOM when the `Window` is dropped. - On Web, `WindowEvent::Resized` is now emitted when `Window::set_inner_size` is called. +- **Breaking:** `Fullscreen` enum now uses `Borderless(Option)` instead of `Borderless(MonitorHandle)` to allow picking the current monitor. # 0.22.2 (2020-05-16) diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 3c5ed185..4ed157f0 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -19,7 +19,7 @@ fn main() { let fullscreen = Some(match num { 1 => Fullscreen::Exclusive(prompt_for_video_mode(&prompt_for_monitor(&event_loop))), - 2 => Fullscreen::Borderless(prompt_for_monitor(&event_loop)), + 2 => Fullscreen::Borderless(Some(prompt_for_monitor(&event_loop))), _ => panic!("Please enter a valid number"), }); diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 5134fbfb..68cdb60b 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -83,9 +83,7 @@ fn main() { ); } F => window.set_fullscreen(match (state, modifiers.alt()) { - (true, false) => { - Some(Fullscreen::Borderless(window.current_monitor().unwrap())) - } + (true, false) => Some(Fullscreen::Borderless(None)), (true, true) => Some(Fullscreen::Exclusive( video_modes.iter().nth(video_mode_id).unwrap().clone(), )), diff --git a/examples/window_debug.rs b/examples/window_debug.rs index 2771b370..dd4007f3 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -21,6 +21,7 @@ fn main() { eprintln!("debugging keys:"); eprintln!(" (E) Enter exclusive fullscreen"); eprintln!(" (F) Toggle borderless fullscreen"); + eprintln!(" (P) Toggle borderless fullscreen on system's preffered monitor"); eprintln!(" (M) Toggle minimized"); eprintln!(" (Q) Quit event loop"); eprintln!(" (V) Toggle visibility"); @@ -85,10 +86,17 @@ fn main() { if window.fullscreen().is_some() { window.set_fullscreen(None); } else { - let monitor = window.current_monitor().unwrap(); + let monitor = window.current_monitor(); window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); } } + VirtualKeyCode::P => { + if window.fullscreen().is_some() { + window.set_fullscreen(None); + } else { + window.set_fullscreen(Some(Fullscreen::Borderless(None))); + } + } VirtualKeyCode::M => { minimized = !minimized; window.set_minimized(minimized); diff --git a/src/platform_impl/ios/view.rs b/src/platform_impl/ios/view.rs index 5481b8ef..df5a803a 100644 --- a/src/platform_impl/ios/view.rs +++ b/src/platform_impl/ios/view.rs @@ -519,7 +519,15 @@ pub unsafe fn create_window( msg_send![window, setScreen:video_mode.monitor().ui_screen()] } Some(Fullscreen::Borderless(ref monitor)) => { - msg_send![window, setScreen:monitor.ui_screen()] + let uiscreen: id = match &monitor { + Some(monitor) => monitor.ui_screen() as id, + None => { + let uiscreen: id = msg_send![window, screen]; + uiscreen + } + }; + + msg_send![window, setScreen: uiscreen] } None => (), } diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index a7deb61b..d83b4941 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -196,7 +196,9 @@ impl Inner { let () = msg_send![uiscreen, setCurrentMode: video_mode.video_mode.screen_mode]; uiscreen } - Some(Fullscreen::Borderless(monitor)) => monitor.ui_screen() as id, + Some(Fullscreen::Borderless(monitor)) => monitor + .unwrap_or_else(|| self.current_monitor_inner()) + .ui_screen() as id, None => { warn!("`Window::set_fullscreen(None)` ignored on iOS"); return; @@ -235,7 +237,7 @@ impl Inner { && screen_space_bounds.size.width == screen_bounds.size.width && screen_space_bounds.size.height == screen_bounds.size.height { - Some(Fullscreen::Borderless(monitor)) + Some(Fullscreen::Borderless(Some(monitor))) } else { None } @@ -353,8 +355,10 @@ impl Window { Some(Fullscreen::Exclusive(ref video_mode)) => { video_mode.video_mode.monitor.ui_screen() as id } - Some(Fullscreen::Borderless(ref monitor)) => monitor.ui_screen() as id, - None => monitor::main_uiscreen().ui_screen(), + Some(Fullscreen::Borderless(Some(ref monitor))) => monitor.inner.ui_screen(), + Some(Fullscreen::Borderless(None)) | None => { + monitor::main_uiscreen().ui_screen() as id + } }; let screen_bounds: CGRect = msg_send![screen, bounds]; diff --git a/src/platform_impl/linux/wayland/window.rs b/src/platform_impl/linux/wayland/window.rs index c61ff19e..06f668cc 100644 --- a/src/platform_impl/linux/wayland/window.rs +++ b/src/platform_impl/linux/wayland/window.rs @@ -154,11 +154,16 @@ impl Window { Some(Fullscreen::Exclusive(_)) => { panic!("Wayland doesn't support exclusive fullscreen") } - Some(Fullscreen::Borderless(RootMonitorHandle { - inner: PlatformMonitorHandle::Wayland(ref monitor_id), - })) => frame.set_fullscreen(Some(&monitor_id.proxy)), - #[cfg(feature = "x11")] - Some(Fullscreen::Borderless(_)) => unreachable!(), + Some(Fullscreen::Borderless(monitor)) => { + let monitor = + monitor.and_then(|RootMonitorHandle { inner: monitor }| match monitor { + PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy), + #[cfg(feature = "x11")] + PlatformMonitorHandle::X(_) => None, + }); + + frame.set_fullscreen(monitor.as_ref()) + } None => { if attributes.maximized { frame.set_maximized(); @@ -333,11 +338,13 @@ impl Window { pub fn fullscreen(&self) -> Option { if *(self.fullscreen.lock().unwrap()) { - // If the monitor cannot be determined, we cannot report any fullscreen mode. - let current_monitor = self.current_monitor()?; - Some(Fullscreen::Borderless(RootMonitorHandle { - inner: PlatformMonitorHandle::Wayland(current_monitor), - })) + let current_monitor = self + .current_monitor() + .map(|current_monitor| RootMonitorHandle { + inner: PlatformMonitorHandle::Wayland(current_monitor), + }); + + Some(Fullscreen::Borderless(current_monitor)) } else { None } @@ -348,16 +355,16 @@ impl Window { Some(Fullscreen::Exclusive(_)) => { panic!("Wayland doesn't support exclusive fullscreen") } - Some(Fullscreen::Borderless(RootMonitorHandle { - inner: PlatformMonitorHandle::Wayland(ref monitor_id), - })) => { - self.frame - .lock() - .unwrap() - .set_fullscreen(Some(&monitor_id.proxy)); + Some(Fullscreen::Borderless(monitor)) => { + let monitor = + monitor.and_then(|RootMonitorHandle { inner: monitor }| match monitor { + PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy), + #[cfg(feature = "x11")] + PlatformMonitorHandle::X(_) => None, + }); + + self.frame.lock().unwrap().set_fullscreen(monitor.as_ref()); } - #[cfg(feature = "x11")] - Some(Fullscreen::Borderless(_)) => unreachable!(), None => self.frame.lock().unwrap().unset_fullscreen(), } } diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index ae63f436..058b3aa7 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -649,10 +649,11 @@ impl UnownedWindow { let (video_mode, monitor) = match fullscreen { Fullscreen::Exclusive(RootVideoMode { video_mode: PlatformVideoMode::X(ref video_mode), - }) => (Some(video_mode), video_mode.monitor.as_ref().unwrap()), - Fullscreen::Borderless(RootMonitorHandle { - inner: PlatformMonitorHandle::X(ref monitor), - }) => (None, monitor), + }) => (Some(video_mode), video_mode.monitor.clone().unwrap()), + Fullscreen::Borderless(Some(RootMonitorHandle { + inner: PlatformMonitorHandle::X(monitor), + })) => (None, monitor), + Fullscreen::Borderless(None) => (None, self.current_monitor()), #[cfg(feature = "wayland")] _ => unreachable!(), }; diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index d2b01403..191ce60a 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -142,13 +142,14 @@ fn create_window( unsafe { let pool = NSAutoreleasePool::new(nil); let screen = match attrs.fullscreen { - Some(Fullscreen::Borderless(RootMonitorHandle { inner: ref monitor })) + Some(Fullscreen::Borderless(Some(RootMonitorHandle { inner: ref monitor }))) | Some(Fullscreen::Exclusive(RootVideoMode { video_mode: VideoMode { ref monitor, .. }, })) => { let monitor_screen = monitor.ns_screen(); Some(monitor_screen.unwrap_or(appkit::NSScreen::mainScreen(nil))) } + Some(Fullscreen::Borderless(None)) => Some(appkit::NSScreen::mainScreen(nil)), None => None, }; let frame = match screen { @@ -755,10 +756,15 @@ impl UnownedWindow { // does not take a screen parameter, but uses the current screen) if let Some(ref fullscreen) = fullscreen { let new_screen = match fullscreen { - Fullscreen::Borderless(RootMonitorHandle { inner: ref monitor }) => monitor, + Fullscreen::Borderless(borderless) => { + let RootMonitorHandle { inner: monitor } = borderless + .clone() + .unwrap_or_else(|| self.current_monitor_inner()); + monitor + } Fullscreen::Exclusive(RootVideoMode { video_mode: VideoMode { ref monitor, .. }, - }) => monitor, + }) => monitor.clone(), } .ns_screen() .unwrap(); diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 9d106e15..d9067561 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -450,7 +450,7 @@ extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) { // Otherwise, we must've reached fullscreen by the user clicking // on the green fullscreen button. Update state! None => { - let current_monitor = window.current_monitor_inner(); + let current_monitor = Some(window.current_monitor_inner()); shared_state.fullscreen = Some(Fullscreen::Borderless(current_monitor)) } } diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index b78048f4..4719044e 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -233,7 +233,7 @@ impl Window { #[inline] pub fn fullscreen(&self) -> Option { if self.canvas.borrow().is_fullscreen() { - Some(Fullscreen::Borderless(self.current_monitor_inner())) + Some(Fullscreen::Borderless(Some(self.current_monitor_inner()))) } else { None } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 9227bceb..a6d15fb8 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -853,8 +853,11 @@ unsafe extern "system" fn public_window_callback( winuser::MonitorFromRect(&new_rect, winuser::MONITOR_DEFAULTTONULL); match fullscreen { Fullscreen::Borderless(ref mut fullscreen_monitor) => { - if new_monitor != fullscreen_monitor.inner.hmonitor() - && new_monitor != ptr::null_mut() + if new_monitor != ptr::null_mut() + && fullscreen_monitor + .as_ref() + .map(|monitor| new_monitor != monitor.inner.hmonitor()) + .unwrap_or(true) { if let Ok(new_monitor_info) = monitor::get_monitor_info(new_monitor) { let new_monitor_rect = new_monitor_info.rcMonitor; @@ -863,9 +866,9 @@ unsafe extern "system" fn public_window_callback( window_pos.cx = new_monitor_rect.right - new_monitor_rect.left; window_pos.cy = new_monitor_rect.bottom - new_monitor_rect.top; } - *fullscreen_monitor = crate::monitor::MonitorHandle { + *fullscreen_monitor = Some(crate::monitor::MonitorHandle { inner: MonitorHandle::new(new_monitor), - }; + }); } } Fullscreen::Exclusive(ref video_mode) => { diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 34406310..6253c943 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -496,9 +496,12 @@ impl Window { // Update window bounds match &fullscreen { Some(fullscreen) => { - let monitor = match fullscreen { - Fullscreen::Exclusive(ref video_mode) => video_mode.monitor(), - Fullscreen::Borderless(ref monitor) => monitor.clone(), + let monitor = match &fullscreen { + Fullscreen::Exclusive(video_mode) => video_mode.monitor(), + Fullscreen::Borderless(Some(monitor)) => monitor.clone(), + Fullscreen::Borderless(None) => RootMonitorHandle { + inner: monitor::current_monitor(window.0), + }, }; let position: (i32, i32) = monitor.position().into(); diff --git a/src/window.rs b/src/window.rs index 1977d32c..d6cd8e6c 100644 --- a/src/window.rs +++ b/src/window.rs @@ -628,6 +628,7 @@ impl Window { /// /// - **iOS:** Can only be called on the main thread. /// - **Android:** Will always return `None`. + /// - **Wayland:** Can return `Borderless(None)` when there are no monitors. #[inline] pub fn fullscreen(&self) -> Option { self.window.fullscreen() @@ -850,10 +851,13 @@ impl Default for CursorIcon { } } +/// Fullscreen modes. #[derive(Clone, Debug, PartialEq)] pub enum Fullscreen { Exclusive(VideoMode), - Borderless(MonitorHandle), + + /// Providing `None` to `Borderless` will fullscreen on the current monitor. + Borderless(Option), } #[derive(Clone, Debug, PartialEq)]