Fix invalid translation between bottom/top left coordinate spaces

Antonio Scandurra and Mikayla Maki created

Co-Authored-By: Mikayla Maki <mikayla@zed.dev>

Change summary

crates/gpui/src/platform/mac/geometry.rs | 53 +------------------------
crates/gpui/src/platform/mac/window.rs   | 31 ++++++++++++--
2 files changed, 29 insertions(+), 55 deletions(-)

Detailed changes

crates/gpui/src/platform/mac/geometry.rs 🔗

@@ -1,7 +1,6 @@
 use cocoa::{
-    appkit::NSWindow,
     base::id,
-    foundation::{NSPoint, NSRect, NSSize},
+    foundation::{NSPoint, NSRect},
 };
 use objc::{msg_send, sel, sel_impl};
 use pathfinder_geometry::{
@@ -25,61 +24,15 @@ impl Vector2FExt for Vector2F {
     }
 }
 
-pub trait RectFExt {
-    /// Converts self to an NSRect with y axis pointing up.
-    /// The resulting NSRect will have an origin at the bottom left of the rectangle.
-    /// Also takes care of converting from window scaled coordinates to screen coordinates
-    fn to_screen_ns_rect(&self, native_window: id) -> NSRect;
-
-    /// Converts self to an NSRect with y axis point up.
-    /// The resulting NSRect will have an origin at the bottom left of the rectangle.
-    /// Unlike to_screen_ns_rect, coordinates are not converted and are assumed to already be in screen scale
-    fn to_ns_rect(&self) -> NSRect;
-}
-impl RectFExt for RectF {
-    fn to_screen_ns_rect(&self, native_window: id) -> NSRect {
-        unsafe { native_window.convertRectToScreen_(self.to_ns_rect()) }
-    }
-
-    fn to_ns_rect(&self) -> NSRect {
-        NSRect::new(
-            NSPoint::new(
-                self.origin_x() as f64,
-                -(self.origin_y() + self.height()) as f64,
-            ),
-            NSSize::new(self.width() as f64, self.height() as f64),
-        )
-    }
-}
-
 pub trait NSRectExt {
-    /// Converts self to a RectF with y axis pointing down.
-    /// The resulting RectF will have an origin at the top left of the rectangle.
-    /// Also takes care of converting from screen scale coordinates to window coordinates
-    fn to_window_rectf(&self, native_window: id) -> RectF;
-
-    /// Converts self to a RectF with y axis pointing down.
-    /// The resulting RectF will have an origin at the top left of the rectangle.
-    /// Unlike to_screen_ns_rect, coordinates are not converted and are assumed to already be in screen scale
     fn to_rectf(&self) -> RectF;
-
     fn intersects(&self, other: Self) -> bool;
 }
-impl NSRectExt for NSRect {
-    fn to_window_rectf(&self, native_window: id) -> RectF {
-        unsafe {
-            self.origin.x;
-            let rect: NSRect = native_window.convertRectFromScreen_(*self);
-            rect.to_rectf()
-        }
-    }
 
+impl NSRectExt for NSRect {
     fn to_rectf(&self) -> RectF {
         RectF::new(
-            vec2f(
-                self.origin.x as f32,
-                -(self.origin.y + self.size.height) as f32,
-            ),
+            vec2f(self.origin.x as f32, self.origin.y as f32),
             vec2f(self.size.width as f32, self.size.height as f32),
         )
     }

crates/gpui/src/platform/mac/window.rs 🔗

@@ -8,7 +8,7 @@ use crate::{
     mac::platform::NSViewLayerContentsRedrawDuringViewResize,
     platform::{
         self,
-        mac::{geometry::RectFExt, renderer::Renderer, screen::Screen},
+        mac::{renderer::Renderer, screen::Screen},
         Event, WindowBounds,
     },
     InputHandler, KeyDownEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
@@ -372,7 +372,8 @@ impl WindowState {
             }
 
             let window_frame = self.frame();
-            if window_frame == self.native_window.screen().visibleFrame().to_rectf() {
+            let screen_frame = self.native_window.screen().visibleFrame().to_rectf();
+            if window_frame.size() == screen_frame.size() {
                 WindowBounds::Maximized
             } else {
                 WindowBounds::Fixed(window_frame)
@@ -383,8 +384,19 @@ impl WindowState {
     // Returns the window bounds in window coordinates
     fn frame(&self) -> RectF {
         unsafe {
-            let ns_frame = NSWindow::frame(self.native_window);
-            ns_frame.to_rectf()
+            let screen_frame = self.native_window.screen().visibleFrame();
+            let window_frame = NSWindow::frame(self.native_window);
+            RectF::new(
+                vec2f(
+                    window_frame.origin.x as f32,
+                    (screen_frame.size.height - window_frame.origin.y - window_frame.size.height)
+                        as f32,
+                ),
+                vec2f(
+                    window_frame.size.width as f32,
+                    window_frame.size.height as f32,
+                ),
+            )
         }
     }
 
@@ -472,7 +484,16 @@ impl Window {
                 }
                 WindowBounds::Fixed(rect) => {
                     let screen_frame = screen.visibleFrame();
-                    let ns_rect = rect.to_ns_rect();
+                    let ns_rect = NSRect::new(
+                        NSPoint::new(
+                            rect.origin_x() as f64,
+                            screen_frame.size.height
+                                - rect.origin_y() as f64
+                                - rect.height() as f64,
+                        ),
+                        NSSize::new(rect.width() as f64, rect.height() as f64),
+                    );
+
                     dbg!(screen_frame.as_CGRect(), ns_rect.as_CGRect());
                     if ns_rect.intersects(screen_frame) {
                         native_window.setFrame_display_(ns_rect, YES);