Detailed changes
@@ -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<Item = usize> + '_ {
self.cx.windows.keys().cloned()
}
@@ -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<dyn FnMut()>);
+ fn is_topmost_for_position(&self, position: Vector2F) -> bool;
}
#[derive(Debug)]
@@ -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),
@@ -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],
@@ -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 {
@@ -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<dyn FnMut()>) {
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 | 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
+ }
+ }
+ }
}
impl WindowState {
@@ -332,6 +332,10 @@ impl super::Window for Window {
}
fn on_appearance_changed(&mut self, _: Box<dyn FnMut()>) {}
+
+ fn is_topmost_for_position(&self, _position: Vector2F) -> bool {
+ true
+ }
}
pub fn platform() -> Platform {
@@ -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() {
@@ -209,6 +209,7 @@ impl EventDispatcher {
break;
}
}
+
cx.platform().set_cursor_style(style_to_assign);
if !event_reused {
@@ -100,7 +100,6 @@ actions!(
NewTerminal,
NewSearch,
Feedback,
- ShowNotif,
]
);