diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 9c4a2c407e..ae37bf9adb 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -1,4 +1,5 @@ mod app_menu; +mod keyboard; mod keystroke; #[cfg(any(target_os = "linux", target_os = "freebsd"))] @@ -63,6 +64,7 @@ use strum::EnumIter; use uuid::Uuid; pub use app_menu::*; +pub use keyboard::*; pub use keystroke::*; #[cfg(any(target_os = "linux", target_os = "freebsd"))] @@ -1679,11 +1681,3 @@ impl From for ClipboardString { } } } - -/// A trait for platform-specific keyboard layouts -pub trait PlatformKeyboardLayout { - /// Get the keyboard layout ID, which should be unique to the layout - fn id(&self) -> &str; - /// Get the keyboard layout display name - fn name(&self) -> &str; -} diff --git a/crates/gpui/src/platform/keyboard.rs b/crates/gpui/src/platform/keyboard.rs new file mode 100644 index 0000000000..e28d781520 --- /dev/null +++ b/crates/gpui/src/platform/keyboard.rs @@ -0,0 +1,7 @@ +/// A trait for platform-specific keyboard layouts +pub trait PlatformKeyboardLayout { + /// Get the keyboard layout ID, which should be unique to the layout + fn id(&self) -> &str; + /// Get the keyboard layout display name + fn name(&self) -> &str; +} diff --git a/crates/gpui/src/platform/linux.rs b/crates/gpui/src/platform/linux.rs index 20bc2ddca9..af8b8c2370 100644 --- a/crates/gpui/src/platform/linux.rs +++ b/crates/gpui/src/platform/linux.rs @@ -1,5 +1,6 @@ mod dispatcher; mod headless; +mod keyboard; mod platform; #[cfg(any(feature = "wayland", feature = "x11"))] mod text_system; @@ -13,6 +14,7 @@ mod xdg_desktop_portal; pub(crate) use dispatcher::*; pub(crate) use headless::*; +pub(crate) use keyboard::*; pub(crate) use platform::*; #[cfg(any(feature = "wayland", feature = "x11"))] pub(crate) use text_system::*; diff --git a/crates/gpui/src/platform/linux/keyboard.rs b/crates/gpui/src/platform/linux/keyboard.rs new file mode 100644 index 0000000000..b4c296d8ac --- /dev/null +++ b/crates/gpui/src/platform/linux/keyboard.rs @@ -0,0 +1,21 @@ +use crate::PlatformKeyboardLayout; + +pub(crate) struct LinuxKeyboardLayout { + id: String, +} + +impl PlatformKeyboardLayout for LinuxKeyboardLayout { + fn id(&self) -> &str { + &self.id + } + + fn name(&self) -> &str { + &self.id + } +} + +impl LinuxKeyboardLayout { + pub(crate) fn new(id: String) -> Self { + Self { id } + } +} diff --git a/crates/gpui/src/platform/linux/platform.rs b/crates/gpui/src/platform/linux/platform.rs index 417dc46a55..167e232f0b 100644 --- a/crates/gpui/src/platform/linux/platform.rs +++ b/crates/gpui/src/platform/linux/platform.rs @@ -858,26 +858,6 @@ impl crate::Modifiers { } } -pub(crate) struct LinuxKeyboardLayout { - id: String, -} - -impl PlatformKeyboardLayout for LinuxKeyboardLayout { - fn id(&self) -> &str { - &self.id - } - - fn name(&self) -> &str { - &self.id - } -} - -impl LinuxKeyboardLayout { - pub(crate) fn new(id: String) -> Self { - Self { id } - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/gpui/src/platform/mac.rs b/crates/gpui/src/platform/mac.rs index 75041b8cc1..cce65e4293 100644 --- a/crates/gpui/src/platform/mac.rs +++ b/crates/gpui/src/platform/mac.rs @@ -4,6 +4,7 @@ mod dispatcher; mod display; mod display_link; mod events; +mod keyboard; mod screen_capture; #[cfg(not(feature = "macos-blade"))] @@ -45,6 +46,7 @@ use std::{ pub(crate) use dispatcher::*; pub(crate) use display::*; pub(crate) use display_link::*; +pub(crate) use keyboard::*; pub(crate) use platform::*; pub(crate) use window::*; diff --git a/crates/gpui/src/platform/mac/keyboard.rs b/crates/gpui/src/platform/mac/keyboard.rs new file mode 100644 index 0000000000..a9f6af3edb --- /dev/null +++ b/crates/gpui/src/platform/mac/keyboard.rs @@ -0,0 +1,49 @@ +use std::ffi::{CStr, c_void}; + +use objc::{msg_send, runtime::Object, sel, sel_impl}; + +use crate::PlatformKeyboardLayout; + +use super::{ + TISCopyCurrentKeyboardLayoutInputSource, TISGetInputSourceProperty, kTISPropertyInputSourceID, + kTISPropertyLocalizedName, +}; + +pub(crate) struct MacKeyboardLayout { + id: String, + name: String, +} + +impl PlatformKeyboardLayout for MacKeyboardLayout { + fn id(&self) -> &str { + &self.id + } + + fn name(&self) -> &str { + &self.name + } +} + +impl MacKeyboardLayout { + pub(crate) fn new() -> Self { + unsafe { + let current_keyboard = TISCopyCurrentKeyboardLayoutInputSource(); + + let id: *mut Object = TISGetInputSourceProperty( + current_keyboard, + kTISPropertyInputSourceID as *const c_void, + ); + let id: *const std::os::raw::c_char = msg_send![id, UTF8String]; + let id = CStr::from_ptr(id).to_str().unwrap().to_string(); + + let name: *mut Object = TISGetInputSourceProperty( + current_keyboard, + kTISPropertyLocalizedName as *const c_void, + ); + let name: *const std::os::raw::c_char = msg_send![name, UTF8String]; + let name = CStr::from_ptr(name).to_str().unwrap().to_string(); + + Self { id, name } + } + } +} diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index 16f87200c4..9b6868ee84 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -1,5 +1,5 @@ use super::{ - BoolExt, + BoolExt, MacKeyboardLayout, attributed_string::{NSAttributedString, NSMutableAttributedString}, events::key_to_native, is_macos_version_at_least, renderer, screen_capture, @@ -1579,45 +1579,6 @@ impl UTType { } } -struct MacKeyboardLayout { - id: String, - name: String, -} - -impl PlatformKeyboardLayout for MacKeyboardLayout { - fn id(&self) -> &str { - &self.id - } - - fn name(&self) -> &str { - &self.name - } -} - -impl MacKeyboardLayout { - fn new() -> Self { - unsafe { - let current_keyboard = TISCopyCurrentKeyboardLayoutInputSource(); - - let id: *mut Object = TISGetInputSourceProperty( - current_keyboard, - kTISPropertyInputSourceID as *const c_void, - ); - let id: *const std::os::raw::c_char = msg_send![id, UTF8String]; - let id = CStr::from_ptr(id).to_str().unwrap().to_string(); - - let name: *mut Object = TISGetInputSourceProperty( - current_keyboard, - kTISPropertyLocalizedName as *const c_void, - ); - let name: *const std::os::raw::c_char = msg_send![name, UTF8String]; - let name = CStr::from_ptr(name).to_str().unwrap().to_string(); - - Self { id, name } - } - } -} - #[cfg(test)] mod tests { use crate::ClipboardItem; diff --git a/crates/gpui/src/platform/windows.rs b/crates/gpui/src/platform/windows.rs index b3a89e9635..462ed2158a 100644 --- a/crates/gpui/src/platform/windows.rs +++ b/crates/gpui/src/platform/windows.rs @@ -4,6 +4,7 @@ mod direct_write; mod dispatcher; mod display; mod events; +mod keyboard; mod platform; mod system_settings; mod util; @@ -16,6 +17,7 @@ pub(crate) use direct_write::*; pub(crate) use dispatcher::*; pub(crate) use display::*; pub(crate) use events::*; +pub(crate) use keyboard::*; pub(crate) use platform::*; pub(crate) use system_settings::*; pub(crate) use util::*; diff --git a/crates/gpui/src/platform/windows/keyboard.rs b/crates/gpui/src/platform/windows/keyboard.rs new file mode 100644 index 0000000000..131f708e7e --- /dev/null +++ b/crates/gpui/src/platform/windows/keyboard.rs @@ -0,0 +1,43 @@ +use anyhow::Result; +use windows::Win32::UI::{ + Input::KeyboardAndMouse::GetKeyboardLayoutNameW, WindowsAndMessaging::KL_NAMELENGTH, +}; +use windows_core::HSTRING; + +use crate::PlatformKeyboardLayout; + +pub(crate) struct WindowsKeyboardLayout { + id: String, + name: String, +} + +impl PlatformKeyboardLayout for WindowsKeyboardLayout { + fn id(&self) -> &str { + &self.id + } + + fn name(&self) -> &str { + &self.name + } +} + +impl WindowsKeyboardLayout { + pub(crate) fn new() -> Result { + let mut buffer = [0u16; KL_NAMELENGTH as usize]; + unsafe { GetKeyboardLayoutNameW(&mut buffer)? }; + let id = HSTRING::from_wide(&buffer).to_string(); + let entry = windows_registry::LOCAL_MACHINE.open(format!( + "System\\CurrentControlSet\\Control\\Keyboard Layouts\\{}", + id + ))?; + let name = entry.get_hstring("Layout Text")?.to_string(); + Ok(Self { id, name }) + } + + pub(crate) fn unknown() -> Self { + Self { + id: "unknown".to_string(), + name: "unknown".to_string(), + } + } +} diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index f1a6a1dbc8..b76bc887a1 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -299,9 +299,9 @@ impl Platform for WindowsPlatform { fn keyboard_layout(&self) -> Box { Box::new( - KeyboardLayout::new() + WindowsKeyboardLayout::new() .log_err() - .unwrap_or(KeyboardLayout::unknown()), + .unwrap_or(WindowsKeyboardLayout::unknown()), ) } @@ -840,42 +840,6 @@ fn should_auto_hide_scrollbars() -> Result { Ok(ui_settings.AutoHideScrollBars()?) } -struct KeyboardLayout { - id: String, - name: String, -} - -impl PlatformKeyboardLayout for KeyboardLayout { - fn id(&self) -> &str { - &self.id - } - - fn name(&self) -> &str { - &self.name - } -} - -impl KeyboardLayout { - fn new() -> Result { - let mut buffer = [0u16; KL_NAMELENGTH as usize]; - unsafe { GetKeyboardLayoutNameW(&mut buffer)? }; - let id = HSTRING::from_wide(&buffer).to_string(); - let entry = windows_registry::LOCAL_MACHINE.open(format!( - "System\\CurrentControlSet\\Control\\Keyboard Layouts\\{}", - id - ))?; - let name = entry.get_hstring("Layout Text")?.to_string(); - Ok(Self { id, name }) - } - - fn unknown() -> Self { - Self { - id: "unknown".to_string(), - name: "unknown".to_string(), - } - } -} - #[cfg(test)] mod tests { use crate::{ClipboardItem, read_from_clipboard, write_to_clipboard};