diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 0fafe7694204b2500b203db5edc6489ed094bf40..d0388a9aedebbec4618fa02b22b335e2a659c5aa 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -3390,15 +3390,14 @@ impl<'a, 'b, 'c, V: View> LayoutContext<'a, 'b, 'c, V> { self.keystroke_matcher .bindings_for_action_type(action.as_any().type_id()) .find_map(|b| { - handler_depth - .map(|highest_handler| { - if (0..=highest_handler).any(|depth| b.match_context(&contexts[depth..])) { - Some(b.keystrokes().into()) - } else { - None - } - }) - .flatten() + let highest_handler = handler_depth?; + if action.eq(b.action()) + && (0..=highest_handler).any(|depth| b.match_context(&contexts[depth..])) + { + Some(b.keystrokes().into()) + } else { + None + } }) } @@ -6090,6 +6089,53 @@ mod tests { } } + #[crate::test(self)] + fn test_keystrokes_for_action_with_data(cx: &mut TestAppContext) { + #[derive(Clone, Debug, Deserialize, PartialEq)] + struct ActionWithArg { + #[serde(default)] + arg: bool, + } + + struct View; + impl super::Entity for View { + type Event = (); + } + impl super::View for View { + fn render(&mut self, _: &mut ViewContext) -> AnyElement { + Empty::new().into_any() + } + fn ui_name() -> &'static str { + "View" + } + } + + impl_actions!(test, [ActionWithArg]); + + let (window_id, view) = cx.add_window(|_| View); + cx.update(|cx| { + cx.add_global_action(|_: &ActionWithArg, _| {}); + cx.add_bindings(vec![ + Binding::new("a", ActionWithArg { arg: false }, None), + Binding::new("shift-a", ActionWithArg { arg: true }, None), + ]); + }); + + let actions = cx.available_actions(window_id, view.id()); + assert_eq!( + actions[0].1.as_any().downcast_ref::(), + Some(&ActionWithArg { arg: false }) + ); + assert_eq!( + actions[0] + .2 + .iter() + .map(|b| b.keystrokes()[0].clone()) + .collect::>(), + vec![Keystroke::parse("a").unwrap()], + ); + } + #[crate::test(self)] async fn test_model_condition(cx: &mut TestAppContext) { struct Counter(usize); diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 24a36865635b895908bd9f647be9f3880e5ab2a0..30d58cdd726e532599a743caa5aae3c01917340f 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -394,17 +394,18 @@ impl<'a> WindowContext<'a> { .iter() .filter_map(move |(name, (type_id, deserialize))| { if let Some(action_depth) = handler_depths_by_action_type.get(type_id).copied() { - Some(( - *name, - deserialize("{}").ok()?, - self.keystroke_matcher - .bindings_for_action_type(*type_id) - .filter(|b| { - (0..=action_depth).any(|depth| b.match_context(&contexts[depth..])) - }) - .cloned() - .collect(), - )) + let action = deserialize("{}").ok()?; + let bindings = self + .keystroke_matcher + .bindings_for_action_type(*type_id) + .filter(|b| { + action.eq(b.action()) + && (0..=action_depth) + .any(|depth| b.match_context(&contexts[depth..])) + }) + .cloned() + .collect(); + Some((*name, action, bindings)) } else { None } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 1c2b33214e26fd0e45f29aa97316049e28f80ec7..da23d23285b0587de444b1072b55c37b22d99d21 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -105,16 +105,19 @@ pub struct RemoveWorktreeFromProject(pub WorktreeId); #[derive(Copy, Clone, Default, Deserialize, PartialEq)] pub struct ToggleLeftDock { + #[serde(default = "default_true")] pub focus: bool, } #[derive(Copy, Clone, Default, Deserialize, PartialEq)] pub struct ToggleBottomDock { + #[serde(default = "default_true")] pub focus: bool, } #[derive(Copy, Clone, Default, Deserialize, PartialEq)] pub struct ToggleRightDock { + #[serde(default = "default_true")] pub focus: bool, } @@ -3378,6 +3381,10 @@ fn parse_pixel_position_env_var(value: &str) -> Option { Some(vec2f(width as f32, height as f32)) } +fn default_true() -> bool { + true +} + #[cfg(test)] mod tests { use super::*;