diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index e5b0f71ff3..12338b75fb 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1774,11 +1774,13 @@ impl MutableAppContext { presenter.borrow().dispatch_path(cx.as_ref()), keystroke, ) { - return; + return true; } } - presenter.borrow_mut().dispatch_event(event, cx); + presenter.borrow_mut().dispatch_event(event, cx) + } else { + false } }) })); diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 10de12fbe1..6d841f3962 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -90,7 +90,7 @@ pub trait Dispatcher: Send + Sync { pub trait Window: WindowContext { fn as_any_mut(&mut self) -> &mut dyn Any; - fn on_event(&mut self, callback: Box); + fn on_event(&mut self, callback: Box bool>); fn on_active_status_change(&mut self, callback: Box); fn on_resize(&mut self, callback: Box); fn on_close(&mut self, callback: Box); diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 5d6848cd7b..ac5073d893 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -92,8 +92,8 @@ unsafe fn build_classes() { decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel)); decl.add_method( - sel!(keyDown:), - handle_view_event as extern "C" fn(&Object, Sel, id), + sel!(performKeyEquivalent:), + handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL, ); decl.add_method( sel!(mouseDown:), @@ -164,7 +164,7 @@ pub struct Window(Rc>); struct WindowState { id: usize, native_window: id, - event_callback: Option>, + event_callback: Option bool>>, activate_callback: Option>, resize_callback: Option>, close_callback: Option>, @@ -331,7 +331,7 @@ impl platform::Window for Window { self } - fn on_event(&mut self, callback: Box) { + fn on_event(&mut self, callback: Box bool>) { self.0.as_ref().borrow_mut().event_callback = Some(callback); } @@ -528,6 +528,45 @@ extern "C" fn dealloc_view(this: &Object, _: Sel) { } } +extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) -> BOOL { + let window_state = unsafe { get_window_state(this) }; + let mut window_state_borrow = window_state.as_ref().borrow_mut(); + + let event = unsafe { Event::from_native(native_event, Some(window_state_borrow.size().y())) }; + if let Some(event) = event { + match &event { + Event::KeyDown { + keystroke, + input, + is_held, + } => { + let keydown = (keystroke.clone(), input.clone()); + // Ignore events from held-down keys after some of the initially-pressed keys + // were released. + if *is_held { + if window_state_borrow.last_fresh_keydown.as_ref() != Some(&keydown) { + return YES; + } + } else { + window_state_borrow.last_fresh_keydown = Some(keydown); + } + } + _ => return NO, + } + + if let Some(mut callback) = window_state_borrow.event_callback.take() { + drop(window_state_borrow); + let handled = callback(event); + window_state.borrow_mut().event_callback = Some(callback); + handled as BOOL + } else { + NO + } + } else { + NO + } +} + extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) { let window_state = unsafe { get_window_state(this) }; let weak_window_state = Rc::downgrade(&window_state); @@ -551,24 +590,6 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) { Event::LeftMouseUp { .. } => { window_state_borrow.synthetic_drag_counter += 1; } - - // Ignore events from held-down keys after some of the initially-pressed keys - // were released. - Event::KeyDown { - input, - keystroke, - is_held, - } => { - let keydown = (keystroke.clone(), input.clone()); - if *is_held { - if window_state_borrow.last_fresh_keydown.as_ref() != Some(&keydown) { - return; - } - } else { - window_state_borrow.last_fresh_keydown = Some(keydown); - } - } - _ => {} } diff --git a/crates/gpui/src/platform/test.rs b/crates/gpui/src/platform/test.rs index e22db89e3b..b1b460ff70 100644 --- a/crates/gpui/src/platform/test.rs +++ b/crates/gpui/src/platform/test.rs @@ -34,7 +34,7 @@ pub struct Window { size: Vector2F, scale_factor: f32, current_scene: Option, - event_handlers: Vec>, + event_handlers: Vec bool>>, resize_handlers: Vec>, close_handlers: Vec>, pub(crate) title: Option, @@ -233,7 +233,7 @@ impl super::Window for Window { self } - fn on_event(&mut self, callback: Box) { + fn on_event(&mut self, callback: Box bool>) { self.event_handlers.push(callback); } diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index eb7f351444..4b0050e943 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -224,7 +224,7 @@ impl Presenter { } } - pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) { + pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) -> bool { if let Some(root_view_id) = cx.root_view_id(self.window_id) { let mut invalidated_views = Vec::new(); let mut mouse_down_out_handlers = Vec::new(); @@ -366,7 +366,7 @@ impl Presenter { } if !handled { - event_cx.dispatch_event(root_view_id, &event); + handled = event_cx.dispatch_event(root_view_id, &event); } invalidated_views.extend(event_cx.invalidated_views); @@ -384,6 +384,10 @@ impl Presenter { } cx.dispatch_action_any(self.window_id, &dispatch_path, directive.action.as_ref()); } + + handled + } else { + false } }