gpui: Refactor PlatformKeyboardLayout (#29653)

Release Notes:

- N/A
This commit is contained in:
张小白 2025-04-30 16:17:26 +08:00 committed by GitHub
parent edda386827
commit 074b6965e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 131 additions and 106 deletions

View file

@ -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<String> 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;
}

View file

@ -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;
}

View file

@ -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::*;

View file

@ -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 }
}
}

View file

@ -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::*;

View file

@ -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::*;

View file

@ -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 }
}
}
}

View file

@ -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;

View file

@ -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::*;

View file

@ -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<Self> {
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(),
}
}
}

View file

@ -299,9 +299,9 @@ impl Platform for WindowsPlatform {
fn keyboard_layout(&self) -> Box<dyn PlatformKeyboardLayout> {
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<bool> {
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<Self> {
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};