diff --git a/crates/docs_preprocessor/src/main.rs b/crates/docs_preprocessor/src/main.rs index c900eb692a..c8c3dc54b7 100644 --- a/crates/docs_preprocessor/src/main.rs +++ b/crates/docs_preprocessor/src/main.rs @@ -19,6 +19,10 @@ static KEYMAP_LINUX: LazyLock = LazyLock::new(|| { load_keymap("keymaps/default-linux.json").expect("Failed to load Linux keymap") }); +static KEYMAP_WINDOWS: LazyLock = LazyLock::new(|| { + load_keymap("keymaps/default-windows.json").expect("Failed to load Windows keymap") +}); + static ALL_ACTIONS: LazyLock> = LazyLock::new(dump_all_gpui_actions); const FRONT_MATTER_COMMENT: &str = ""; @@ -216,6 +220,7 @@ fn find_binding(os: &str, action: &str) -> Option { let keymap = match os { "macos" => &KEYMAP_MACOS, "linux" | "freebsd" => &KEYMAP_LINUX, + "windows" => &KEYMAP_WINDOWS, _ => unreachable!("Not a valid OS: {}", os), }; diff --git a/crates/gpui/src/keymap/binding.rs b/crates/gpui/src/keymap/binding.rs index 730da7fe27..edc772b4e9 100644 --- a/crates/gpui/src/keymap/binding.rs +++ b/crates/gpui/src/keymap/binding.rs @@ -3,8 +3,8 @@ use std::rc::Rc; use collections::HashMap; use crate::{ - Action, AsKeystroke, InvalidKeystrokeError, KeyBindingContextPredicate, KeybindingKeystroke, - Keystroke, SharedString, + Action, AsKeystroke, DummyKeyboardMapper, InvalidKeystrokeError, KeyBindingContextPredicate, + KeybindingKeystroke, Keystroke, PlatformKeyboardMapper, SharedString, }; use smallvec::SmallVec; @@ -35,7 +35,16 @@ impl KeyBinding { pub fn new(keystrokes: &str, action: A, context: Option<&str>) -> Self { let context_predicate = context.map(|context| KeyBindingContextPredicate::parse(context).unwrap().into()); - Self::load(keystrokes, Box::new(action), context_predicate, None, None).unwrap() + Self::load( + keystrokes, + Box::new(action), + context_predicate, + false, + None, + None, + &DummyKeyboardMapper, + ) + .unwrap() } /// Load a keybinding from the given raw data. @@ -43,12 +52,14 @@ impl KeyBinding { keystrokes: &str, action: Box, context_predicate: Option>, + use_key_equivalents: bool, key_equivalents: Option<&HashMap>, action_input: Option, + keyboard_mapper: &dyn PlatformKeyboardMapper, ) -> std::result::Result { let mut keystrokes: SmallVec<[Keystroke; 2]> = keystrokes .split_whitespace() - .map(|source| Keystroke::parse(source).map(|keystroke| keystroke.into_shifted())) + .map(Keystroke::parse) .collect::>()?; if let Some(equivalents) = key_equivalents { @@ -63,7 +74,9 @@ impl KeyBinding { let keystrokes = keystrokes .into_iter() - .map(KeybindingKeystroke::new) + .map(|keystroke| { + KeybindingKeystroke::new(keystroke, use_key_equivalents, keyboard_mapper) + }) .collect(); Ok(Self { diff --git a/crates/gpui/src/platform/keyboard.rs b/crates/gpui/src/platform/keyboard.rs index 2f91cb976b..8f52e11cb2 100644 --- a/crates/gpui/src/platform/keyboard.rs +++ b/crates/gpui/src/platform/keyboard.rs @@ -11,13 +11,22 @@ pub trait PlatformKeyboardLayout { /// A trait for platform-specific keyboard mappings pub trait PlatformKeyboardMapper { /// Map a key equivalent to its platform-specific representation - fn map_key_equivalent(&self, keystroke: Keystroke) -> KeybindingKeystroke; + fn map_key_equivalent( + &self, + keystroke: Keystroke, + use_key_equivalents: bool, + ) -> KeybindingKeystroke; } -pub(crate) struct DummyKeyboardMapper; +/// A dummy implementation of the platform keyboard mapper +pub struct DummyKeyboardMapper; impl PlatformKeyboardMapper for DummyKeyboardMapper { - fn map_key_equivalent(&self, keystroke: Keystroke) -> KeybindingKeystroke { - KeybindingKeystroke::new(keystroke) + fn map_key_equivalent( + &self, + keystroke: Keystroke, + _use_key_equivalents: bool, + ) -> KeybindingKeystroke { + KeybindingKeystroke::from_keystroke(keystroke) } } diff --git a/crates/gpui/src/platform/keystroke.rs b/crates/gpui/src/platform/keystroke.rs index c463caad28..c3a2f7d7a2 100644 --- a/crates/gpui/src/platform/keystroke.rs +++ b/crates/gpui/src/platform/keystroke.rs @@ -5,6 +5,8 @@ use std::{ fmt::{Display, Write}, }; +use crate::PlatformKeyboardMapper; + /// TODO: pub trait AsKeystroke { /// TODO: @@ -281,30 +283,23 @@ impl Keystroke { } self } - - /// TODO: - pub fn into_shifted(self) -> Self { - let Keystroke { - modifiers, - key, - key_char, - } = self; - let (key, modifiers) = into_shifted_key(key, modifiers); - Self { - key, - modifiers, - key_char, - } - } } impl KeybindingKeystroke { /// Create a new keybinding keystroke from the given keystroke - pub fn new(inner: Keystroke) -> Self { - let key = inner.key.clone(); - let modifiers = inner.modifiers; + pub fn new( + inner: Keystroke, + use_key_equivalents: bool, + keyboard_mapper: &dyn PlatformKeyboardMapper, + ) -> Self { + keyboard_mapper.map_key_equivalent(inner, use_key_equivalents) + } + + pub(crate) fn from_keystroke(keystroke: Keystroke) -> Self { + let key = keystroke.key.clone(); + let modifiers = keystroke.modifiers; KeybindingKeystroke { - inner, + inner: keystroke, modifiers, key, } @@ -608,191 +603,6 @@ impl AsKeystroke for KeybindingKeystroke { } } -fn to_unshifted_key(key: &str, modifiers: &Modifiers) -> (String, Modifiers) { - let mut modifiers = modifiers.clone(); - match key { - "~" => { - modifiers.shift = true; - ("`".to_string(), modifiers) - } - "!" => { - modifiers.shift = true; - ("1".to_string(), modifiers) - } - "@" => { - modifiers.shift = true; - ("2".to_string(), modifiers) - } - "#" => { - modifiers.shift = true; - ("3".to_string(), modifiers) - } - "$" => { - modifiers.shift = true; - ("4".to_string(), modifiers) - } - "%" => { - modifiers.shift = true; - ("5".to_string(), modifiers) - } - "^" => { - modifiers.shift = true; - ("6".to_string(), modifiers) - } - "&" => { - modifiers.shift = true; - ("7".to_string(), modifiers) - } - "*" => { - modifiers.shift = true; - ("8".to_string(), modifiers) - } - "(" => { - modifiers.shift = true; - ("9".to_string(), modifiers) - } - ")" => { - modifiers.shift = true; - ("0".to_string(), modifiers) - } - "_" => { - modifiers.shift = true; - ("-".to_string(), modifiers) - } - "+" => { - modifiers.shift = true; - ("=".to_string(), modifiers) - } - "{" => { - modifiers.shift = true; - ("[".to_string(), modifiers) - } - "}" => { - modifiers.shift = true; - ("]".to_string(), modifiers) - } - "|" => { - modifiers.shift = true; - ("\\".to_string(), modifiers) - } - ":" => { - modifiers.shift = true; - (";".to_string(), modifiers) - } - "\"" => { - modifiers.shift = true; - ("'".to_string(), modifiers) - } - "<" => { - modifiers.shift = true; - (",".to_string(), modifiers) - } - ">" => { - modifiers.shift = true; - (">".to_string(), modifiers) - } - "?" => { - modifiers.shift = true; - ("/".to_string(), modifiers) - } - _ => (key.to_string(), modifiers), - } -} - -fn into_shifted_key(key: String, mut modifiers: Modifiers) -> (String, Modifiers) { - if !modifiers.shift { - (key, modifiers) - } else { - match key.as_str() { - "`" => { - modifiers.shift = false; - ("~".to_string(), modifiers) - } - "1" => { - modifiers.shift = false; - ("!".to_string(), modifiers) - } - "2" => { - modifiers.shift = false; - ("@".to_string(), modifiers) - } - "3" => { - modifiers.shift = false; - ("#".to_string(), modifiers) - } - "4" => { - modifiers.shift = false; - ("$".to_string(), modifiers) - } - "5" => { - modifiers.shift = false; - ("%".to_string(), modifiers) - } - "6" => { - modifiers.shift = false; - ("^".to_string(), modifiers) - } - "7" => { - modifiers.shift = false; - ("&".to_string(), modifiers) - } - "8" => { - modifiers.shift = false; - ("*".to_string(), modifiers) - } - "9" => { - modifiers.shift = false; - ("(".to_string(), modifiers) - } - "0" => { - modifiers.shift = false; - (")".to_string(), modifiers) - } - "-" => { - modifiers.shift = false; - ("_".to_string(), modifiers) - } - "=" => { - modifiers.shift = false; - ("+".to_string(), modifiers) - } - "[" => { - modifiers.shift = false; - ("{".to_string(), modifiers) - } - "]" => { - modifiers.shift = false; - ("}".to_string(), modifiers) - } - "\\" => { - modifiers.shift = false; - ("|".to_string(), modifiers) - } - ";" => { - modifiers.shift = false; - (":".to_string(), modifiers) - } - "'" => { - modifiers.shift = false; - ("\"".to_string(), modifiers) - } - "," => { - modifiers.shift = false; - ("<".to_string(), modifiers) - } - "." => { - modifiers.shift = false; - (">".to_string(), modifiers) - } - "/" => { - modifiers.shift = false; - ("?".to_string(), modifiers) - } - _ => (key, modifiers), - } - } -} - fn display_modifiers(modifiers: &Modifiers, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if modifiers.control { #[cfg(target_os = "macos")] @@ -858,45 +668,3 @@ fn display_key(key: &str, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { }; f.write_char(key) } - -#[cfg(test)] -mod tests { - use crate::{KeybindingKeystroke, Keystroke, Modifiers}; - - #[test] - fn test_parsing_keystroke_on_windows() { - // On windows, users prefer to use "ctrl-shift-key", so here we support - // both "ctrl-$" and "ctrl-shift-4" - let source = "ctrl-$"; - let keystroke = Keystroke::parse(source).unwrap(); - assert_eq!(keystroke.modifiers, Modifiers::control()); - assert_eq!(keystroke.key, "$"); - assert_eq!(keystroke.key_char, None); - - let keystroke_display = KeybindingKeystroke::new(keystroke.clone()); - assert_eq!(keystroke_display.inner, keystroke); - assert_eq!(keystroke_display.key, "4"); - assert_eq!(keystroke_display.modifiers, Modifiers::control_shift()); - - let source = "ctrl-shift-4"; - let keystroke = Keystroke::parse(source).unwrap(); - assert_eq!(keystroke.modifiers, Modifiers::control_shift()); - assert_eq!(keystroke.key, "4"); - assert_eq!(keystroke.key_char, None); - - let keystroke = keystroke.into_shifted(); - assert_eq!(keystroke.modifiers, Modifiers::control()); - assert_eq!(keystroke.key, "$"); - let keystroke_display = KeybindingKeystroke::new(keystroke.clone()); - assert_eq!( - keystroke_display.inner, - Keystroke { - modifiers: Modifiers::control(), - key: "$".to_string(), - key_char: None - } - ); - assert_eq!(keystroke_display.key, "4"); - assert_eq!(keystroke_display.modifiers, Modifiers::control_shift()); - } -} diff --git a/crates/gpui/src/platform/windows/keyboard.rs b/crates/gpui/src/platform/windows/keyboard.rs index 526522511c..25fcffb236 100644 --- a/crates/gpui/src/platform/windows/keyboard.rs +++ b/crates/gpui/src/platform/windows/keyboard.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use collections::HashMap; use windows::Win32::UI::{ Input::KeyboardAndMouse::{ GetKeyboardLayoutNameW, MAPVK_VK_TO_CHAR, MAPVK_VK_TO_VSC, MapVirtualKeyW, ToUnicode, @@ -19,7 +20,11 @@ pub(crate) struct WindowsKeyboardLayout { name: String, } -pub(crate) struct WindowsKeyboardMapper; +pub(crate) struct WindowsKeyboardMapper { + key_to_vkey: HashMap, + vkey_to_key: HashMap, + vkey_to_shifted: HashMap, +} impl PlatformKeyboardLayout for WindowsKeyboardLayout { fn id(&self) -> &str { @@ -32,9 +37,14 @@ impl PlatformKeyboardLayout for WindowsKeyboardLayout { } impl PlatformKeyboardMapper for WindowsKeyboardMapper { - fn map_key_equivalent(&self, mut keystroke: Keystroke) -> KeybindingKeystroke { - let Some((vkey, shifted_key)) = key_needs_processing(&keystroke.key) else { - return KeybindingKeystroke::new(keystroke); + fn map_key_equivalent( + &self, + mut keystroke: Keystroke, + use_key_equivalents: bool, + ) -> KeybindingKeystroke { + let Some((vkey, shifted_key)) = self.get_vkey_from_key(&keystroke.key, use_key_equivalents) + else { + return KeybindingKeystroke::from_keystroke(keystroke); }; if shifted_key && keystroke.modifiers.shift { log::warn!( @@ -46,31 +56,22 @@ impl PlatformKeyboardMapper for WindowsKeyboardMapper { let shift = shifted_key || keystroke.modifiers.shift; keystroke.modifiers.shift = false; - let Some(key) = get_key_from_vkey(vkey) else { + let Some(key) = self.vkey_to_key.get(&vkey).cloned() else { log::error!( "Failed to map key equivalent '{:?}' to a valid key", keystroke ); - return KeybindingKeystroke::new(keystroke); + return KeybindingKeystroke::from_keystroke(keystroke); }; keystroke.key = if shift { - let scan_code = unsafe { MapVirtualKeyW(vkey.0 as u32, MAPVK_VK_TO_VSC) }; - if scan_code == 0 { - log::error!( - "Failed to map keystroke {:?} with virtual key '{:?}' to a scan code", - keystroke, - vkey - ); - return KeybindingKeystroke::new(keystroke); - } - let Some(shifted_key) = get_shifted_key(vkey, scan_code) else { + let Some(shifted_key) = self.vkey_to_shifted.get(&vkey).cloned() else { log::error!( "Failed to map keystroke {:?} with virtual key '{:?}' to a shifted key", keystroke, vkey ); - return KeybindingKeystroke::new(keystroke); + return KeybindingKeystroke::from_keystroke(keystroke); }; shifted_key } else { @@ -113,7 +114,36 @@ impl WindowsKeyboardLayout { impl WindowsKeyboardMapper { pub(crate) fn new() -> Self { - Self + let mut key_to_vkey = HashMap::default(); + let mut vkey_to_key = HashMap::default(); + let mut vkey_to_shifted = HashMap::default(); + for vkey in CANDIDATE_VKEYS { + if let Some(key) = get_key_from_vkey(*vkey) { + key_to_vkey.insert(key.clone(), (vkey.0, false)); + vkey_to_key.insert(vkey.0, key); + } + let scan_code = unsafe { MapVirtualKeyW(vkey.0 as u32, MAPVK_VK_TO_VSC) }; + if scan_code == 0 { + continue; + } + if let Some(shifted_key) = get_shifted_key(*vkey, scan_code) { + key_to_vkey.insert(shifted_key.clone(), (vkey.0, true)); + vkey_to_shifted.insert(vkey.0, shifted_key); + } + } + Self { + key_to_vkey, + vkey_to_key, + vkey_to_shifted, + } + } + + fn get_vkey_from_key(&self, key: &str, use_key_equivalents: bool) -> Option<(u16, bool)> { + if use_key_equivalents { + key_needs_processing(key) + } else { + self.key_to_vkey.get(key).cloned() + } } } @@ -210,54 +240,81 @@ pub(crate) fn generate_key_char( } } -fn key_needs_processing(key: &str) -> Option<(VIRTUAL_KEY, bool)> { +fn key_needs_processing(key: &str) -> Option<(u16, bool)> { match key { - "`" => Some((VK_OEM_3, false)), - "~" => Some((VK_OEM_3, true)), - "1" => Some((VK_1, false)), - "!" => Some((VK_1, true)), - "2" => Some((VK_2, false)), - "@" => Some((VK_2, true)), - "3" => Some((VK_3, false)), - "#" => Some((VK_3, true)), - "4" => Some((VK_4, false)), - "$" => Some((VK_4, true)), - "5" => Some((VK_5, false)), - "%" => Some((VK_5, true)), - "6" => Some((VK_6, false)), - "^" => Some((VK_6, true)), - "7" => Some((VK_7, false)), - "&" => Some((VK_7, true)), - "8" => Some((VK_8, false)), - "*" => Some((VK_8, true)), - "9" => Some((VK_9, false)), - "(" => Some((VK_9, true)), - "0" => Some((VK_0, false)), - ")" => Some((VK_0, true)), - "-" => Some((VK_OEM_MINUS, false)), - "_" => Some((VK_OEM_MINUS, true)), - "=" => Some((VK_OEM_PLUS, false)), - "+" => Some((VK_OEM_PLUS, true)), - "[" => Some((VK_OEM_4, false)), - "{" => Some((VK_OEM_4, true)), - "]" => Some((VK_OEM_6, false)), - "}" => Some((VK_OEM_6, true)), - "\\" => Some((VK_OEM_5, false)), - "|" => Some((VK_OEM_5, true)), - ";" => Some((VK_OEM_1, false)), - ":" => Some((VK_OEM_1, true)), - "'" => Some((VK_OEM_7, false)), - "\"" => Some((VK_OEM_7, true)), - "," => Some((VK_OEM_COMMA, false)), - "<" => Some((VK_OEM_COMMA, true)), - "." => Some((VK_OEM_PERIOD, false)), - ">" => Some((VK_OEM_PERIOD, true)), - "/" => Some((VK_OEM_2, false)), - "?" => Some((VK_OEM_2, true)), + "`" => Some((VK_OEM_3.0, false)), + "~" => Some((VK_OEM_3.0, true)), + "1" => Some((VK_1.0, false)), + "!" => Some((VK_1.0, true)), + "2" => Some((VK_2.0, false)), + "@" => Some((VK_2.0, true)), + "3" => Some((VK_3.0, false)), + "#" => Some((VK_3.0, true)), + "4" => Some((VK_4.0, false)), + "$" => Some((VK_4.0, true)), + "5" => Some((VK_5.0, false)), + "%" => Some((VK_5.0, true)), + "6" => Some((VK_6.0, false)), + "^" => Some((VK_6.0, true)), + "7" => Some((VK_7.0, false)), + "&" => Some((VK_7.0, true)), + "8" => Some((VK_8.0, false)), + "*" => Some((VK_8.0, true)), + "9" => Some((VK_9.0, false)), + "(" => Some((VK_9.0, true)), + "0" => Some((VK_0.0, false)), + ")" => Some((VK_0.0, true)), + "-" => Some((VK_OEM_MINUS.0, false)), + "_" => Some((VK_OEM_MINUS.0, true)), + "=" => Some((VK_OEM_PLUS.0, false)), + "+" => Some((VK_OEM_PLUS.0, true)), + "[" => Some((VK_OEM_4.0, false)), + "{" => Some((VK_OEM_4.0, true)), + "]" => Some((VK_OEM_6.0, false)), + "}" => Some((VK_OEM_6.0, true)), + "\\" => Some((VK_OEM_5.0, false)), + "|" => Some((VK_OEM_5.0, true)), + ";" => Some((VK_OEM_1.0, false)), + ":" => Some((VK_OEM_1.0, true)), + "'" => Some((VK_OEM_7.0, false)), + "\"" => Some((VK_OEM_7.0, true)), + "," => Some((VK_OEM_COMMA.0, false)), + "<" => Some((VK_OEM_COMMA.0, true)), + "." => Some((VK_OEM_PERIOD.0, false)), + ">" => Some((VK_OEM_PERIOD.0, true)), + "/" => Some((VK_OEM_2.0, false)), + "?" => Some((VK_OEM_2.0, true)), _ => None, } } +const CANDIDATE_VKEYS: &[VIRTUAL_KEY] = &[ + VK_OEM_3, + VK_OEM_MINUS, + VK_OEM_PLUS, + VK_OEM_4, + VK_OEM_5, + VK_OEM_6, + VK_OEM_1, + VK_OEM_7, + VK_OEM_COMMA, + VK_OEM_PERIOD, + VK_OEM_2, + VK_OEM_102, + VK_OEM_8, + VK_ABNT_C1, + VK_0, + VK_1, + VK_2, + VK_3, + VK_4, + VK_5, + VK_6, + VK_7, + VK_8, + VK_9, +]; + #[cfg(test)] mod tests { use crate::{Keystroke, Modifiers, PlatformKeyboardMapper, WindowsKeyboardMapper}; @@ -272,7 +329,7 @@ mod tests { key: "a".to_string(), key_char: None, }; - let mapped = mapper.map_key_equivalent(keystroke.clone()); + let mapped = mapper.map_key_equivalent(keystroke.clone(), true); assert_eq!(mapped.inner, keystroke); assert_eq!(mapped.key, "a"); assert_eq!(mapped.modifiers, Modifiers::control()); @@ -283,7 +340,7 @@ mod tests { key: "$".to_string(), key_char: None, }; - let mapped = mapper.map_key_equivalent(keystroke.clone()); + let mapped = mapper.map_key_equivalent(keystroke.clone(), true); assert_eq!(mapped.inner, keystroke); assert_eq!(mapped.key, "4"); assert_eq!(mapped.modifiers, Modifiers::control_shift()); @@ -294,7 +351,7 @@ mod tests { key: "$".to_string(), key_char: None, }; - let mapped = mapper.map_key_equivalent(keystroke.clone()); + let mapped = mapper.map_key_equivalent(keystroke.clone(), true); assert_eq!(mapped.inner.modifiers, Modifiers::control()); assert_eq!(mapped.key, "4"); assert_eq!(mapped.modifiers, Modifiers::control_shift()); @@ -305,7 +362,7 @@ mod tests { key: "4".to_string(), key_char: None, }; - let mapped = mapper.map_key_equivalent(keystroke.clone()); + let mapped = mapper.map_key_equivalent(keystroke.clone(), true); assert_eq!(mapped.inner.modifiers, Modifiers::control()); assert_eq!(mapped.inner.key, "$"); assert_eq!(mapped.key, "4"); diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index f77b71a6fe..d9ae52d1cc 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -279,6 +279,7 @@ impl KeymapFile { keystrokes, action, context_predicate.clone(), + *use_key_equivalents, key_equivalents, cx, ); @@ -337,6 +338,7 @@ impl KeymapFile { keystrokes: &str, action: &KeymapAction, context: Option>, + use_key_equivalents: bool, key_equivalents: Option<&HashMap>, cx: &App, ) -> std::result::Result { @@ -405,8 +407,10 @@ impl KeymapFile { keystrokes, action, context, + use_key_equivalents, key_equivalents, action_input_string.map(SharedString::from), + cx.keyboard_mapper(), ) { Ok(key_binding) => key_binding, Err(InvalidKeystrokeError { keystroke }) => { @@ -1021,7 +1025,7 @@ impl From for KeyBindingMetaIndex { #[cfg(test)] mod tests { - use gpui::{KeybindingKeystroke, Keystroke}; + use gpui::{DummyKeyboardMapper, KeybindingKeystroke, Keystroke}; use unindent::Unindent; use crate::{ @@ -1059,7 +1063,13 @@ mod tests { fn parse_keystrokes(keystrokes: &str) -> Vec { keystrokes .split(' ') - .map(|s| KeybindingKeystroke::new(Keystroke::parse(s).expect("Keystrokes valid"))) + .map(|s| { + KeybindingKeystroke::new( + Keystroke::parse(s).expect("Keystrokes valid"), + false, + &DummyKeyboardMapper, + ) + }) .collect() } diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index b73ab9ae95..91a2d07827 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -89,9 +89,12 @@ pub fn default_settings() -> Cow<'static, str> { #[cfg(target_os = "macos")] pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-macos.json"; -#[cfg(not(target_os = "macos"))] +#[cfg(target_os = "linux")] pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-linux.json"; +#[cfg(target_os = "windows")] +pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-windows.json"; + pub fn default_keymap() -> Cow<'static, str> { asset_str::(DEFAULT_KEYMAP_PATH) } diff --git a/crates/settings_ui/src/ui_components/keystroke_input.rs b/crates/settings_ui/src/ui_components/keystroke_input.rs index b37f6e20f7..f0518a5e11 100644 --- a/crates/settings_ui/src/ui_components/keystroke_input.rs +++ b/crates/settings_ui/src/ui_components/keystroke_input.rs @@ -301,7 +301,8 @@ impl KeystrokeInput { return; } - let mut keystroke = KeybindingKeystroke::new(keystroke.clone()); + let mut keystroke = + KeybindingKeystroke::new(keystroke.clone(), false, cx.keyboard_mapper()); if let Some(last) = self.keystrokes.last() && last.key.is_empty() && (!self.search || self.previous_modifiers.modified())