From 7030548c76e156dc0d981a1f582cb94b52459941 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 22 Aug 2020 17:57:17 +0300 Subject: [PATCH] Make 'current_monitor' return 'Option' On certain platforms window couldn't be on any monitor resulting in failures of 'current_monitor' function. Such issue was happening on Wayland, since the window isn't on any monitor, unless the user has drawn something into it. Returning 'Option' will give an ability to handle such situations gracefully by properly indicating that there's no current monitor. Fixes #793. --- CHANGELOG.md | 5 +++-- examples/multithreaded.rs | 6 +++--- examples/window_debug.rs | 4 ++-- src/platform_impl/android/mod.rs | 6 +++--- src/platform_impl/ios/window.rs | 8 ++++++-- src/platform_impl/linux/mod.rs | 19 ++++++++++++++++--- src/platform_impl/linux/wayland/window.rs | 10 +++++----- src/platform_impl/macos/window.rs | 7 ++++++- src/platform_impl/macos/window_delegate.rs | 3 ++- src/platform_impl/web/window.rs | 9 +++++++-- src/platform_impl/windows/window.rs | 6 +++--- src/window.rs | 6 ++++-- 12 files changed, 60 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3658c23da81..3acb79f4ac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,9 +25,10 @@ - **Breaking:** On Web, `set_cursor_position` and `set_cursor_grab` will now always return an error. - **Breaking:** `PixelDelta` scroll events now return a `PhysicalPosition`. - On NetBSD, fixed crash due to incorrect detection of the main thread. -- **Breaking:** The virtual key code `Subtract` has been renamed to `NumpadSubtract` -- **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract` +- **Breaking:** The virtual key code `Subtract` has been renamed to `NumpadSubtract`. +- **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`. - On macOS, fix inverted horizontal scroll. +- **Breaking:** `current_monitor` now returns `Option`. # 0.22.2 (2020-05-16) diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 60f9d802de6..4141775e476 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -21,7 +21,7 @@ fn main() { .build(&event_loop) .unwrap(); - let mut video_modes: Vec<_> = window.current_monitor().video_modes().collect(); + let mut video_modes: Vec<_> = window.current_monitor().unwrap().video_modes().collect(); let mut video_mode_id = 0usize; let (tx, rx) = mpsc::channel(); @@ -34,7 +34,7 @@ fn main() { // was moved to an another monitor, so that the window // appears on this monitor instead when we go fullscreen let previous_video_mode = video_modes.iter().cloned().nth(video_mode_id); - video_modes = window.current_monitor().video_modes().collect(); + video_modes = window.current_monitor().unwrap().video_modes().collect(); video_mode_id = video_mode_id.min(video_modes.len()); let video_mode = video_modes.iter().nth(video_mode_id); @@ -83,7 +83,7 @@ fn main() { } F => window.set_fullscreen(match (state, modifiers.alt()) { (true, false) => { - Some(Fullscreen::Borderless(window.current_monitor())) + Some(Fullscreen::Borderless(window.current_monitor().unwrap())) } (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 f6e960a7944..e8de3cf0112 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -70,7 +70,7 @@ fn main() { size.width * size.height } - let monitor = window.current_monitor(); + let monitor = window.current_monitor().unwrap(); if let Some(mode) = monitor .video_modes() .max_by(|a, b| area(a.size()).cmp(&area(b.size()))) @@ -84,7 +84,7 @@ fn main() { if window.fullscreen().is_some() { window.set_fullscreen(None); } else { - let monitor = window.current_monitor(); + let monitor = window.current_monitor().unwrap(); window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); } } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 453815d8725..db759ed50e4 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -391,10 +391,10 @@ impl Window { v } - pub fn current_monitor(&self) -> monitor::MonitorHandle { - monitor::MonitorHandle { + pub fn current_monitor(&self) -> Option { + Some(monitor::MonitorHandle { inner: MonitorHandle, - } + }) } pub fn scale_factor(&self) -> f64 { diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 5fa83e9027a..db834c606a6 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -224,7 +224,7 @@ impl Inner { pub fn fullscreen(&self) -> Option { unsafe { - let monitor = self.current_monitor(); + let monitor = self.current_monitor_inner(); let uiscreen = monitor.inner.ui_screen(); let screen_space_bounds = self.screen_frame(); let screen_bounds: CGRect = msg_send![uiscreen, bounds]; @@ -258,7 +258,7 @@ impl Inner { warn!("`Window::set_ime_position` is ignored on iOS") } - pub fn current_monitor(&self) -> RootMonitorHandle { + fn current_monitor_inner(&self) -> RootMonitorHandle { unsafe { let uiscreen: id = msg_send![self.window, screen]; RootMonitorHandle { @@ -267,6 +267,10 @@ impl Inner { } } + pub fn current_monitor(&self) -> Option { + Some(self.current_monitor_inner()) + } + pub fn available_monitors(&self) -> VecDeque { unsafe { monitor::uiscreens() } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 73b84777608..b0272f5121d 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -425,9 +425,22 @@ impl Window { } #[inline] - pub fn current_monitor(&self) -> RootMonitorHandle { - RootMonitorHandle { - inner: x11_or_wayland!(match self; Window(window) => window.current_monitor(); as MonitorHandle), + pub fn current_monitor(&self) -> Option { + match self { + #[cfg(feature = "x11")] + &Window::X(ref window) => { + let current_monitor = window.current_monitor(); + Some(RootMonitorHandle { + inner: MonitorHandle::X(current_monitor), + }) + } + #[cfg(feature = "wayland")] + &Window::Wayland(ref window) => { + let current_monitor = window.current_monitor()?; + Some(RootMonitorHandle { + inner: MonitorHandle::Wayland(current_monitor), + }) + } } } diff --git a/src/platform_impl/linux/wayland/window.rs b/src/platform_impl/linux/wayland/window.rs index a0be1e9d7c1..7150392b155 100644 --- a/src/platform_impl/linux/wayland/window.rs +++ b/src/platform_impl/linux/wayland/window.rs @@ -335,7 +335,7 @@ impl Window { pub fn fullscreen(&self) -> Option { if *(self.fullscreen.lock().unwrap()) { Some(Fullscreen::Borderless(RootMonitorHandle { - inner: PlatformMonitorHandle::Wayland(self.current_monitor()), + inner: PlatformMonitorHandle::Wayland(self.current_monitor().unwrap()), })) } else { None @@ -396,12 +396,12 @@ impl Window { &self.surface } - pub fn current_monitor(&self) -> MonitorHandle { - let output = get_outputs(&self.surface).last().unwrap().clone(); - MonitorHandle { + pub fn current_monitor(&self) -> Option { + let output = get_outputs(&self.surface).last()?.clone(); + Some(MonitorHandle { proxy: output, mgr: self.outputs.clone(), - } + }) } pub fn available_monitors(&self) -> VecDeque { diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 175cf73345c..b82f9bcc258 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -972,7 +972,7 @@ impl UnownedWindow { } #[inline] - pub fn current_monitor(&self) -> RootMonitorHandle { + pub(crate) fn current_monitor_inner(&self) -> RootMonitorHandle { unsafe { let screen: id = msg_send![*self.ns_window, screen]; let desc = NSScreen::deviceDescription(screen); @@ -985,6 +985,11 @@ impl UnownedWindow { } } + #[inline] + pub fn current_monitor(&self) -> Option { + Some(self.current_monitor_inner()) + } + #[inline] pub fn available_monitors(&self) -> VecDeque { monitor::available_monitors() diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 8c49e773be7..9d106e15187 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -450,7 +450,8 @@ 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 => { - shared_state.fullscreen = Some(Fullscreen::Borderless(window.current_monitor())) + let current_monitor = window.current_monitor_inner(); + shared_state.fullscreen = Some(Fullscreen::Borderless(current_monitor)) } } shared_state.in_fullscreen_transition = true; diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index bcf701164e6..f42fd77a3b3 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -201,7 +201,7 @@ impl Window { #[inline] pub fn fullscreen(&self) -> Option { if self.canvas.is_fullscreen() { - Some(Fullscreen::Borderless(self.current_monitor())) + Some(Fullscreen::Borderless(self.current_monitor_inner())) } else { None } @@ -237,12 +237,17 @@ impl Window { } #[inline] - pub fn current_monitor(&self) -> RootMH { + fn current_monitor_inner(&self) -> RootMH { RootMH { inner: monitor::Handle, } } + #[inline] + pub fn current_monitor(&self) -> Option { + Some(self.current_monitor_inner()) + } + #[inline] pub fn available_monitors(&self) -> VecDequeIter { VecDeque::new().into_iter() diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 3b8dc98f515..34406310dfa 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -577,10 +577,10 @@ impl Window { } #[inline] - pub fn current_monitor(&self) -> RootMonitorHandle { - RootMonitorHandle { + pub fn current_monitor(&self) -> Option { + Some(RootMonitorHandle { inner: monitor::current_monitor(self.window.0), - } + }) } #[inline] diff --git a/src/window.rs b/src/window.rs index a00cd7c0285..b8bec50bf05 100644 --- a/src/window.rs +++ b/src/window.rs @@ -736,13 +736,15 @@ impl Window { /// Monitor info functions. impl Window { - /// Returns the monitor on which the window currently resides + /// Returns the monitor on which the window currently resides. + /// + /// Returns `None` if current monitor can't be detected. /// /// ## Platform-specific /// /// **iOS:** Can only be called on the main thread. #[inline] - pub fn current_monitor(&self) -> MonitorHandle { + pub fn current_monitor(&self) -> Option { self.window.current_monitor() }