diff --git a/.changes/cursor-position-scale.md b/.changes/cursor-position-scale.md new file mode 100644 index 000000000..7fc06bbfa --- /dev/null +++ b/.changes/cursor-position-scale.md @@ -0,0 +1,5 @@ +--- +"tao": "patch" +--- + +Fix `Window::cursor_position` and `EventLoopWindowTarget::cursor_position` scale on Linux and macOS. diff --git a/src/event_loop.rs b/src/event_loop.rs index 5ae7c8095..56937251f 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -248,7 +248,7 @@ impl EventLoopWindowTarget { /// /// ## Platform-specific /// - /// - **iOS / Android**: Unsupported. + /// - **iOS / Android / Linux(Wayland)**: Unsupported, returns `0,0`. #[inline] pub fn cursor_position(&self) -> Result, ExternalError> { self.p.cursor_position() diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 8974e646e..823c5f85d 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -108,7 +108,7 @@ impl EventLoopWindowTarget { #[inline] pub fn cursor_position(&self) -> Result, ExternalError> { - util::cursor_position() + util::cursor_position(self.is_wayland()) } } diff --git a/src/platform_impl/linux/util.rs b/src/platform_impl/linux/util.rs index bd0b647f3..ed1792c82 100644 --- a/src/platform_impl/linux/util.rs +++ b/src/platform_impl/linux/util.rs @@ -1,13 +1,29 @@ use gdk::Display; -use crate::{dpi::PhysicalPosition, error::ExternalError}; +use crate::{ + dpi::{LogicalPosition, PhysicalPosition}, + error::ExternalError, +}; #[inline] -pub fn cursor_position() -> Result, ExternalError> { - Display::default() - .and_then(|d| d.default_seat()) - .and_then(|s| s.pointer()) - .map(|p| p.position_double()) - .map(|(_, x, y)| (x, y).into()) - .ok_or(ExternalError::Os(os_error!(super::OsError))) +pub fn cursor_position(is_wayland: bool) -> Result, ExternalError> { + if is_wayland { + Ok((0, 0).into()) + } else { + Display::default() + .map(|d| { + ( + d.default_seat().and_then(|s| s.pointer()), + d.default_group(), + ) + }) + .map(|(p, g)| { + p.map(|p| { + let (_, x, y) = p.position_double(); + LogicalPosition::new(x, y).to_physical(g.scale_factor() as _) + }) + }) + .map(|p| p.ok_or(ExternalError::Os(os_error!(super::OsError)))) + .ok_or(ExternalError::Os(os_error!(super::OsError)))? + } } diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 762095eb6..c3ac9d265 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -761,7 +761,7 @@ impl Window { #[inline] pub fn cursor_position(&self) -> Result, ExternalError> { - util::cursor_position() + util::cursor_position(self.window.display().backend().is_wayland()) } pub fn current_monitor(&self) -> Option { diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 8ec8a6b23..78ebd13a8 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -104,7 +104,12 @@ impl EventLoopWindowTarget { #[inline] pub fn cursor_position(&self) -> Result, ExternalError> { - util::cursor_position() + let point = util::cursor_position()?; + if let Some(m) = self.monitor_from_point(point.x, point.y) { + Ok(point.to_physical(m.scale_factor())) + } else { + Err(ExternalError::Os(os_error!(super::OsError::CGError(0)))) + } } } diff --git a/src/platform_impl/macos/util/mod.rs b/src/platform_impl/macos/util/mod.rs index 4c16610b3..c1fda802a 100644 --- a/src/platform_impl/macos/util/mod.rs +++ b/src/platform_impl/macos/util/mod.rs @@ -24,11 +24,7 @@ use core_graphics::{ }; use objc::runtime::{Class, Object, Sel, BOOL, YES}; -use crate::{ - dpi::{LogicalPosition, PhysicalPosition}, - error::ExternalError, - platform_impl::platform::ffi, -}; +use crate::{dpi::LogicalPosition, error::ExternalError, platform_impl::platform::ffi}; // Replace with `!` once stable #[derive(Debug)] @@ -129,11 +125,11 @@ pub fn window_position(position: LogicalPosition) -> NSPoint { } // FIXME: This is actually logical position. -pub fn cursor_position() -> Result, ExternalError> { +pub fn cursor_position() -> Result, ExternalError> { if let Ok(s) = CGEventSource::new(CGEventSourceStateID::CombinedSessionState) { if let Ok(e) = CGEvent::new(s) { let pt = e.location(); - let pos = PhysicalPosition::new(pt.x, pt.y); + let pos = LogicalPosition::new(pt.x, pt.y); return Ok(pos); } } diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index a458cf486..211d8b5d0 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -805,7 +805,12 @@ impl UnownedWindow { #[inline] pub fn cursor_position(&self) -> Result, ExternalError> { - util::cursor_position() + let point = util::cursor_position()?; + if let Some(m) = self.monitor_from_point(point.x, point.y) { + Ok(point.to_physical(m.scale_factor())) + } else { + Err(ExternalError::Os(os_error!(OsError::CGError(0)))) + } } #[inline] diff --git a/src/window.rs b/src/window.rs index 269676412..050d35469 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1202,7 +1202,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android**: Unsupported, returns `0,0`. + /// - **iOS / Android / Linux(Wayland)**: Unsupported, returns `0,0`. #[inline] pub fn cursor_position(&self) -> Result, ExternalError> { self.window.cursor_position()