gpui: Introduce PlatformKeyboardLayout trait for human-friendly keyboard layout names (#29049)

This PR adds a new `PlatformKeyboardLayout` trait with two methods:
`id(&self) -> &str` and `name(&self) -> &str`. The `id()` method returns
a unique identifier for the keyboard layout, while `name()` provides a
human-readable name. This distinction is especially important on
Windows, where the `id` and `name` can be quite different. For example,
the French layout has an `id` of `0000040C`, which is not
human-readable, whereas the `name` would simply be `French`. Currently,
the existing `keyboard_layout()` method returns what's essentially the
same as `id()` in this new design.

This PR implements the `name()` method for both Windows and macOS. On
Linux, for now, `name()` still returns the same value as `id()`.

Release Notes:

- N/A
This commit is contained in:
张小白 2025-04-19 22:23:03 +08:00 committed by GitHub
parent 0454e7a22e
commit f0ef3110d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 197 additions and 68 deletions

View file

@ -25,8 +25,8 @@ use xkbcommon::xkb::{self, Keycode, Keysym, State};
use crate::{
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
ForegroundExecutor, Keymap, LinuxDispatcher, Menu, MenuItem, OwnedMenu, PathPromptOptions,
Pixels, Platform, PlatformDisplay, PlatformTextSystem, PlatformWindow, Point, Result,
ScreenCaptureSource, Task, WindowAppearance, WindowParams, px,
Pixels, Platform, PlatformDisplay, PlatformKeyboardLayout, PlatformTextSystem, PlatformWindow,
Point, Result, ScreenCaptureSource, Task, WindowAppearance, WindowParams, px,
};
#[cfg(any(feature = "wayland", feature = "x11"))]
@ -46,7 +46,7 @@ const FILE_PICKER_PORTAL_MISSING: &str =
pub trait LinuxClient {
fn compositor_name(&self) -> &'static str;
fn with_common<R>(&self, f: impl FnOnce(&mut LinuxCommon) -> R) -> R;
fn keyboard_layout(&self) -> String;
fn keyboard_layout(&self) -> Box<dyn PlatformKeyboardLayout>;
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>>;
#[allow(unused)]
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>>;
@ -138,7 +138,7 @@ impl<P: LinuxClient + 'static> Platform for P {
self.with_common(|common| common.text_system.clone())
}
fn keyboard_layout(&self) -> String {
fn keyboard_layout(&self) -> Box<dyn PlatformKeyboardLayout> {
self.keyboard_layout()
}
@ -858,6 +858,26 @@ 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::*;