[gtk+/gtk-3-22] wayland: do not cancel key repeat on key press



commit 4146d7f3cc738d7d912adeccd2ef8e8f89b9671e
Author: Olivier Fourdan <ofourdan redhat com>
Date:   Thu Feb 2 10:43:45 2017 +0100

    wayland: do not cancel key repeat on key press
    
    The key repeat is stopped as soon as a key is pressed, so if the user
    quickly presses a key while another is already pressed and being
    repeated, key repeat gets cancelled:
    
     - key1 press
     - key1 repeat
     - key2 press -> key1 repeat stopped
     - key1 release
     - key 2 is not repeated even though it's kept depressed
    
    This is a different behavior from X11, which confuses migrating users.
    
    To mimic the X11 behavior, keep track of the number of keys pressed
    simultaneously and cancel key repeat only when none is pressed.
    
    This way, if a user pressed a key while another one is being repeated,
    the new key press can possibly be repeated as well.
    
    Bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=778019

 gdk/wayland/gdkdevice-wayland.c |   34 +++++++++++++++++++++++++---------
 1 files changed, 25 insertions(+), 9 deletions(-)
---
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index 9bc3477..815fa9a 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -227,6 +227,7 @@ struct _GdkWaylandSeat
   guint32 repeat_key;
   guint32 repeat_count;
   gint64 repeat_deadline;
+  gint32 nkeys;
   GSettings *keyboard_settings;
   uint32_t keyboard_time;
   uint32_t keyboard_key_serial;
@@ -307,7 +308,8 @@ struct _GdkWaylandDeviceManagerClass
 static void deliver_key_event (GdkWaylandSeat       *seat,
                                uint32_t              time_,
                                uint32_t              key,
-                               uint32_t              state);
+                               uint32_t              state,
+                               gboolean              from_key_repeat);
 GType gdk_wayland_device_manager_get_type (void);
 
 G_DEFINE_TYPE (GdkWaylandDeviceManager,
@@ -2077,7 +2079,8 @@ static void
 deliver_key_event (GdkWaylandSeat *seat,
                    uint32_t        time_,
                    uint32_t        key,
-                   uint32_t        state)
+                   uint32_t        state,
+                   gboolean        from_key_repeat)
 {
   GdkEvent *event;
   struct xkb_state *xkb_state;
@@ -2125,17 +2128,30 @@ deliver_key_event (GdkWaylandSeat *seat,
                        event->key.hardware_keycode, event->key.keyval,
                        event->key.string, event->key.state));
 
-  if (state == 0)
-    return;
-
   if (!xkb_keymap_key_repeats (xkb_keymap, key))
     return;
 
   if (!get_key_repeat (seat, &delay, &interval))
     return;
 
+  if (!from_key_repeat)
+    {
+      if (state) /* Another key is pressed */
+        {
+          seat->repeat_key = key;
+          seat->nkeys++;
+        }
+      else /* a key is released */
+        {
+          /* The compositor may send us more key releases than key presses */
+          seat->nkeys = MAX (0, seat->nkeys - 1);
+        }
+    }
+
+  if (seat->nkeys == 0)
+    return;
+
   seat->repeat_count++;
-  seat->repeat_key = key;
 
   interval *= 1000L;
   delay *= 1000L;
@@ -2165,8 +2181,7 @@ sync_after_repeat_callback (void               *data,
   GdkWaylandSeat *seat = data;
 
   g_clear_pointer (&seat->repeat_callback, wl_callback_destroy);
-
-  deliver_key_event (seat, seat->keyboard_time, seat->repeat_key, 1);
+  deliver_key_event (seat, seat->keyboard_time, seat->repeat_key, 1, TRUE);
 }
 
 static const struct wl_callback_listener sync_after_repeat_callback_listener = {
@@ -2213,7 +2228,8 @@ keyboard_handle_key (void               *data,
   seat->keyboard_key_serial = serial;
   seat->repeat_count = 0;
   _gdk_wayland_display_update_serial (display, serial);
-  deliver_key_event (data, time, key + 8, state_w);
+  deliver_key_event (data, time, key + 8, state_w, FALSE);
+
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]