refactor keyboard layout

Junkui Zhang created

Change summary

crates/gpui/src/platform/linux/keyboard.rs       | 11 +++++++++--
crates/gpui/src/platform/linux/wayland/client.rs |  6 ++++++
crates/gpui/src/platform/linux/x11/client.rs     | 13 +++----------
3 files changed, 18 insertions(+), 12 deletions(-)

Detailed changes

crates/gpui/src/platform/linux/keyboard.rs 🔗

@@ -9,13 +9,13 @@ use strum::{EnumIter, IntoEnumIterator as _};
 use x11rb::{protocol::xkb::ConnectionExt as _, xcb_ffi::XCBConnection};
 #[cfg(any(feature = "wayland", feature = "x11"))]
 use xkbcommon::xkb::{
-    Keycode, Keysym,
+    Keycode, Keysym, STATE_LAYOUT_EFFECTIVE, State,
     x11::ffi::{XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION},
 };
 
 use crate::{PlatformKeyboardLayout, SharedString};
 
-#[derive(Clone)]
+#[derive(Debug, Clone)]
 pub(crate) struct LinuxKeyboardLayout {
     name: SharedString,
 }
@@ -34,6 +34,13 @@ impl LinuxKeyboardLayout {
     pub(crate) fn new(name: SharedString) -> Self {
         Self { name }
     }
+
+    #[cfg(any(feature = "wayland", feature = "x11"))]
+    pub(crate) fn unknown() -> Self {
+        Self {
+            id: "unknown".to_string(),
+        }
+    }
 }
 
 #[cfg(any(feature = "wayland", feature = "x11"))]

crates/gpui/src/platform/linux/wayland/client.rs 🔗

@@ -216,6 +216,7 @@ pub(crate) struct WaylandClientState {
     keyboard_layout: LinuxKeyboardLayout,
     keymap_state: Option<State>,
     compose_state: Option<xkb::compose::State>,
+    keyboard_layout: Box<LinuxKeyboardLayout>,
     keyboard_mapper: Option<LinuxKeyboardMapper>,
     drag: DragState,
     click: ClickState,
@@ -453,6 +454,7 @@ impl WaylandClient {
     pub(crate) fn new() -> Self {
         let conn = Connection::connect_to_env().unwrap();
 
+        let keyboard_layout = Box::new(LinuxKeyboardLayout::unknown());
         let (globals, mut event_queue) =
             registry_queue_init::<WaylandClientStatePtr>(&conn).unwrap();
         let qh = event_queue.handle();
@@ -577,6 +579,7 @@ impl WaylandClient {
             keymap_state: None,
             compose_state: None,
             keyboard_mapper: None,
+            keyboard_layout,
             drag: DragState {
                 data_offer: None,
                 window: None,
@@ -1218,9 +1221,12 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientStatePtr {
                     .flatten()
                     .expect("Failed to create keymap")
                 };
+                let keymap_state = xkb::State::new(&keymap);
+                let keyboard_layout = LinuxKeyboardLayout::new(&keymap_state);
                 state.keymap_state = Some(xkb::State::new(&keymap));
                 state.compose_state = get_xkb_compose_state(&xkb_context);
                 state.keyboard_mapper = Some(LinuxKeyboardMapper::new(0, 0, 0));
+                state.keyboard_layout = Box::new(keyboard_layout);
                 drop(state);
 
                 this.handle_keyboard_layout_change();

crates/gpui/src/platform/linux/x11/client.rs 🔗

@@ -206,6 +206,7 @@ pub struct X11ClientState {
     pub(crate) xkb: State,
     previous_xkb_state: XKBStateNotiy,
     keyboard_layout: LinuxKeyboardLayout,
+    pub(crate) keyboard_layout: Box<LinuxKeyboardLayout>,
     pub(crate) keyboard_mapper: LinuxKeyboardMapper,
     pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
     pub(crate) xim_handler: Option<XimHandler>,
@@ -426,6 +427,7 @@ impl X11Client {
             .layout_get_name(layout_idx)
             .to_string();
         let keyboard_layout = LinuxKeyboardLayout::new(layout_name.into());
+        let keyboard_layout = Box::new(LinuxKeyboardLayout::new(&xkb_state));
         let keyboard_mapper = LinuxKeyboardMapper::new(0, 0, 0);
 
         let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
@@ -983,16 +985,7 @@ impl X11Client {
                 drop(state);
                 self.handle_keyboard_layout_change();
                 state.keyboard_mapper = LinuxKeyboardMapper::new(0, 0, 0);
-                let layout_idx = state.xkb.serialize_layout(STATE_LAYOUT_EFFECTIVE);
-                let layout = LinuxKeyboardLayout::new(
-                    state
-                        .xkb
-                        .get_keymap()
-                        .layout_get_name(layout_idx)
-                        .to_string(),
-                )
-                .id()
-                .to_string();
+                let layout = LinuxKeyboardLayout::new(&state.xkb).id().to_string();
                 println!("X11 Keyboard layout: {:#?}", layout);
             }
             Event::XkbStateNotify(event) => {