@@ -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+
583626void
584627meta_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
698743broadcast_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
727752void
0 commit comments