Skip to content

Commit 68efbd8

Browse files
authored
keybindings/modifiers (wayland): Remove old workaround for xwayland (#785)
clients, fix event processing for wayland clients. ref: https://gitlab.gnome.org/GNOME/mutter/-/commit/cefa4044d1 Fixes linuxmint/wayland#1.
1 parent c6be033 commit 68efbd8

5 files changed

Lines changed: 65 additions & 27 deletions

File tree

src/core/events.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "backends/x11/meta-backend-x11.h"
3030
#include "compositor/meta-window-actor-private.h"
3131
#include "core/display-private.h"
32+
#include "core/keybindings-private.h"
3233
#include "core/window-private.h"
3334
#include "meta/meta-backend.h"
3435

@@ -378,12 +379,21 @@ meta_display_handle_event (MetaDisplay *display,
378379
* handled (because it's one of our hot-keys, or because we are
379380
* in a keyboard-grabbed mode like moving a window, we don't
380381
* want to pass the key event to the compositor or Wayland at all.
382+
*
383+
* Exception: modifier-only key events should still reach Wayland clients
384+
* so they can handle modifier+click combinations (Ctrl+click, etc.).
385+
* The keybinding handler just tracks modifier state for overlay key
386+
* functionality, which doesn't conflict with clients also receiving
387+
* the modifier events.
381388
*/
382389
if (display->event_route != META_EVENT_ROUTE_COMPOSITOR_GRAB &&
383390
meta_keybindings_process_event (display, window, event))
384391
{
385392
bypass_clutter = TRUE;
386-
bypass_wayland = TRUE;
393+
#ifdef HAVE_WAYLAND
394+
if (!(IS_KEY_EVENT (event) && meta_keybindings_is_modifier (event->key.keyval)))
395+
#endif
396+
bypass_wayland = TRUE;
387397
goto out;
388398
}
389399

src/core/keybindings-private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ void meta_window_ungrab_all_keys (MetaWindow *window,
139139
gboolean meta_keybindings_process_event (MetaDisplay *display,
140140
MetaWindow *window,
141141
const ClutterEvent *event);
142+
gboolean meta_keybindings_is_modifier (xkb_keysym_t keysym);
142143
int meta_keybindings_get_mouse_zoom_modifiers (MetaDisplay *display);
143144
ClutterModifierType meta_display_get_window_grab_modifiers (MetaDisplay *display);
144145

src/core/keybindings.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,8 +1953,8 @@ meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp)
19531953
XIAsyncDevice, timestamp);
19541954
}
19551955

1956-
static gboolean
1957-
is_modifier (xkb_keysym_t keysym)
1956+
gboolean
1957+
meta_keybindings_is_modifier (xkb_keysym_t keysym)
19581958
{
19591959
switch (keysym)
19601960
{
@@ -2631,7 +2631,7 @@ process_keyboard_move_grab (MetaDisplay *display,
26312631
return TRUE;
26322632

26332633
/* don't end grab on modifier key presses */
2634-
if (is_modifier (event->keyval))
2634+
if (meta_keybindings_is_modifier (event->keyval))
26352635
return TRUE;
26362636

26372637
meta_window_get_frame_rect (window, &frame_rect);
@@ -2885,7 +2885,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
28852885
return TRUE;
28862886

28872887
/* don't end grab on modifier key presses */
2888-
if (is_modifier (event->keyval))
2888+
if (meta_keybindings_is_modifier (event->keyval))
28892889
return TRUE;
28902890

28912891
if (event->keyval == CLUTTER_KEY_Escape)

src/wayland/meta-wayland-keyboard.c

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,8 @@ meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard)
529529
MetaBackend *backend = meta_get_backend ();
530530
ClutterBackend *clutter_backend = clutter_get_default_backend ();
531531

532+
wl_array_init (&keyboard->pressed_keys);
533+
532534
keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
533535
g_signal_connect (keyboard->settings, "changed",
534536
G_CALLBACK (settings_changed), keyboard);
@@ -569,6 +571,8 @@ meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
569571
wl_list_remove (&keyboard->focus_resource_list);
570572
wl_list_init (&keyboard->focus_resource_list);
571573

574+
wl_array_release (&keyboard->pressed_keys);
575+
572576
g_clear_object (&keyboard->settings);
573577
}
574578

@@ -580,6 +584,45 @@ evdev_code (const ClutterKeyEvent *event)
580584
return event->hardware_keycode - 8;
581585
}
582586

587+
static void
588+
update_pressed_keys (MetaWaylandKeyboard *keyboard,
589+
uint32_t evdev_code,
590+
gboolean is_press)
591+
{
592+
if (is_press)
593+
{
594+
uint32_t *end = (uint32_t *) ((char *) keyboard->pressed_keys.data +
595+
keyboard->pressed_keys.size);
596+
uint32_t *k;
597+
598+
for (k = keyboard->pressed_keys.data; k < end; k++)
599+
{
600+
if (*k == evdev_code)
601+
return;
602+
}
603+
604+
k = wl_array_add (&keyboard->pressed_keys, sizeof (*k));
605+
if (k)
606+
*k = evdev_code;
607+
}
608+
else
609+
{
610+
uint32_t *end = (uint32_t *) ((char *) keyboard->pressed_keys.data +
611+
keyboard->pressed_keys.size);
612+
uint32_t *k;
613+
614+
for (k = keyboard->pressed_keys.data; k < end; k++)
615+
{
616+
if (*k == evdev_code)
617+
{
618+
*k = *(end - 1);
619+
keyboard->pressed_keys.size -= sizeof (*k);
620+
return;
621+
}
622+
}
623+
}
624+
}
625+
583626
void
584627
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
585628
const ClutterKeyEvent *event)
@@ -594,6 +637,8 @@ meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
594637
(CLUTTER_EVENT_FLAG_SYNTHETIC | CLUTTER_EVENT_FLAG_INPUT_METHOD)) != 0)
595638
return;
596639

640+
update_pressed_keys (keyboard, evdev_code (event), is_press);
641+
597642
/* If we get a key event but still have pending modifier state
598643
* changes from a previous event that didn't get cleared, we need to
599644
* send that state right away so that the new key event can be
@@ -698,30 +743,10 @@ static void
698743
broadcast_focus (MetaWaylandKeyboard *keyboard,
699744
struct wl_resource *resource)
700745
{
701-
struct wl_array fake_keys;
702-
703-
/* We never want to send pressed keys to wayland clients on
704-
* enter. The protocol says that we should send them, presumably so
705-
* that clients can trigger their own key repeat routine in case
706-
* they are given focus and a key is physically pressed.
707-
*
708-
* Unfortunately this causes some clients, in particular Xwayland,
709-
* to register key events that they really shouldn't handle,
710-
* e.g. on an Alt+Tab keybinding, where Alt is released before Tab,
711-
* clients would see Tab being pressed on enter followed by a key
712-
* release event for Tab, meaning that Tab would be processed by
713-
* the client when it really shouldn't.
714-
*
715-
* Since the use case for the pressed keys array on enter seems weak
716-
* to us, we'll just fake that there are no pressed keys instead
717-
* which should be spec compliant even if it might not be true.
718-
*/
719-
wl_array_init (&fake_keys);
720-
721-
keyboard_send_modifiers (keyboard, resource, keyboard->focus_serial);
722746
wl_keyboard_send_enter (resource, keyboard->focus_serial,
723747
keyboard->focus_surface->resource,
724-
&fake_keys);
748+
&keyboard->pressed_keys);
749+
keyboard_send_modifiers (keyboard, resource, keyboard->focus_serial);
725750
}
726751

727752
void

src/wayland/meta-wayland-keyboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ struct _MetaWaylandKeyboard
9595
uint32_t key_up_keycode;
9696
uint32_t key_up_serial;
9797

98+
struct wl_array pressed_keys;
99+
98100
MetaWaylandXkbInfo xkb_info;
99101
enum xkb_state_component mods_changed;
100102
xkb_mod_mask_t kbd_a11y_latched_mods;

0 commit comments

Comments
 (0)