@@ -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
@@ -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