mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
Rework status bar item to use a custom view
This commit is contained in:
parent
a102b3ba4b
commit
97ccb16c97
2 changed files with 75 additions and 34 deletions
|
@ -21,8 +21,11 @@ impl View for ContactsStatusItem {
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_down(gpui::MouseButton::Left, |_, cx| {})
|
.on_down(gpui::MouseButton::Left, |_, _| {})
|
||||||
.on_up(gpui::MouseButton::Left, |_, cx| {})
|
.on_down_out(gpui::MouseButton::Left, |_, _| {})
|
||||||
|
.on_up(gpui::MouseButton::Left, |_, _| {})
|
||||||
|
.on_up_out(gpui::MouseButton::Left, |_, _| {})
|
||||||
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
.with_background_color(Color::green())
|
.with_background_color(Color::green())
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::vector::{vec2f, Vector2F},
|
geometry::vector::{vec2f, Vector2F},
|
||||||
platform::{self, mac::renderer::Renderer},
|
platform::{self, mac::renderer::Renderer},
|
||||||
Event, FontSystem, Scene, Window,
|
Event, FontSystem, Scene,
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{
|
appkit::{NSSquareStatusItemLength, NSStatusBar, NSStatusItem, NSView, NSWindow},
|
||||||
NSApplication, NSButton, NSEventMask, NSSquareStatusItemLength, NSStatusBar, NSStatusItem,
|
|
||||||
NSView, NSViewHeightSizable, NSViewWidthSizable, NSWindow,
|
|
||||||
},
|
|
||||||
base::{id, nil, YES},
|
base::{id, nil, YES},
|
||||||
foundation::{NSSize, NSUInteger},
|
foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize},
|
||||||
};
|
};
|
||||||
use ctor::ctor;
|
use ctor::ctor;
|
||||||
use foreign_types::ForeignTypeRef;
|
use foreign_types::ForeignTypeRef;
|
||||||
|
@ -29,21 +26,56 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut HANDLER_CLASS: *const Class = ptr::null();
|
static mut VIEW_CLASS: *const Class = ptr::null();
|
||||||
const STATE_IVAR: &str = "state";
|
const STATE_IVAR: &str = "state";
|
||||||
|
|
||||||
#[ctor]
|
#[ctor]
|
||||||
unsafe fn build_classes() {
|
unsafe fn build_classes() {
|
||||||
HANDLER_CLASS = {
|
VIEW_CLASS = {
|
||||||
let mut decl = ClassDecl::new("GPUIStatusItemEventHandler", class!(NSObject)).unwrap();
|
let mut decl = ClassDecl::new("GPUIStatusItemView", class!(NSView)).unwrap();
|
||||||
decl.add_ivar::<*mut c_void>(STATE_IVAR);
|
decl.add_ivar::<*mut c_void>(STATE_IVAR);
|
||||||
|
|
||||||
|
decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel));
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(dealloc),
|
sel!(mouseDown:),
|
||||||
dealloc_handler as extern "C" fn(&Object, Sel),
|
handle_view_event as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(handleEvent),
|
sel!(mouseUp:),
|
||||||
handle_event as extern "C" fn(&Object, Sel),
|
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!(mouseMoved:),
|
||||||
|
handle_view_event as extern "C" fn(&Object, Sel, id),
|
||||||
|
);
|
||||||
|
decl.add_method(
|
||||||
|
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()
|
decl.register()
|
||||||
|
@ -56,36 +88,39 @@ struct StatusItemState {
|
||||||
native_item: StrongPtr,
|
native_item: StrongPtr,
|
||||||
renderer: Renderer,
|
renderer: Renderer,
|
||||||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||||
_event_handler: StrongPtr,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatusItem {
|
impl StatusItem {
|
||||||
pub fn add(fonts: Arc<dyn FontSystem>) -> Self {
|
pub fn add(fonts: Arc<dyn FontSystem>) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let pool = NSAutoreleasePool::new(nil);
|
||||||
|
|
||||||
let renderer = Renderer::new(false, fonts);
|
let renderer = Renderer::new(false, fonts);
|
||||||
let status_bar = NSStatusBar::systemStatusBar(nil);
|
let status_bar = NSStatusBar::systemStatusBar(nil);
|
||||||
let native_item =
|
let native_item =
|
||||||
StrongPtr::retain(status_bar.statusItemWithLength_(NSSquareStatusItemLength));
|
StrongPtr::retain(status_bar.statusItemWithLength_(NSSquareStatusItemLength));
|
||||||
|
|
||||||
let button = native_item.button();
|
let button = native_item.button();
|
||||||
button.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable);
|
let _: () = msg_send![button, setHidden: YES];
|
||||||
button.setWantsBestResolutionOpenGLSurface_(YES);
|
|
||||||
button.setLayer(renderer.layer().as_ptr() as id);
|
|
||||||
|
|
||||||
let item = Self(Rc::new_cyclic(|state| {
|
let item = Self(Rc::new_cyclic(|state| {
|
||||||
let event_handler = StrongPtr::new(msg_send![HANDLER_CLASS, alloc]);
|
let parent_view = button.superview().superview();
|
||||||
let _: () = msg_send![*event_handler, init];
|
|
||||||
(**event_handler)
|
let view: id = msg_send![VIEW_CLASS, alloc];
|
||||||
.set_ivar(STATE_IVAR, Weak::into_raw(state.clone()) as *const c_void);
|
NSView::initWithFrame_(
|
||||||
button.setTarget_(*event_handler);
|
view,
|
||||||
button.setAction_(sel!(handleEvent));
|
NSRect::new(NSPoint::new(0., 0.), NSView::frame(parent_view).size),
|
||||||
let _: () = msg_send![button, sendActionOn: NSEventMask::NSAnyEventMask];
|
);
|
||||||
|
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 {
|
RefCell::new(StatusItemState {
|
||||||
native_item,
|
native_item,
|
||||||
renderer,
|
renderer,
|
||||||
event_callback: None,
|
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()));
|
layer.set_drawable_size(metal::CGSize::new(size.x().into(), size.y().into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pool.drain();
|
||||||
|
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,8 +229,11 @@ impl platform::Window for StatusItem {
|
||||||
|
|
||||||
impl StatusItemState {
|
impl StatusItemState {
|
||||||
fn size(&self) -> Vector2F {
|
fn size(&self) -> Vector2F {
|
||||||
let NSSize { width, height, .. } = unsafe { NSView::frame(self.native_item.button()) }.size;
|
unsafe {
|
||||||
vec2f(width as f32, height as f32)
|
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 {
|
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 {
|
unsafe {
|
||||||
drop_state(this);
|
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 {
|
unsafe {
|
||||||
if let Some(state) = get_state(this).upgrade() {
|
if let Some(state) = get_state(this).upgrade() {
|
||||||
let mut state_borrow = state.as_ref().borrow_mut();
|
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(event) = Event::from_native(native_event, Some(state_borrow.size().y())) {
|
||||||
if let Some(mut callback) = state_borrow.event_callback.take() {
|
if let Some(mut callback) = state_borrow.event_callback.take() {
|
||||||
drop(state_borrow);
|
drop(state_borrow);
|
||||||
|
|
Loading…
Reference in a new issue