diff --git a/winit-appkit/src/monitor.rs b/winit-appkit/src/monitor.rs index cc4a15e52f..5affbe4db7 100644 --- a/winit-appkit/src/monitor.rs +++ b/winit-appkit/src/monitor.rs @@ -175,7 +175,7 @@ impl MonitorHandle { /// bar and the Dock (see `NSScreen.visibleFrame`). `None` if the underlying /// `NSScreen` can no longer be found. pub(crate) fn work_area(&self) -> Option<(PhysicalPosition, PhysicalSize)> { - let scale_factor = self.scale_factor(); + let scale_factor = self.scale_factor().unwrap_or(1.0); run_on_main(|mtm| { let visible_frame = self.ns_screen(mtm)?.visibleFrame(); let origin = flip_window_screen_coordinates(visible_frame); @@ -226,16 +226,11 @@ impl MonitorHandleProvider for MonitorHandle { // flip_window_screen_coordinates(self.ns_screen(mtm)?.frame()) let bounds = CGDisplayBounds(self.display_id()); let position = LogicalPosition::new(bounds.origin.x, bounds.origin.y); - Some(position.to_physical(self.scale_factor())) + self.scale_factor().map(|scale_factor| position.to_physical(scale_factor)) } - fn scale_factor(&self) -> f64 { - run_on_main(|mtm| { - match self.ns_screen(mtm) { - Some(screen) => screen.backingScaleFactor() as f64, - None => 1.0, // default to 1.0 when we can't find the screen - } - }) + fn scale_factor(&self) -> Option { + run_on_main(|mtm| self.ns_screen(mtm).map(|screen| screen.backingScaleFactor() as f64)) } fn current_video_mode(&self) -> Option { diff --git a/winit-core/src/monitor.rs b/winit-core/src/monitor.rs index 4c5750b613..32b4105def 100644 --- a/winit-core/src/monitor.rs +++ b/winit-core/src/monitor.rs @@ -98,11 +98,12 @@ pub trait MonitorHandleProvider: Any + fmt::Debug + Send + Sync { /// /// See the [`dpi`] module for more information. /// - /// - **Wayland:** May differ from [`Window::scale_factor`]. - /// - **Web:** Always returns `0.0` without `detailed_monitor_permissions`. + /// - **Wayland:** Returns `None` since the precise scale factor is not known before window + /// creation. + /// - **Web:** Returns `None` without `detailed_monitor_permissions`. /// /// [`Window::scale_factor`]: crate::window::Window::scale_factor - fn scale_factor(&self) -> f64; + fn scale_factor(&self) -> Option; fn current_video_mode(&self) -> Option; diff --git a/winit-uikit/src/monitor.rs b/winit-uikit/src/monitor.rs index c2d7935372..be81bcbf04 100644 --- a/winit-uikit/src/monitor.rs +++ b/winit-uikit/src/monitor.rs @@ -109,8 +109,8 @@ impl MonitorHandleProvider for MonitorHandle { Some((bounds.origin.x as f64, bounds.origin.y as f64).into()) } - fn scale_factor(&self) -> f64 { - self.ui_screen.get_on_main(|ui_screen| ui_screen.nativeScale()) as f64 + fn scale_factor(&self) -> Option { + Some(self.ui_screen.get_on_main(|ui_screen| ui_screen.nativeScale()) as f64) } fn current_video_mode(&self) -> Option { diff --git a/winit-wayland/src/output.rs b/winit-wayland/src/output.rs index 72ac253f61..76ab6c6b8f 100644 --- a/winit-wayland/src/output.rs +++ b/winit-wayland/src/output.rs @@ -50,9 +50,11 @@ impl CoreMonitorHandle for MonitorHandle { })) } - fn scale_factor(&self) -> f64 { - let output_data = self.proxy.data::().unwrap(); - output_data.scale_factor() as f64 + fn scale_factor(&self) -> Option { + // Although we can extract an integer scale factor via + // self.proxy.data::() this often differs from the real + // scale factor (due to usage of fractional scaling). + None } fn current_video_mode(&self) -> Option { diff --git a/winit-web/src/monitor.rs b/winit-web/src/monitor.rs index 029eb4ab21..f9cbaa33cd 100644 --- a/winit-web/src/monitor.rs +++ b/winit-web/src/monitor.rs @@ -127,7 +127,7 @@ impl MonitorHandleProvider for MonitorHandle { self.id.unwrap_or_default() } - fn scale_factor(&self) -> f64 { + fn scale_factor(&self) -> Option { self.inner.queue(|inner| inner.scale_factor()) } @@ -276,10 +276,10 @@ impl Inner { Self { window, engine, screen, orientation: OnceCell::new() } } - fn scale_factor(&self) -> f64 { + fn scale_factor(&self) -> Option { match &self.screen { - Screen::Screen(_) => 0., - Screen::Detailed { screen, .. } => screen.device_pixel_ratio(), + Screen::Screen(_) => None, + Screen::Detailed { screen, .. } => Some(screen.device_pixel_ratio()), } } diff --git a/winit-win32/src/monitor.rs b/winit-win32/src/monitor.rs index 9d031bc2d1..9c47825255 100644 --- a/winit-win32/src/monitor.rs +++ b/winit-win32/src/monitor.rs @@ -192,8 +192,8 @@ impl MonitorHandleProvider for MonitorHandle { .ok() } - fn scale_factor(&self) -> f64 { - dpi_to_scale_factor(get_monitor_dpi(self.0).unwrap_or(96)) + fn scale_factor(&self) -> Option { + get_monitor_dpi(self.0).map(dpi_to_scale_factor) } fn current_video_mode(&self) -> Option { diff --git a/winit-x11/src/monitor.rs b/winit-x11/src/monitor.rs index 7f324fde5e..d986a52e12 100644 --- a/winit-x11/src/monitor.rs +++ b/winit-x11/src/monitor.rs @@ -68,8 +68,8 @@ impl MonitorHandleProvider for MonitorHandle { Some(self.position.into()) } - fn scale_factor(&self) -> f64 { - self.scale_factor + fn scale_factor(&self) -> Option { + Some(self.scale_factor) } fn current_video_mode(&self) -> Option { diff --git a/winit-x11/src/window.rs b/winit-x11/src/window.rs index aae7e8258c..8374609d43 100644 --- a/winit-x11/src/window.rs +++ b/winit-x11/src/window.rs @@ -510,7 +510,7 @@ impl UnownedWindow { }) .unwrap_or_else(|| monitors.swap_remove(0)) }; - let scale_factor = guessed_monitor.scale_factor(); + let scale_factor = guessed_monitor.scale_factor().unwrap_or(1.0); info!("Guessed window scale factor: {}", scale_factor); diff --git a/winit/examples/application.rs b/winit/examples/application.rs index 27fb844349..203b67381c 100644 --- a/winit/examples/application.rs +++ b/winit/examples/application.rs @@ -342,7 +342,9 @@ impl Application { info!(" Position: {x},{y}"); } - info!(" Scale factor: {}", monitor.scale_factor()); + if let Some(factor) = monitor.scale_factor() { + info!(" Scale factor: {factor}"); + } info!(" Available modes (width x height x bit-depth):"); for mode in monitor.video_modes() { diff --git a/winit/src/changelog/unreleased.md b/winit/src/changelog/unreleased.md index a0e7d3a474..6bb6d6121b 100644 --- a/winit/src/changelog/unreleased.md +++ b/winit/src/changelog/unreleased.md @@ -40,6 +40,9 @@ changelog entry. ## Unreleased +### Changed +- `MonitorHandleProvider::scale_factor` now returns `Option`. + ### Fixed - On Windows, fix a crash occurring when trying to create a DXGI surface on a window that is both fullscreen and always on top.