linux: Fix keyboard events not working on first start in X11 (#36224)

Closes #29083

On X11, `ibus-x11` crashes on some distros after Zed interacts with it.
This is not unique to Zed, `xim-rs` shows the same behavior, and there
are similar upstream `ibus` reports with apps like Blender:

- https://github.com/ibus/ibus/issues/2697

I opened an upstream issue to track this:

- https://github.com/ibus/ibus/issues/2789

When this crash happens, we don’t get a disconnect event, so Zed keeps
sending events to the IM server and waits for a response. It works on
subsequent starts because IM server doesn't exist now and we default to
non-XIM path.

This PR detects the crash via X11 events and falls back to the non-XIM
path so typing keeps working. We still need to investigate whether the
root cause is in `xim-rs` or `ibus-x11`.

Release Notes:

- Fixed an issue on X11 where keyboard input sometimes didn’t work on
first start.
This commit is contained in:
smit 2025-08-15 12:51:32 +05:30 committed by GitHub
parent 4d27b228f7
commit 23d0433158
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 19 deletions

View file

@ -209,7 +209,7 @@ xkbcommon = { version = "0.8.0", features = [
"wayland",
"x11",
], optional = true }
xim = { git = "https://github.com/XDeme1/xim-rs", rev = "d50d461764c2213655cd9cf65a0ea94c70d3c4fd", features = [
xim = { git = "https://github.com/zed-industries/xim-rs", rev = "c0a70c1bd2ce197364216e5e818a2cb3adb99a8d" , features = [
"x11rb-xcb",
"x11rb-client",
], optional = true }

View file

@ -642,13 +642,7 @@ impl X11Client {
let xim_connected = xim_handler.connected;
drop(state);
let xim_filtered = match ximc.filter_event(&event, &mut xim_handler) {
Ok(handled) => handled,
Err(err) => {
log::error!("XIMClientError: {}", err);
false
}
};
let xim_filtered = ximc.filter_event(&event, &mut xim_handler);
let xim_callback_event = xim_handler.last_callback_event.take();
let mut state = self.0.borrow_mut();
@ -659,14 +653,28 @@ impl X11Client {
self.handle_xim_callback_event(event);
}
if xim_filtered {
continue;
}
if xim_connected {
self.xim_handle_event(event);
} else {
self.handle_event(event);
match xim_filtered {
Ok(handled) => {
if handled {
continue;
}
if xim_connected {
self.xim_handle_event(event);
} else {
self.handle_event(event);
}
}
Err(err) => {
// this might happen when xim server crashes on one of the events
// we do lose 1-2 keys when crash happens since there is no reliable way to get that info
// luckily, x11 sends us window not found error when xim server crashes upon further key press
// hence we fall back to handle_event
log::error!("XIMClientError: {}", err);
let mut state = self.0.borrow_mut();
state.take_xim();
drop(state);
self.handle_event(event);
}
}
}
}