test work

Smit Barmase created

Change summary

crates/gpui/src/platform/linux/x11/client.rs | 90 ++++++++++++---------
1 file changed, 53 insertions(+), 37 deletions(-)

Detailed changes

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

@@ -139,13 +139,6 @@ impl From<xim::ClientError> for EventHandlerError {
     }
 }
 
-#[derive(Debug, Default, Clone)]
-struct XKBStateNotiy {
-    depressed_layout: LayoutIndex,
-    latched_layout: LayoutIndex,
-    locked_layout: LayoutIndex,
-}
-
 #[derive(Debug, Default)]
 pub struct Xdnd {
     other_window: xproto::Window,
@@ -198,7 +191,6 @@ pub struct X11ClientState {
     pub(crate) mouse_focused_window: Option<xproto::Window>,
     pub(crate) keyboard_focused_window: Option<xproto::Window>,
     pub(crate) xkb: xkbc::State,
-    previous_xkb_state: XKBStateNotiy,
     keyboard_layout: LinuxKeyboardLayout,
     pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
     pub(crate) xim_handler: Option<XimHandler>,
@@ -510,7 +502,6 @@ impl X11Client {
             mouse_focused_window: None,
             keyboard_focused_window: None,
             xkb: xkb_state,
-            previous_xkb_state: XKBStateNotiy::default(),
             keyboard_layout,
             ximc,
             xim_handler,
@@ -931,6 +922,22 @@ impl X11Client {
                 if let Some(handler) = state.xim_handler.as_mut() {
                     handler.window = event.event;
                 }
+                let reply = state
+                    .xcb_connection
+                    .xkb_get_state(xkb::ID::USE_CORE_KBD.into())
+                    .reply()
+                    .context("Failed to get XKB state on focus")
+                    .log_err();
+                if let Some(reply) = reply {
+                    state.xkb.update_mask(
+                        reply.base_mods.into(),
+                        reply.latched_mods.into(),
+                        reply.locked_mods.into(),
+                        reply.base_group as u32,
+                        reply.latch_group as u32,
+                        reply.lock_group.into(),
+                    );
+                }
                 drop(state);
                 self.enable_ime();
             }
@@ -965,11 +972,6 @@ impl X11Client {
                 let depressed_layout = xkb_state.serialize_layout(xkbc::STATE_LAYOUT_DEPRESSED);
                 let latched_layout = xkb_state.serialize_layout(xkbc::STATE_LAYOUT_LATCHED);
                 let locked_layout = xkb_state.serialize_layout(xkbc::ffi::XKB_STATE_LAYOUT_LOCKED);
-                state.previous_xkb_state = XKBStateNotiy {
-                    depressed_layout,
-                    latched_layout,
-                    locked_layout,
-                };
                 state.xkb = xkb_state;
                 drop(state);
                 self.handle_keyboard_layout_change();
@@ -986,11 +988,6 @@ impl X11Client {
                     event.latched_group as u32,
                     event.locked_group.into(),
                 );
-                state.previous_xkb_state = XKBStateNotiy {
-                    depressed_layout: event.base_group as u32,
-                    latched_layout: event.latched_group as u32,
-                    locked_layout: event.locked_group.into(),
-                };
 
                 let modifiers = Modifiers::from_xkb(&state.xkb);
                 let capslock = Capslock::from_xkb(&state.xkb);
@@ -1026,17 +1023,45 @@ impl X11Client {
                 let modifiers = modifiers_from_state(event.state);
                 state.modifiers = modifiers;
                 state.pre_key_char_down.take();
+
+                if let Ok(server_state) = state
+                    .xcb_connection
+                    .xkb_get_state(xkb::ID::USE_CORE_KBD.into())
+                    .reply()
+                {
+                    let client_effective_mods = state.xkb.serialize_mods(xkb::STATE_MODS_EFFECTIVE);
+                    let server_effective_mods = (server_state.base_mods
+                        | server_state.latched_mods
+                        | server_state.locked_mods)
+                        as u32;
+
+                    let num_groups = state.xkb.get_keymap().num_groups();
+                    let server_effective_layout =
+                        ((server_state.lock_group + server_state.latch_group + server_state.group)
+                            as u32)
+                            % num_groups;
+                    let client_effective_layout =
+                        state.xkb.serialize_layout(xkb::STATE_LAYOUT_EFFECTIVE);
+
+                    if server_effective_mods != client_effective_mods
+                        || server_effective_layout != client_effective_layout
+                    {
+                        state.xkb.update_mask(
+                            server_state.base_mods.into(),
+                            server_state.latched_mods.into(),
+                            server_state.locked_mods.into(),
+                            server_state.group as u32,
+                            server_state.latch_group as u32,
+                            server_state.lock_group.into(),
+                        );
+                        log::warn!("XKB state desync detected and corrected on KeyPress");
+                    }
+                } else {
+                    log::error!("Failed to query XKB state for desync check");
+                }
+
                 let keystroke = {
                     let code = event.detail.into();
-                    let xkb_state = state.previous_xkb_state.clone();
-                    state.xkb.update_mask(
-                        event.state.bits() as ModMask,
-                        0,
-                        0,
-                        xkb_state.depressed_layout,
-                        xkb_state.latched_layout,
-                        xkb_state.locked_layout,
-                    );
                     let mut keystroke = crate::Keystroke::from_xkb(&state.xkb, modifiers, code);
                     let keysym = state.xkb.key_get_one_sym(code);
                     if keysym.is_modifier_key() {
@@ -1096,15 +1121,6 @@ impl X11Client {
 
                 let keystroke = {
                     let code = event.detail.into();
-                    let xkb_state = state.previous_xkb_state.clone();
-                    state.xkb.update_mask(
-                        event.state.bits() as ModMask,
-                        0,
-                        0,
-                        xkb_state.depressed_layout,
-                        xkb_state.latched_layout,
-                        xkb_state.locked_layout,
-                    );
                     let keystroke = crate::Keystroke::from_xkb(&state.xkb, modifiers, code);
                     let keysym = state.xkb.key_get_one_sym(code);
                     if keysym.is_modifier_key() {