wayland: Account for doubly pressed/released keys in MetaWaylandKeyboard

Given the presence of IMs and the different paths in event handling to reach
one of them, we cannot make guesses about whether should stick to the original
hardware-triggered event, or wait/prefer a second hand IM event that might or
might not arrive. We also have no say for other IM foci unrelated to wayland
(e.g. ClutterText) triggering the double event emission.

So go with it and maintain our own internal state for keys, we already kinda
do, but mainly for warning purposes, at the time of updating the
MetaWaylandKeyboard state.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3044>
This commit is contained in:
Carlos Garnacho 2023-06-07 12:52:46 +02:00 committed by Marge Bot
parent 7b26aab08d
commit eaa09be17c

View File

@ -586,7 +586,7 @@ meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
g_clear_object (&keyboard->settings);
}
static void
static gboolean
update_pressed_keys (struct wl_array *keys,
uint32_t evdev_code,
gboolean is_press)
@ -600,12 +600,13 @@ update_pressed_keys (struct wl_array *keys,
for (k = keys->data; k < end; k++)
{
if (*k == evdev_code)
return;
return FALSE;
}
/* Otherwise add the key to the list of pressed keys */
k = wl_array_add (keys, sizeof (*k));
*k = evdev_code;
return TRUE;
}
else
{
@ -616,11 +617,11 @@ update_pressed_keys (struct wl_array *keys,
{
*k = *(end - 1);
keys->size -= sizeof (*k);
return;
return TRUE;
}
}
g_warning ("unexpected key release event for key 0x%x", evdev_code);
return FALSE;
}
}
@ -630,16 +631,9 @@ meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
{
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
/* Only handle real, non-synthetic, events here. The IM is free to reemit
* key events (incl. modifiers), handling those additionally will result
* in doubly-pressed keys.
*/
if ((event->flags &
(CLUTTER_EVENT_FLAG_SYNTHETIC | CLUTTER_EVENT_FLAG_INPUT_METHOD)) != 0)
if (!update_pressed_keys (&keyboard->pressed_keys, event->evdev_code, is_press))
return;
update_pressed_keys (&keyboard->pressed_keys, event->evdev_code, is_press);
/* If we get a key event but still have pending modifier state
* changes from a previous event that didn't get cleared, we need to
* send that state right away so that the new key event can be