From d08ec438ed029955b325654a891a13dd10bc8341 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 7 Sep 2021 18:37:45 +0200 Subject: [PATCH] Make titlebar taller and position traffic lights accordingly Co-Authored-By: Nathan Sobo --- gpui/src/platform.rs | 2 ++ gpui/src/platform/mac/window.rs | 63 +++++++++++++++++++++++++++++++-- zed/src/workspace.rs | 3 +- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/gpui/src/platform.rs b/gpui/src/platform.rs index dec7db9103..a4c86eab2f 100644 --- a/gpui/src/platform.rs +++ b/gpui/src/platform.rs @@ -105,6 +105,7 @@ pub struct WindowOptions<'a> { pub bounds: RectF, pub title: Option<&'a str>, pub titlebar_appears_transparent: bool, + pub traffic_light_position: Option, } pub struct PathPromptOptions { @@ -155,6 +156,7 @@ impl<'a> Default for WindowOptions<'a> { bounds: RectF::new(Default::default(), vec2f(1024.0, 768.0)), title: Default::default(), titlebar_appears_transparent: Default::default(), + traffic_light_position: Default::default(), } } } diff --git a/gpui/src/platform/mac/window.rs b/gpui/src/platform/mac/window.rs index bcdb61241c..e960107a99 100644 --- a/gpui/src/platform/mac/window.rs +++ b/gpui/src/platform/mac/window.rs @@ -8,8 +8,8 @@ use crate::{ use block::ConcreteBlock; use cocoa::{ appkit::{ - NSApplication, NSBackingStoreBuffered, NSScreen, NSView, NSViewHeightSizable, - NSViewWidthSizable, NSWindow, NSWindowStyleMask, + CGPoint, NSApplication, NSBackingStoreBuffered, NSScreen, NSView, NSViewHeightSizable, + NSViewWidthSizable, NSWindow, NSWindowButton, NSWindowStyleMask, }, base::{id, nil}, foundation::{NSAutoreleasePool, NSInteger, NSSize, NSString}, @@ -66,6 +66,10 @@ unsafe fn build_classes() { sel!(sendEvent:), send_event as extern "C" fn(&Object, Sel, id), ); + decl.add_method( + sel!(windowDidResize:), + window_did_resize as extern "C" fn(&Object, Sel, id), + ); decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel)); decl.register() }; @@ -139,6 +143,7 @@ struct WindowState { command_queue: metal::CommandQueue, last_fresh_keydown: Option<(Keystroke, String)>, layer: id, + traffic_light_position: Option, } impl Window { @@ -204,12 +209,14 @@ impl Window { command_queue: device.new_command_queue(), last_fresh_keydown: None, layer, + traffic_light_position: options.traffic_light_position, }))); (*native_window).set_ivar( WINDOW_STATE_IVAR, Rc::into_raw(window.0.clone()) as *const c_void, ); + native_window.setDelegate_(native_window); (*native_view).set_ivar( WINDOW_STATE_IVAR, Rc::into_raw(window.0.clone()) as *const c_void, @@ -243,6 +250,7 @@ impl Window { native_window.center(); native_window.makeKeyAndOrderFront_(nil); + window.0.borrow().move_traffic_light(); pool.drain(); window @@ -343,6 +351,52 @@ impl platform::WindowContext for Window { } } +impl WindowState { + fn move_traffic_light(&self) { + if let Some(traffic_light_position) = self.traffic_light_position { + let titlebar_height = self.titlebar_height(); + + unsafe { + let close_button: id = msg_send![ + self.native_window, + standardWindowButton: NSWindowButton::NSWindowCloseButton + ]; + let min_button: id = msg_send![ + self.native_window, + standardWindowButton: NSWindowButton::NSWindowMiniaturizeButton + ]; + let zoom_button: id = msg_send![ + self.native_window, + standardWindowButton: NSWindowButton::NSWindowZoomButton + ]; + + let mut close_button_frame: CGRect = msg_send![close_button, frame]; + let mut min_button_frame: CGRect = msg_send![min_button, frame]; + let mut zoom_button_frame: CGRect = msg_send![zoom_button, frame]; + let mut origin = vec2f( + traffic_light_position.x(), + titlebar_height + - traffic_light_position.y() + - close_button_frame.size.height as f32, + ); + let button_spacing = + (min_button_frame.origin.x - close_button_frame.origin.x) as f32; + + close_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64); + let _: () = msg_send![close_button, setFrame: close_button_frame]; + origin.set_x(origin.x() + button_spacing); + + min_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64); + let _: () = msg_send![min_button, setFrame: min_button_frame]; + origin.set_x(origin.x() + button_spacing); + + zoom_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64); + let _: () = msg_send![zoom_button, setFrame: zoom_button_frame]; + } + } + } +} + impl platform::WindowContext for WindowState { fn size(&self) -> Vector2F { let NSSize { width, height, .. } = @@ -462,6 +516,11 @@ extern "C" fn send_event(this: &Object, _: Sel, native_event: id) { } } +extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) { + let window_state = unsafe { get_window_state(this) }; + window_state.as_ref().borrow().move_traffic_light(); +} + extern "C" fn close_window(this: &Object, _: Sel) { unsafe { let close_callback = { diff --git a/zed/src/workspace.rs b/zed/src/workspace.rs index 95050ca607..1b7b9226d0 100644 --- a/zed/src/workspace.rs +++ b/zed/src/workspace.rs @@ -142,6 +142,7 @@ fn window_options() -> WindowOptions<'static> { bounds: RectF::new(vec2f(0., 0.), vec2f(1024., 768.)), title: None, titlebar_appears_transparent: true, + traffic_light_position: Some(vec2f(8., 8.)), } } @@ -952,7 +953,7 @@ impl View for Workspace { Flex::column() .with_child( ConstrainedBox::new(Empty::new().boxed()) - .with_height(cx.titlebar_height) + .with_height(32.) .named("titlebar"), ) .with_child(