diff options
author | Brian Ashworth <bosrsf04@gmail.com> | 2019-12-13 00:06:48 -0500 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2019-12-13 09:53:51 +0100 |
commit | f9ce8749dc4e4f4991aa336aba7137455aa67327 (patch) | |
tree | c0e7725fc1f290882730cf6c62f3420645427ba7 | |
parent | input/keyboard: remove group listeners on destroy (diff) | |
download | sway-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.c | 10 |
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 | ||
662 | static void destroy_empty_wlr_keyboard_group(void *data) { | ||
663 | wlr_keyboard_group_destroy(data); | ||
664 | } | ||
665 | |||
662 | static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { | 666 | static 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 | ||