From cd65031cda46d859db1b23faf3d32aaaaed13c9c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 18 Dec 2021 08:12:08 -0700 Subject: [PATCH] Halt keystroke dispatch immediately when we call a global action handler Someday, we may want to define a global action context that allows us to propagate the action, but this isn't currently supported. Previous to this commit, we were invoking the same global action handler multiple times, once for each view in the responder chain. --- crates/gpui/src/app.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 38c3aba045c4771e8476dd0231f44eaa6a278301..f5c947019fe59f22a56a41b41b9b1b0de8548441 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -667,7 +667,7 @@ pub struct MutableAppContext { assets: Arc, cx: AppContext, actions: HashMap>>>, - global_actions: HashMap>>, + global_actions: HashMap>, keystroke_matcher: keymap::Matcher, next_entity_id: usize, next_window_id: usize, @@ -838,10 +838,13 @@ impl MutableAppContext { handler(action, cx); }); - self.global_actions - .entry(TypeId::of::()) - .or_default() - .push(handler); + if self + .global_actions + .insert(TypeId::of::(), handler) + .is_some() + { + panic!("registered multiple global handlers for the same action type"); + } } pub fn window_ids(&self) -> impl Iterator + '_ { @@ -1125,7 +1128,7 @@ impl MutableAppContext { } if !halted_dispatch { - this.dispatch_global_action_any(action); + halted_dispatch = this.dispatch_global_action_any(action); } halted_dispatch }) @@ -1135,13 +1138,14 @@ impl MutableAppContext { self.dispatch_global_action_any(&action); } - fn dispatch_global_action_any(&mut self, action: &dyn AnyAction) { + fn dispatch_global_action_any(&mut self, action: &dyn AnyAction) -> bool { self.update(|this| { - if let Some((name, mut handlers)) = this.global_actions.remove_entry(&action.id()) { - for handler in handlers.iter_mut().rev() { - handler(action, this); - } - this.global_actions.insert(name, handlers); + if let Some((name, mut handler)) = this.global_actions.remove_entry(&action.id()) { + handler(action, this); + this.global_actions.insert(name, handler); + true + } else { + false } }) }