linux: Fix keyboard events not working on first start in X11 (#36224)
smit
created
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.
@@ -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);
+ }
}
}
}