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 38c3aba045..f5c947019f 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 } }) }