From 642fd36fdc86951b5fb475cc37405549582f873b Mon Sep 17 00:00:00 2001 From: "gcp-cherry-pick-bot[bot]" <98988430+gcp-cherry-pick-bot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:33:36 +0100 Subject: [PATCH] Fix dispatching global actions from a window (cherry-pick #9502) (#9504) Cherry-picked Fix dispatching global actions from a window (#9502) Fixes https://github.com/zed-industries/zed/issues/9313 Release Notes: - Fixed a regression that caused global actions to stop working when invoked from a window (preview-only) ([#9313](https://github.com/zed-industries/zed/issues/9313)). Co-authored-by: Conrad Co-authored-by: Antonio Scandurra Co-authored-by: Conrad --- crates/gpui/src/app.rs | 2 +- crates/gpui/src/window.rs | 60 +++++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 1c30f16199fa7bf11963fe9212e809c2a3012866..f8d0fda071282b3991e851eb63c409cdae329fab 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1144,7 +1144,7 @@ impl AppContext { } } - pub(crate) fn dispatch_global_action(&mut self, action: &dyn Action) { + fn dispatch_global_action(&mut self, action: &dyn Action) { self.propagate_event = true; if let Some(mut global_listeners) = self diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index c41c58fdba07948e4c68a3fb06ff41ea6ca3c098..27e58a629cfdf708fe0b3575cd902916b7d9e55f 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -696,7 +696,6 @@ impl<'a> WindowContext<'a> { let window = self.window.handle; self.app.defer(move |cx| { - cx.propagate_event = true; window .update(cx, |_, cx| { let node_id = focus_handle @@ -711,9 +710,6 @@ impl<'a> WindowContext<'a> { cx.dispatch_action_on_node(node_id, action.as_ref()); }) .log_err(); - if cx.propagate_event { - cx.dispatch_global_action(action.as_ref()); - } }) } @@ -1454,7 +1450,34 @@ impl<'a> WindowContext<'a> { .dispatch_tree .dispatch_path(node_id); - // Capture phase + // Capture phase for global actions. + self.propagate_event = true; + if let Some(mut global_listeners) = self + .global_action_listeners + .remove(&action.as_any().type_id()) + { + for listener in &global_listeners { + listener(action.as_any(), DispatchPhase::Capture, self); + if !self.propagate_event { + break; + } + } + + global_listeners.extend( + self.global_action_listeners + .remove(&action.as_any().type_id()) + .unwrap_or_default(), + ); + + self.global_action_listeners + .insert(action.as_any().type_id(), global_listeners); + } + + if !self.propagate_event { + return; + } + + // Capture phase for window actions. for node_id in &dispatch_path { let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { @@ -1474,7 +1497,8 @@ impl<'a> WindowContext<'a> { } } } - // Bubble phase + + // Bubble phase for window actions. for node_id in dispatch_path.iter().rev() { let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { @@ -1496,6 +1520,30 @@ impl<'a> WindowContext<'a> { } } } + + // Bubble phase for global actions. + if let Some(mut global_listeners) = self + .global_action_listeners + .remove(&action.as_any().type_id()) + { + for listener in global_listeners.iter().rev() { + self.propagate_event = false; // Actions stop propagation by default during the bubble phase + + listener(action.as_any(), DispatchPhase::Bubble, self); + if !self.propagate_event { + break; + } + } + + global_listeners.extend( + self.global_action_listeners + .remove(&action.as_any().type_id()) + .unwrap_or_default(), + ); + + self.global_action_listeners + .insert(action.as_any().type_id(), global_listeners); + } } /// Register the given handler to be invoked whenever the global of the given type