diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index ad1fad85b1..2e7378fc16 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -21,6 +21,7 @@ use std::{ use anyhow::{anyhow, Context, Result}; use lazy_static::lazy_static; use parking_lot::Mutex; +use pathfinder_geometry::vector::Vector2F; use postage::oneshot; use smallvec::SmallVec; use smol::prelude::*; @@ -865,6 +866,14 @@ impl MutableAppContext { } } + pub fn is_topmost_window_for_position(&self, window_id: usize, position: Vector2F) -> bool { + self.presenters_and_platform_windows + .get(&window_id) + .map_or(false, |(_, window)| { + window.is_topmost_for_position(position) + }) + } + pub fn window_ids(&self) -> impl Iterator + '_ { self.cx.windows.keys().cloned() } diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 99d607e407..05ba61a9ad 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -145,6 +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 is_topmost_for_position(&self, position: Vector2F) -> bool; } #[derive(Debug)] diff --git a/crates/gpui/src/platform/mac/event.rs b/crates/gpui/src/platform/mac/event.rs index 2f29898c26..6882721372 100644 --- a/crates/gpui/src/platform/mac/event.rs +++ b/crates/gpui/src/platform/mac/event.rs @@ -125,6 +125,7 @@ impl Event { button, position: vec2f( native_event.locationInWindow().x as f32, + // MacOS screen coordinates are relative to bottom left window_height - native_event.locationInWindow().y as f32, ), modifiers: read_modifiers(native_event), @@ -150,6 +151,7 @@ impl Event { button, position: vec2f( native_event.locationInWindow().x as f32, + // MacOS view coordinates are relative to bottom left window_height - native_event.locationInWindow().y as f32, ), modifiers: read_modifiers(native_event), diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index 37406858ec..dbb1a01f31 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -699,7 +699,9 @@ impl platform::Platform for MacPlatform { unsafe { let cursor: id = match style { CursorStyle::Arrow => msg_send![class!(NSCursor), arrowCursor], - CursorStyle::ResizeLeftRight => msg_send![class!(NSCursor), resizeLeftRightCursor], + 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], diff --git a/crates/gpui/src/platform/mac/status_item.rs b/crates/gpui/src/platform/mac/status_item.rs index 33feb4808f..2da7caab7e 100644 --- a/crates/gpui/src/platform/mac/status_item.rs +++ b/crates/gpui/src/platform/mac/status_item.rs @@ -258,6 +258,10 @@ impl platform::Window for StatusItem { crate::Appearance::from_native(appearance) } } + + fn is_topmost_for_position(&self, _: Vector2F) -> bool { + true + } } impl StatusItemState { diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 6126533644..bef6f65e42 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::{ @@ -755,6 +755,37 @@ impl platform::Window for Window { fn on_appearance_changed(&mut self, callback: Box) { self.0.borrow_mut().appearance_changed_callback = Some(callback); } + + 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 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]; + 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 == YES || is_window == YES { + 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 + } + } + } } impl WindowState { diff --git a/crates/gpui/src/platform/test.rs b/crates/gpui/src/platform/test.rs index 00cd524c1d..d33e3e2fca 100644 --- a/crates/gpui/src/platform/test.rs +++ b/crates/gpui/src/platform/test.rs @@ -332,6 +332,10 @@ impl super::Window for Window { } fn on_appearance_changed(&mut self, _: Box) {} + + fn is_topmost_for_position(&self, _position: Vector2F) -> bool { + true + } } pub fn platform() -> Platform { diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 0909d95fd0..1fff5c50b5 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -316,7 +316,16 @@ impl Presenter { break; } } - cx.platform().set_cursor_style(style_to_assign); + + let t0 = std::time::Instant::now(); + let is_topmost_window = + cx.is_topmost_window_for_position(self.window_id, *position); + println!("is_topmost_window => {:?}", t0.elapsed()); + if is_topmost_window { + let t1 = std::time::Instant::now(); + cx.platform().set_cursor_style(style_to_assign); + println!("set_cursor_style => {:?}", t1.elapsed()); + } if !event_reused { if pressed_button.is_some() { diff --git a/crates/gpui/src/presenter/event_dispatcher.rs b/crates/gpui/src/presenter/event_dispatcher.rs index 4c72334910..960c565bd4 100644 --- a/crates/gpui/src/presenter/event_dispatcher.rs +++ b/crates/gpui/src/presenter/event_dispatcher.rs @@ -209,6 +209,7 @@ impl EventDispatcher { break; } } + cx.platform().set_cursor_style(style_to_assign); if !event_reused { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index ec7ba8fae0..b0abe09070 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -100,7 +100,6 @@ actions!( NewTerminal, NewSearch, Feedback, - ShowNotif, ] );