diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 0e5697c30b..2e7378fc16 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -866,10 +866,12 @@ impl MutableAppContext { } } - pub fn screen_position(&self, window_id: usize, view_position: &Vector2F) -> Option { + pub fn is_topmost_window_for_position(&self, window_id: usize, position: Vector2F) -> bool { self.presenters_and_platform_windows .get(&window_id) - .map(|(_, window)| window.screen_position(view_position)) + .map_or(false, |(_, window)| { + window.is_topmost_for_position(position) + }) } pub fn window_ids(&self) -> impl Iterator + '_ { diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 0601fd9764..05ba61a9ad 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -64,7 +64,7 @@ pub trait Platform: Send + Sync { fn read_credentials(&self, url: &str) -> Result)>>; fn delete_credentials(&self, url: &str) -> Result<()>; - fn set_cursor_style(&self, style: CursorStyle, window_id: usize, screen_position: &Vector2F); + fn set_cursor_style(&self, style: CursorStyle); fn should_auto_hide_scrollbars(&self) -> bool; fn local_timezone(&self) -> UtcOffset; @@ -145,7 +145,7 @@ pub trait Window { fn present_scene(&mut self, scene: Scene); fn appearance(&self) -> Appearance; fn on_appearance_changed(&mut self, callback: Box); - fn screen_position(&self, view_position: &Vector2F) -> Vector2F; + fn is_topmost_for_position(&self, position: Vector2F) -> bool; } #[derive(Debug)] diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index ae9db6a396..dbb1a01f31 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -37,7 +37,6 @@ use objc::{ runtime::{Class, Object, Sel}, sel, sel_impl, }; -use pathfinder_geometry::vector::Vector2F; use postage::oneshot; use ptr::null_mut; use std::{ @@ -696,21 +695,18 @@ impl platform::Platform for MacPlatform { Ok(()) } - fn set_cursor_style(&self, style: CursorStyle, window_id: usize, screen_position: &Vector2F) { - if Some(window_id) == Window::window_id_under(screen_position) { - dbg!(screen_position, style); - unsafe { - let cursor: id = match style { - CursorStyle::Arrow => msg_send![class!(NSCursor), arrowCursor], - CursorStyle::ResizeLeftRight => { - msg_send![class!(NSCursor), resizeLeftRightCursor] - } - CursorStyle::ResizeUpDown => msg_send![class!(NSCursor), resizeUpDownCursor], - CursorStyle::PointingHand => msg_send![class!(NSCursor), pointingHandCursor], - CursorStyle::IBeam => msg_send![class!(NSCursor), IBeamCursor], - }; - let _: () = msg_send![cursor, set]; - } + fn set_cursor_style(&self, style: CursorStyle) { + unsafe { + let cursor: id = match style { + CursorStyle::Arrow => msg_send![class!(NSCursor), arrowCursor], + CursorStyle::ResizeLeftRight => { + msg_send![class!(NSCursor), resizeLeftRightCursor] + } + CursorStyle::ResizeUpDown => msg_send![class!(NSCursor), resizeUpDownCursor], + CursorStyle::PointingHand => msg_send![class!(NSCursor), pointingHandCursor], + CursorStyle::IBeam => msg_send![class!(NSCursor), IBeamCursor], + }; + let _: () = msg_send![cursor, set]; } } diff --git a/crates/gpui/src/platform/mac/status_item.rs b/crates/gpui/src/platform/mac/status_item.rs index d05c559772..2da7caab7e 100644 --- a/crates/gpui/src/platform/mac/status_item.rs +++ b/crates/gpui/src/platform/mac/status_item.rs @@ -259,8 +259,8 @@ impl platform::Window for StatusItem { } } - fn screen_position(&self, _view_position: &Vector2F) -> Vector2F { - unimplemented!() + fn is_topmost_for_position(&self, _: Vector2F) -> bool { + true } } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 067dd69115..191ab77058 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -17,9 +17,9 @@ use crate::{ use block::ConcreteBlock; use cocoa::{ appkit::{ - CGPoint, NSApplication, NSBackingStoreBuffered, NSScreen, NSView, NSViewHeightSizable, - NSViewWidthSizable, NSWindow, NSWindowButton, NSWindowCollectionBehavior, - NSWindowStyleMask, + CGFloat, CGPoint, NSApplication, NSBackingStoreBuffered, NSScreen, NSView, + NSViewHeightSizable, NSViewWidthSizable, NSWindow, NSWindowButton, + NSWindowCollectionBehavior, NSWindowStyleMask, }, base::{id, nil}, foundation::{ @@ -52,8 +52,6 @@ use std::{ time::Duration, }; -use super::geometry::Vector2FExt; - const WINDOW_STATE_IVAR: &str = "windowState"; static mut WINDOW_CLASS: *const Class = ptr::null(); @@ -561,28 +559,6 @@ impl Window { } } } - - pub fn window_id_under(screen_position: &Vector2F) -> Option { - unsafe { - let app = NSApplication::sharedApplication(nil); - - let point = screen_position.to_ns_point(); - let window_number: NSInteger = msg_send![class!(NSWindow), windowNumberAtPoint:point belowWindowWithWindowNumber:0]; - - // For some reason this API doesn't work when our two windows are on top of each other - let top_most_window: id = msg_send![app, windowWithWindowNumber: window_number]; - - // dbg!(top_most_window); - let is_panel: BOOL = msg_send![top_most_window, isKindOfClass: PANEL_CLASS]; - let is_window: BOOL = msg_send![top_most_window, isKindOfClass: WINDOW_CLASS]; - if is_panel | is_window { - let id = get_window_state(&*top_most_window).borrow().id; - Some(id) - } else { - None - } - } - } } impl Drop for Window { @@ -780,13 +756,34 @@ impl platform::Window for Window { self.0.borrow_mut().appearance_changed_callback = Some(callback); } - fn screen_position(&self, view_position: &Vector2F) -> Vector2F { - let self_borrow = self.0.borrow_mut(); + fn is_topmost_for_position(&self, position: Vector2F) -> bool { + let window_bounds = self.bounds(); + let self_borrow = self.0.borrow(); + let self_id = self_borrow.id; + unsafe { - let point = view_position.to_ns_point(); + let app = NSApplication::sharedApplication(nil); + + // Convert back to bottom-left coordinates + let point = NSPoint::new( + position.x() as CGFloat, + (window_bounds.height() - position.y()) as CGFloat, + ); + let screen_point: NSPoint = msg_send![self_borrow.native_window, convertPointToScreen: point]; - vec2f(screen_point.x as f32, screen_point.y as f32) + let window_number: NSInteger = msg_send![class!(NSWindow), windowNumberAtPoint:screen_point belowWindowWithWindowNumber:0]; + let top_most_window: id = msg_send![app, windowWithWindowNumber: window_number]; + + let is_panel: BOOL = msg_send![top_most_window, isKindOfClass: PANEL_CLASS]; + let is_window: BOOL = msg_send![top_most_window, isKindOfClass: WINDOW_CLASS]; + if is_panel | is_window { + let topmost_window_id = get_window_state(&*top_most_window).borrow().id; + topmost_window_id == self_id + } else { + // Someone else's window is on top + false + } } } } diff --git a/crates/gpui/src/platform/test.rs b/crates/gpui/src/platform/test.rs index 7295bf525b..d33e3e2fca 100644 --- a/crates/gpui/src/platform/test.rs +++ b/crates/gpui/src/platform/test.rs @@ -178,7 +178,7 @@ impl super::Platform for Platform { Ok(()) } - fn set_cursor_style(&self, style: CursorStyle, _window_id: usize, _position: &Vector2F) { + fn set_cursor_style(&self, style: CursorStyle) { *self.cursor.lock() = style; } @@ -333,8 +333,8 @@ impl super::Window for Window { fn on_appearance_changed(&mut self, _: Box) {} - fn screen_position(&self, view_position: &Vector2F) -> Vector2F { - view_position.clone() + fn is_topmost_for_position(&self, _position: Vector2F) -> bool { + true } } diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 1b16574cb8..5bff7e7bb1 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -31,6 +31,7 @@ use std::{ ops::{Deref, DerefMut, Range}, sync::Arc, }; +use time::Instant; pub struct Presenter { window_id: usize, @@ -317,15 +318,8 @@ impl Presenter { } } - dbg!("*******"); - dbg!(position); - dbg!(event_reused); - if let Some(screen_position) = cx.screen_position(self.window_id, position) { - cx.platform().set_cursor_style( - style_to_assign, - self.window_id, - &screen_position, - ); + if cx.is_topmost_window_for_position(self.window_id, *position) { + cx.platform().set_cursor_style(style_to_assign); } if !event_reused {