aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-12-13 00:06:48 -0500
committerLibravatar Simon Ser <contact@emersion.fr>2019-12-13 09:53:51 +0100
commitf9ce8749dc4e4f4991aa336aba7137455aa67327 (patch)
treec0e7725fc1f290882730cf6c62f3420645427ba7
parentinput/keyboard: remove group listeners on destroy (diff)
downloadsway-f9ce8749dc4e4f4991aa336aba7137455aa67327.tar.gz
sway-f9ce8749dc4e4f4991aa336aba7137455aa67327.tar.zst
sway-f9ce8749dc4e4f4991aa336aba7137455aa67327.zip
input/keyboard: defer wlr_keyboard_group destroy
This defers the destruction of wlr_keyboard_groups until idle. This is to prevent the keyboard group's keyboard from being destroyed in the middle of handling a keyboard event. This would occur when changing the keymap of the last keyboard in a group with a keyboard binding. The prevents crashing when attempting to update the xkb state of the keyboard group's keyboard. The sway_keyboard_group is still immediately destroyed so that the group is no longer used
-rw-r--r--sway/input/keyboard.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index cac713ad..f71a7909 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -659,6 +659,10 @@ static bool keymaps_match(struct xkb_keymap *km1, struct xkb_keymap *km2) {
659 return result; 659 return result;
660} 660}
661 661
662static void destroy_empty_wlr_keyboard_group(void *data) {
663 wlr_keyboard_group_destroy(data);
664}
665
662static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { 666static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) {
663 struct sway_input_device *device = keyboard->seat_device->input_device; 667 struct sway_input_device *device = keyboard->seat_device->input_device;
664 struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; 668 struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard;
@@ -681,7 +685,11 @@ static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) {
681 free(sway_group->seat_device->input_device); 685 free(sway_group->seat_device->input_device);
682 free(sway_group->seat_device); 686 free(sway_group->seat_device);
683 free(sway_group); 687 free(sway_group);
684 wlr_keyboard_group_destroy(wlr_group); 688
689 // To prevent use-after-free conditions when handling key events, defer
690 // freeing the wlr_keyboard_group until idle
691 wl_event_loop_add_idle(server.wl_event_loop,
692 destroy_empty_wlr_keyboard_group, wlr_group);
685 } 693 }
686} 694}
687 695