From: tokyo4j Date: Mon, 6 May 2024 14:53:18 +0000 (+0900) Subject: seat: prevent Chromium from crashing when active keyboard is gone X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=cafdcd8e19c99d141afb5a631d1eaadad0a9f5f4;p=proto%2Flabwc.git seat: prevent Chromium from crashing when active keyboard is gone Chromium (and slurp) expect wl_keyboard.keymap event to be sent before wl_keyboard.modifiers event. Normally, wl_keyboard.keymap event is sent on the client first obtains wl_keyboard with wl_seat.get_keyboard request. However, after the active (especially virtual) keyboard is destroyed, wlroots doesn't respond to wl_seat.get_keyboard request with wl_keyboard.keymap event since there's no active keyboard on the seat. Therefore, if we run commands like "sleep 2; wtype hello; chromium", the active keyboard is destroyed when wtype finishes and wl_keyboard.modifiers event is sent to Chromium when Chromium first maps the surface and the keyboard focus is moved to it, then Chromium crashes. With slurp, fcitx5 and multi-monitor setup, a similar thing happens. When slurp first creates the layer-shell surfaces, the focus moves to it (without wl_keyboard.enter though), and fcitx5 is transiently deactivated and it destroys the virtual keyboard. Then when slurp maps those surfaces, the focus moves between them again and wl_keyboard.modifiers event is sent, thus slurp crashes. So with this commit, when the active keyboard on the seat is destroyed, the keyboard from the keyboard group is set to the seat instead so wlroots can respond to wl_seat.get_keyboard request with wl_keyboard.keymap. --- diff --git a/src/seat.c b/src/seat.c index 816e58dd..c16cdcda 100644 --- a/src/seat.c +++ b/src/seat.c @@ -31,6 +31,19 @@ input_device_destroy(struct wl_listener *listener, void *data) wl_list_remove(&keyboard->key.link); wl_list_remove(&keyboard->modifier.link); keyboard_cancel_keybind_repeat(keyboard); + /* + * If the active keyboard on the seat is destroyed, fall back + * to the keyboard from keyboard group so we can respond to + * wl_seat.get_keyboard requests with wl_keyboard.keymap event. + * This prevents Chromium from crashing when started just after + * the active keyboard is destroyed. + */ + struct wlr_keyboard *active_keyboard = + wlr_seat_get_keyboard(input->seat->seat); + if (!active_keyboard || active_keyboard == keyboard->wlr_keyboard) { + wlr_seat_set_keyboard(input->seat->seat, + &input->seat->keyboard_group->keyboard); + } } free(input); }