@@ -1040,20 +1040,10 @@ impl AppContext {
pub fn is_action_available(&mut self, action: &dyn Action) -> bool {
if let Some(window) = self.active_window() {
- let window_action_available = window
- .update(self, |_, cx| {
- if let Some(focus_id) = cx.window.focus {
- cx.window
- .current_frame
- .dispatch_tree
- .is_action_available(action, focus_id)
- } else {
- false
- }
- })
- .unwrap_or(false);
- if window_action_available {
- return true;
+ if let Ok(window_action_available) =
+ window.update(self, |_, cx| cx.is_action_available(action))
+ {
+ return window_action_available;
}
}
@@ -1075,44 +1065,19 @@ impl AppContext {
}
pub fn dispatch_action(&mut self, action: &dyn Action) {
- 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, 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 {
- if let Some(active_window) = self.active_window() {
- active_window
- .update(self, |_, cx| cx.dispatch_action(action.boxed_clone()))
- .log_err();
- }
- }
+ if let Some(active_window) = self.active_window() {
+ active_window
+ .update(self, |_, cx| cx.dispatch_action(action.boxed_clone()))
+ .log_err();
+ } else {
+ self.propagate_event = true;
- if self.propagate_event {
if let Some(mut global_listeners) = self
.global_action_listeners
.remove(&action.as_any().type_id())
{
- for listener in global_listeners.iter().rev() {
- listener(action, DispatchPhase::Bubble, self);
+ for listener in &global_listeners {
+ listener(action.as_any(), DispatchPhase::Capture, self);
if !self.propagate_event {
break;
}
@@ -1127,6 +1092,29 @@ impl AppContext {
self.global_action_listeners
.insert(action.as_any().type_id(), global_listeners);
}
+
+ if self.propagate_event {
+ if let Some(mut global_listeners) = self
+ .global_action_listeners
+ .remove(&action.as_any().type_id())
+ {
+ for listener in global_listeners.iter().rev() {
+ 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);
+ }
+ }
}
}
}
@@ -161,17 +161,15 @@ impl DispatchTree {
actions
}
- pub fn is_action_available(&self, action: &dyn Action, target: FocusId) -> bool {
- if let Some(node) = self.focusable_node_ids.get(&target) {
- for node_id in self.dispatch_path(*node) {
- let node = &self.nodes[node_id.0];
- if node
- .action_listeners
- .iter()
- .any(|listener| listener.action_type == action.as_any().type_id())
- {
- return true;
- }
+ pub fn is_action_available(&self, action: &dyn Action, target: DispatchNodeId) -> bool {
+ for node_id in self.dispatch_path(target) {
+ let node = &self.nodes[node_id.0];
+ if node
+ .action_listeners
+ .iter()
+ .any(|listener| listener.action_type == action.as_any().type_id())
+ {
+ return true;
}
}
false
@@ -804,6 +804,22 @@ impl<'a> WindowContext<'a> {
);
}
+ pub fn is_action_available(&self, action: &dyn Action) -> bool {
+ let target = self
+ .focused()
+ .and_then(|focused_handle| {
+ self.window
+ .current_frame
+ .dispatch_tree
+ .focusable_node_id(focused_handle.id)
+ })
+ .unwrap_or_else(|| self.window.current_frame.dispatch_tree.root_node_id());
+ self.window
+ .current_frame
+ .dispatch_tree
+ .is_action_available(action, target)
+ }
+
/// The position of the mouse relative to the window.
pub fn mouse_position(&self) -> Point<Pixels> {
self.window.mouse_position