mirror of
https://github.com/zed-industries/zed.git
synced 2024-10-23 23:09:42 +00:00
Fix positioning of windows on secondary displays (#4169)
CGDisplayBounds returns data in "global display coordinates" (which are the same as Zed's coordinates), different from the NS APIs which use "screen coordinates" (which have the Y axis inverted) Also remove some transmutes while we're at it Release Notes: - Fixed position of notifications on secondary displays
This commit is contained in:
commit
ac350e9d50
2 changed files with 34 additions and 27 deletions
|
@ -3,13 +3,10 @@ use anyhow::Result;
|
|||
use cocoa::{
|
||||
appkit::NSScreen,
|
||||
base::{id, nil},
|
||||
foundation::{NSDictionary, NSString},
|
||||
foundation::{NSDictionary, NSPoint, NSRect, NSSize, NSString},
|
||||
};
|
||||
use core_foundation::uuid::{CFUUIDGetUUIDBytes, CFUUIDRef};
|
||||
use core_graphics::{
|
||||
display::{CGDirectDisplayID, CGDisplayBounds, CGGetActiveDisplayList},
|
||||
geometry::{CGPoint, CGRect, CGSize},
|
||||
};
|
||||
use core_graphics::display::{CGDirectDisplayID, CGDisplayBounds, CGGetActiveDisplayList};
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -77,14 +74,14 @@ extern "C" {
|
|||
fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
|
||||
}
|
||||
|
||||
/// Convert the given rectangle from CoreGraphics' native coordinate space to GPUI's coordinate space.
|
||||
/// Convert the given rectangle from Cocoa's coordinate space to GPUI's coordinate space.
|
||||
///
|
||||
/// CoreGraphics' coordinate space has its origin at the bottom left of the primary screen,
|
||||
/// Cocoa's coordinate space has its origin at the bottom left of the primary screen,
|
||||
/// with the Y axis pointing upwards.
|
||||
///
|
||||
/// Conversely, in GPUI's coordinate system, the origin is placed at the top left of the primary
|
||||
/// screen, with the Y axis pointing downwards.
|
||||
pub(crate) fn display_bounds_from_native(rect: CGRect) -> Bounds<GlobalPixels> {
|
||||
/// screen, with the Y axis pointing downwards (matching CoreGraphics)
|
||||
pub(crate) fn global_bounds_from_ns_rect(rect: NSRect) -> Bounds<GlobalPixels> {
|
||||
let primary_screen_size = unsafe { CGDisplayBounds(MacDisplay::primary().id().0) }.size;
|
||||
|
||||
Bounds {
|
||||
|
@ -101,22 +98,22 @@ pub(crate) fn display_bounds_from_native(rect: CGRect) -> Bounds<GlobalPixels> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert the given rectangle from GPUI's coordinate system to CoreGraphics' native coordinate space.
|
||||
/// Convert the given rectangle from GPUI's coordinate system to Cocoa's native coordinate space.
|
||||
///
|
||||
/// CoreGraphics' coordinate space has its origin at the bottom left of the primary screen,
|
||||
/// Cocoa's coordinate space has its origin at the bottom left of the primary screen,
|
||||
/// with the Y axis pointing upwards.
|
||||
///
|
||||
/// Conversely, in GPUI's coordinate system, the origin is placed at the top left of the primary
|
||||
/// screen, with the Y axis pointing downwards.
|
||||
pub(crate) fn display_bounds_to_native(bounds: Bounds<GlobalPixels>) -> CGRect {
|
||||
/// screen, with the Y axis pointing downwards (matching CoreGraphics)
|
||||
pub(crate) fn global_bounds_to_ns_rect(bounds: Bounds<GlobalPixels>) -> NSRect {
|
||||
let primary_screen_height = MacDisplay::primary().bounds().size.height;
|
||||
|
||||
CGRect::new(
|
||||
&CGPoint::new(
|
||||
NSRect::new(
|
||||
NSPoint::new(
|
||||
bounds.origin.x.into(),
|
||||
(primary_screen_height - bounds.origin.y - bounds.size.height).into(),
|
||||
),
|
||||
&CGSize::new(bounds.size.width.into(), bounds.size.height.into()),
|
||||
NSSize::new(bounds.size.width.into(), bounds.size.height.into()),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -155,8 +152,20 @@ impl PlatformDisplay for MacDisplay {
|
|||
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
unsafe {
|
||||
let native_bounds = CGDisplayBounds(self.0);
|
||||
display_bounds_from_native(native_bounds)
|
||||
// CGDisplayBounds is in "global display" coordinates, where 0 is
|
||||
// the top left of the primary display.
|
||||
let bounds = CGDisplayBounds(self.0);
|
||||
|
||||
Bounds {
|
||||
origin: point(
|
||||
GlobalPixels(bounds.origin.x as f32),
|
||||
GlobalPixels(bounds.origin.y as f32),
|
||||
),
|
||||
size: size(
|
||||
GlobalPixels(bounds.size.width as f32),
|
||||
GlobalPixels(bounds.size.height as f32),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{display_bounds_from_native, ns_string, MacDisplay, MetalRenderer, NSRange};
|
||||
use super::{global_bounds_from_ns_rect, ns_string, MacDisplay, MetalRenderer, NSRange};
|
||||
use crate::{
|
||||
display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, ExternalPaths,
|
||||
global_bounds_to_ns_rect, point, px, size, AnyWindowHandle, Bounds, ExternalPaths,
|
||||
FileDropEvent, ForegroundExecutor, GlobalPixels, KeyDownEvent, Keystroke, Modifiers,
|
||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
|
||||
PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,
|
||||
|
@ -411,10 +411,8 @@ impl MacWindowState {
|
|||
}
|
||||
|
||||
fn frame(&self) -> Bounds<GlobalPixels> {
|
||||
unsafe {
|
||||
let frame = NSWindow::frame(self.native_window);
|
||||
display_bounds_from_native(mem::transmute::<NSRect, CGRect>(frame))
|
||||
}
|
||||
let frame = unsafe { NSWindow::frame(self.native_window) };
|
||||
global_bounds_from_ns_rect(frame)
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
|
@ -650,11 +648,11 @@ impl MacWindow {
|
|||
WindowBounds::Fixed(bounds) => {
|
||||
let display_bounds = display.bounds();
|
||||
let frame = if bounds.intersects(&display_bounds) {
|
||||
display_bounds_to_native(bounds)
|
||||
global_bounds_to_ns_rect(bounds)
|
||||
} else {
|
||||
display_bounds_to_native(display_bounds)
|
||||
global_bounds_to_ns_rect(display_bounds)
|
||||
};
|
||||
native_window.setFrame_display_(mem::transmute::<CGRect, NSRect>(frame), YES);
|
||||
native_window.setFrame_display_(frame, YES);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue