virtual_keyboard: Emulate key release events on destroy

According to libinput, release events are generated when device is unplugged,
and libinput copies this behavior for device removal. Let's do the same for
our virtual keyboard.

8f846a41fa

This is another attempt to fix #2034 and the following sway issue:

https://github.com/swaywm/sway/issues/6254

Note that we have other key repeating issues in sway, which aren't addressed
by this patch. Since the virtual keyboard itself isn't destroyed when the
keyboard grab is destroyed, we'll probably need some trick to reset the state
of the corresponding virtual keyboard when the grab is released.

https://github.com/swaywm/sway/issues/6095
https://github.com/swaywm/sway/issues/6193
This commit is contained in:
Yuya Nishihara 2021-05-06 17:33:39 +09:00 committed by Simon Ser
parent ed7f2651b6
commit 8008d21f5b

View file

@ -8,6 +8,7 @@
#include <wlr/util/log.h>
#include <xkbcommon/xkbcommon.h>
#include "util/signal.h"
#include "util/time.h"
#include "virtual-keyboard-unstable-v1-protocol.h"
@ -118,9 +119,31 @@ static void virtual_keyboard_modifiers(struct wl_client *client,
mods_depressed, mods_latched, mods_locked, group);
}
/**
* Send release event for each pressed key to bring the keyboard back to
* neutral state.
*
* This may be needed for virtual keyboards. For physical devices, kernel
* or libinput will deal with the removal of devices.
*/
static void keyboard_release_pressed_keys(struct wlr_keyboard *keyboard) {
size_t orig_num_keycodes = keyboard->num_keycodes;
for (size_t i = 0; i < orig_num_keycodes; ++i) {
assert(keyboard->num_keycodes == orig_num_keycodes - i);
struct wlr_event_keyboard_key event = {
.time_msec = get_current_time_msec(),
.keycode = keyboard->keycodes[orig_num_keycodes - i - 1],
.update_state = false,
.state = WL_KEYBOARD_KEY_STATE_RELEASED,
};
wlr_keyboard_notify_key(keyboard, &event); // updates num_keycodes
}
}
static void virtual_keyboard_destroy_resource(struct wl_resource *resource) {
struct wlr_virtual_keyboard_v1 *keyboard =
virtual_keyboard_from_resource(resource);
keyboard_release_pressed_keys(keyboard->input_device.keyboard);
wlr_signal_emit_safe(&keyboard->events.destroy, keyboard);
wl_list_remove(&keyboard->link);
wlr_input_device_destroy(&keyboard->input_device);