[gtk+/2.24: 3/7] win32: discard fake Control keyboard events



commit 10f124e0f0be35db7d514ac0db2b7107be0b6c35
Author: Marc-André Lureau <marcandre lureau gmail com>
Date:   Tue May 7 00:25:54 2013 +0200

    win32: discard fake Control keyboard events
    
    This seems to be a pretty undocumented aspect of Windows keyboard input,
    with some layouts (apprently many of the non-english ones), the client
    receives two consecutive keyboard input events when pressing AltGr.
    
    There doesn't seem to be any way to nicely avoid or discard those
    extra events since they really are just like the "real" ones.
    
    There has been some workaround in Xwin:
    http://cgit.freedesktop.org/xorg/xserver/tree/hw/xwin/winkeybd.c
    
    I adapted this code to experiment with it. It seems that the checking
    of the previous event isn't necessary and actually discard valid
    simultaneous key presses such as left alt+ctrl. However, I always
    get the next event in the message queue when pressing AltGr, so
    the basic idea seems to solve the issue.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=699787

 gdk/win32/gdkevents-win32.c |   71 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 71 insertions(+), 0 deletions(-)
---
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 8b345cb..00fe3bf 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -2029,6 +2029,70 @@ ensure_stacking_on_activate_app (MSG       *msg,
     }
 }
 
+static gboolean
+is_fake_control_l (GdkWindow *window, MSG *msg)
+{
+  LONG last_time = 0;
+  MSG next;
+
+  /* check the next message is Alt with same timestamp and discard press */
+  if ((msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN) &&
+       msg->wParam == VK_CONTROL &&
+      (HIWORD (msg->lParam) & KF_EXTENDED) == 0)
+    {
+      last_time = GetMessageTime ();
+
+      if (PeekMessage (&next, NULL, WM_KEYDOWN, WM_SYSKEYDOWN,
+                       PM_NOREMOVE))
+        {
+          if (next.message != WM_KEYDOWN && next.message != WM_SYSKEYDOWN)
+            last_time = 0;
+
+          else if (next.wParam == VK_MENU && (HIWORD (next.lParam) & KF_EXTENDED) &&
+                   next.time == last_time)
+            return TRUE;
+        }
+    }
+  /* check the next message is Alt with same timestamp and discard release */
+  else if ((msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) &&
+           msg->wParam == VK_CONTROL &&
+           (HIWORD (msg->lParam) & KF_EXTENDED) == 0)
+    {
+      last_time = GetMessageTime ();
+
+      if (PeekMessage (&next, NULL, WM_KEYUP, WM_SYSKEYUP,
+                       PM_NOREMOVE))
+        {
+          if (next.message != WM_KEYUP && next.message != WM_SYSKEYUP)
+            last_time = 0;
+
+          else if (next.wParam == VK_MENU && (HIWORD (next.lParam) & KF_EXTENDED) &&
+                   next.time == last_time)
+            return TRUE;
+        }
+    }
+#if 0
+  /* FIXME: this doesn't seem necessary, and it wrongly cancels
+     simultaneous valid lctrl+lalt events, but Xwin code has this:
+     if the event wasn't yet in the message queue, use a static
+     last_time, and discard the previous Ctrl event if it matches */
+  else if (last_time != 0 &&
+           (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN) &&
+           msg->wParam == VK_MENU &&
+           (HIWORD (msg->lParam) & KF_EXTENDED) == 0)
+    {
+        if (last_time == GetMessageTime ())
+            fake_release_control_r (window, msg);
+
+        last_time = 0;
+    }
+  else
+    last_time = 0;
+#endif
+
+  return FALSE;
+}
+
 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
                             GDK_BUTTON2_MASK | \
                             GDK_BUTTON3_MASK | \
@@ -2249,6 +2313,13 @@ gdk_event_translate (MSG  *msg,
          in_ime_composition)
        break;
 
+      /* Ignore fake Control_L generated with some keyboard layouts */
+      if (is_fake_control_l (window, msg))
+        {
+          GDK_NOTE (EVENTS, g_print ("Discarding fake Control event"));
+          break;
+        }
+
       if (!propagate (&window, msg,
                      _gdk_display->keyboard_grab.window,
                      _gdk_display->keyboard_grab.owner_events,


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