From 97ccb16c97bd9da0fdb2e04b44e9a914adc967b2 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Sep 2022 16:20:34 +0200 Subject: [PATCH] Rework status bar item to use a custom view --- .../src/contacts_status_item.rs | 7 +- crates/gpui/src/platform/mac/status_item.rs | 102 ++++++++++++------ 2 files changed, 75 insertions(+), 34 deletions(-) diff --git a/crates/contacts_status_item/src/contacts_status_item.rs b/crates/contacts_status_item/src/contacts_status_item.rs index 928eecb8fe27d128a8d7b5074d8ffa5989eb0a5a..5905c9ad12854fccaf1c4333497afac410ede006 100644 --- a/crates/contacts_status_item/src/contacts_status_item.rs +++ b/crates/contacts_status_item/src/contacts_status_item.rs @@ -21,8 +21,11 @@ impl View for ContactsStatusItem { }) .boxed() }) - .on_down(gpui::MouseButton::Left, |_, cx| {}) - .on_up(gpui::MouseButton::Left, |_, cx| {}) + .on_down(gpui::MouseButton::Left, |_, _| {}) + .on_down_out(gpui::MouseButton::Left, |_, _| {}) + .on_up(gpui::MouseButton::Left, |_, _| {}) + .on_up_out(gpui::MouseButton::Left, |_, _| {}) + .aligned() .contained() .with_background_color(Color::green()) .boxed() diff --git a/crates/gpui/src/platform/mac/status_item.rs b/crates/gpui/src/platform/mac/status_item.rs index 9c08917927999401211e3416c7f383889f60eb74..c369ab424523938b45c515f6d19d8e77a58af3e3 100644 --- a/crates/gpui/src/platform/mac/status_item.rs +++ b/crates/gpui/src/platform/mac/status_item.rs @@ -1,15 +1,12 @@ use crate::{ geometry::vector::{vec2f, Vector2F}, platform::{self, mac::renderer::Renderer}, - Event, FontSystem, Scene, Window, + Event, FontSystem, Scene, }; use cocoa::{ - appkit::{ - NSApplication, NSButton, NSEventMask, NSSquareStatusItemLength, NSStatusBar, NSStatusItem, - NSView, NSViewHeightSizable, NSViewWidthSizable, NSWindow, - }, + appkit::{NSSquareStatusItemLength, NSStatusBar, NSStatusItem, NSView, NSWindow}, base::{id, nil, YES}, - foundation::{NSSize, NSUInteger}, + foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize}, }; use ctor::ctor; use foreign_types::ForeignTypeRef; @@ -29,21 +26,56 @@ use std::{ sync::Arc, }; -static mut HANDLER_CLASS: *const Class = ptr::null(); +static mut VIEW_CLASS: *const Class = ptr::null(); const STATE_IVAR: &str = "state"; #[ctor] unsafe fn build_classes() { - HANDLER_CLASS = { - let mut decl = ClassDecl::new("GPUIStatusItemEventHandler", class!(NSObject)).unwrap(); + VIEW_CLASS = { + let mut decl = ClassDecl::new("GPUIStatusItemView", class!(NSView)).unwrap(); decl.add_ivar::<*mut c_void>(STATE_IVAR); + + decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel)); + + decl.add_method( + sel!(mouseDown:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(mouseUp:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(rightMouseDown:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(rightMouseUp:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(otherMouseDown:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(otherMouseUp:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); decl.add_method( - sel!(dealloc), - dealloc_handler as extern "C" fn(&Object, Sel), + sel!(mouseMoved:), + handle_view_event as extern "C" fn(&Object, Sel, id), ); decl.add_method( - sel!(handleEvent), - handle_event as extern "C" fn(&Object, Sel), + sel!(mouseDragged:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(scrollWheel:), + handle_view_event as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(flagsChanged:), + handle_view_event as extern "C" fn(&Object, Sel, id), ); decl.register() @@ -56,36 +88,39 @@ struct StatusItemState { native_item: StrongPtr, renderer: Renderer, event_callback: Option bool>>, - _event_handler: StrongPtr, } impl StatusItem { pub fn add(fonts: Arc) -> Self { unsafe { + let pool = NSAutoreleasePool::new(nil); + let renderer = Renderer::new(false, fonts); let status_bar = NSStatusBar::systemStatusBar(nil); let native_item = StrongPtr::retain(status_bar.statusItemWithLength_(NSSquareStatusItemLength)); let button = native_item.button(); - button.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable); - button.setWantsBestResolutionOpenGLSurface_(YES); - button.setLayer(renderer.layer().as_ptr() as id); + let _: () = msg_send![button, setHidden: YES]; let item = Self(Rc::new_cyclic(|state| { - let event_handler = StrongPtr::new(msg_send![HANDLER_CLASS, alloc]); - let _: () = msg_send![*event_handler, init]; - (**event_handler) - .set_ivar(STATE_IVAR, Weak::into_raw(state.clone()) as *const c_void); - button.setTarget_(*event_handler); - button.setAction_(sel!(handleEvent)); - let _: () = msg_send![button, sendActionOn: NSEventMask::NSAnyEventMask]; + let parent_view = button.superview().superview(); + + let view: id = msg_send![VIEW_CLASS, alloc]; + NSView::initWithFrame_( + view, + NSRect::new(NSPoint::new(0., 0.), NSView::frame(parent_view).size), + ); + view.setWantsBestResolutionOpenGLSurface_(YES); + view.setLayer(renderer.layer().as_ptr() as id); + view.setWantsLayer(true); + (*view).set_ivar(STATE_IVAR, Weak::into_raw(state.clone()) as *const c_void); + parent_view.addSubview_(view.autorelease()); RefCell::new(StatusItemState { native_item, renderer, event_callback: None, - _event_handler: event_handler, }) })); @@ -98,6 +133,8 @@ impl StatusItem { layer.set_drawable_size(metal::CGSize::new(size.x().into(), size.y().into())); } + pool.drain(); + item } } @@ -192,8 +229,11 @@ impl platform::Window for StatusItem { impl StatusItemState { fn size(&self) -> Vector2F { - let NSSize { width, height, .. } = unsafe { NSView::frame(self.native_item.button()) }.size; - vec2f(width as f32, height as f32) + unsafe { + let NSSize { width, height, .. } = + NSWindow::frame(self.native_item.button().superview().superview()).size; + vec2f(width as f32, height as f32) + } } fn scale_factor(&self) -> f32 { @@ -204,19 +244,17 @@ impl StatusItemState { } } -extern "C" fn dealloc_handler(this: &Object, _: Sel) { +extern "C" fn dealloc_view(this: &Object, _: Sel) { unsafe { drop_state(this); - let _: () = msg_send![super(this, class!(NSObject)), dealloc]; + let _: () = msg_send![super(this, class!(NSView)), dealloc]; } } -extern "C" fn handle_event(this: &Object, _: Sel) { +extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) { unsafe { if let Some(state) = get_state(this).upgrade() { let mut state_borrow = state.as_ref().borrow_mut(); - let app = NSApplication::sharedApplication(nil); - let native_event: id = msg_send![app, currentEvent]; if let Some(event) = Event::from_native(native_event, Some(state_borrow.size().y())) { if let Some(mut callback) = state_borrow.event_callback.take() { drop(state_borrow);