Changed the presenter to only send 'set_cursor_style' on the topmost window

Mikayla Maki and Antonio created

co-authored-by: Antonio <antonio@zed.dev>

Change summary

crates/gpui/src/app.rs                      |  6 +
crates/gpui/src/platform.rs                 |  4 
crates/gpui/src/platform/mac/platform.rs    | 28 ++++------
crates/gpui/src/platform/mac/status_item.rs |  4 
crates/gpui/src/platform/mac/window.rs      | 59 ++++++++++------------
crates/gpui/src/platform/test.rs            |  6 +-
crates/gpui/src/presenter.rs                | 12 +---
7 files changed, 54 insertions(+), 65 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -866,10 +866,12 @@ impl MutableAppContext {
         }
     }
 
-    pub fn screen_position(&self, window_id: usize, view_position: &Vector2F) -> Option<Vector2F> {
+    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<Item = usize> + '_ {

crates/gpui/src/platform.rs 🔗

@@ -64,7 +64,7 @@ pub trait Platform: Send + Sync {
     fn read_credentials(&self, url: &str) -> Result<Option<(String, Vec<u8>)>>;
     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<dyn FnMut()>);
-    fn screen_position(&self, view_position: &Vector2F) -> Vector2F;
+    fn is_topmost_for_position(&self, position: Vector2F) -> bool;
 }
 
 #[derive(Debug)]

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];
         }
     }
 

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
     }
 }
 

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<usize> {
-        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
+            }
         }
     }
 }

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<dyn FnMut()>) {}
 
-    fn screen_position(&self, view_position: &Vector2F) -> Vector2F {
-        view_position.clone()
+    fn is_topmost_for_position(&self, _position: Vector2F) -> bool {
+        true
     }
 }
 

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 {