diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 0abdf4b174..d23d6e3d9d 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -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(active_window) = self.active_window() { + active_window + .update(self, |_, cx| cx.dispatch_action(action.boxed_clone())) + .log_err(); + } else { + 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 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); + } + } } } } diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index 07561644f7..80e662ad3e 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -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 diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 1bd8b46537..8995d04b64 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -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 { self.window.mouse_position