[at-spi2-core] AtspiDevice key grab fixes



commit 1a7d59f174a66d2b46a7774c1f09154a94ea151c
Author: Mike Gorse <mgorse suse com>
Date:   Wed May 12 15:46:05 2021 -0500

    AtspiDevice key grab fixes

 atspi/atspi-device-legacy.c | 16 +++++++++++--
 atspi/atspi-device-x11.c    | 57 +++++++++++++++++++++++++++++++++++++++++----
 atspi/atspi-device.c        | 16 +++++++++++--
 3 files changed, 81 insertions(+), 8 deletions(-)
---
diff --git a/atspi/atspi-device-legacy.c b/atspi/atspi-device-legacy.c
index 6c19b79..eb67768 100644
--- a/atspi/atspi-device-legacy.c
+++ b/atspi/atspi-device-legacy.c
@@ -47,6 +47,7 @@ struct _AtspiDeviceLegacyPrivate
   GSList *modifiers;
   guint virtual_mods_enabled;
   gboolean keyboard_grabbed;
+  unsigned int numlock_physical_mask;
 };
 
 GObjectClass *device_legacy_parent_class;
@@ -91,13 +92,19 @@ key_cb (AtspiDeviceEvent *event, void *user_data)
   AtspiDeviceLegacy *legacy_device = ATSPI_DEVICE_LEGACY (user_data);
   AtspiDeviceLegacyPrivate *priv = atspi_device_legacy_get_instance_private (legacy_device);
   gboolean ret = priv->keyboard_grabbed;
-
+  guint modifiers;
+  
   set_virtual_modifier (legacy_device, event->hw_code,
                         event->type == (AtspiEventType)ATSPI_KEY_PRESS);
+
+  modifiers = event->modifiers | priv->virtual_mods_enabled;
+  if (modifiers & (1 << ATSPI_MODIFIER_NUMLOCK))
+    modifiers &= ~priv->numlock_physical_mask;
+
   ret |= atspi_device_notify_key (ATSPI_DEVICE (legacy_device),
                                   event->type == (AtspiEventType)ATSPI_KEY_PRESS,
                                   event->hw_code, event->id,
-                                  event->modifiers | priv->virtual_mods_enabled,
+                                  modifiers,
                                   event->event_string);
 
   g_boxed_free (ATSPI_TYPE_DEVICE_EVENT, event);
@@ -126,6 +133,9 @@ check_virtual_modifier (AtspiDeviceLegacy *legacy_device, guint modifier)
   AtspiDeviceLegacyPrivate *priv = atspi_device_legacy_get_instance_private (legacy_device);
   GSList *l;
 
+  if (modifier == (1 << ATSPI_MODIFIER_NUMLOCK))
+    return TRUE;
+
   for (l = priv->modifiers; l; l = l->next)
   {
     AtspiLegacyKeyModifier *entry = l->data;
@@ -269,6 +279,8 @@ atspi_device_legacy_init (AtspiDeviceLegacy *device)
   priv->display=XOpenDisplay("");
   if (priv->display)
     priv->window = DefaultRootWindow(priv->display);
+  priv->numlock_physical_mask = XkbKeysymToModifiers (priv->display,
+                                                     XK_Num_Lock);
 #endif
 
 }
diff --git a/atspi/atspi-device-x11.c b/atspi/atspi-device-x11.c
index e8f2199..4f88e60 100644
--- a/atspi/atspi-device-x11.c
+++ b/atspi/atspi-device-x11.c
@@ -44,6 +44,7 @@ struct _AtspiDeviceX11Private
   GSList *key_grabs;
   guint virtual_mods_enabled;
   gboolean keyboard_grabbed;
+  unsigned int numlock_physical_mask;
 };
 
 GObjectClass *device_x11_parent_class;
@@ -176,7 +177,7 @@ grab_has_active_duplicate (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab)
 }
 
 static void
-grab_key (AtspiDeviceX11 *x11_device, int keycode, int modmask)
+grab_key_aux (AtspiDeviceX11 *x11_device, int keycode, int modmask)
 {
   AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device);
   XIGrabModifiers xi_modifiers;
@@ -196,6 +197,22 @@ grab_key (AtspiDeviceX11 *x11_device, int keycode, int modmask)
   XIGrabKeycode (priv->display, XIAllMasterDevices, keycode, priv->window, XIGrabModeSync, XIGrabModeAsync, 
False, &eventmask, 1, &xi_modifiers);
 }
 
+static void
+grab_key (AtspiDeviceX11 *x11_device, int keycode, int modmask)
+{
+  AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device);
+
+  grab_key_aux (x11_device, keycode, modmask);
+  if (!(modmask & LockMask))
+    grab_key_aux (x11_device, keycode, modmask | LockMask);
+  if (!(modmask & priv->numlock_physical_mask))
+  {
+    grab_key_aux (x11_device, keycode, modmask | priv->numlock_physical_mask);
+    if (!(modmask & LockMask))
+      grab_key_aux (x11_device, keycode, modmask | LockMask | priv->numlock_physical_mask);
+  }
+}
+
 static void
 enable_key_grab (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab)
 {
@@ -209,7 +226,7 @@ enable_key_grab (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab)
 }
 
 static void
-ungrab_key (AtspiDeviceX11 *x11_device, int keycode, int modmask)
+ungrab_key_aux (AtspiDeviceX11 *x11_device, int keycode, int modmask)
 {
   AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device);
   XIGrabModifiers xi_modifiers;
@@ -220,6 +237,22 @@ ungrab_key (AtspiDeviceX11 *x11_device, int keycode, int modmask)
   XIUngrabKeycode (priv->display, XIAllMasterDevices, keycode, priv->window, sizeof(xi_modifiers), 
&xi_modifiers);
 }
 
+static void
+ungrab_key (AtspiDeviceX11 *x11_device, int keycode, int modmask)
+{
+  AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device);
+
+  ungrab_key_aux (x11_device, keycode, modmask);
+  if (!(modmask & LockMask))
+    ungrab_key_aux (x11_device, keycode, modmask | LockMask);
+  if (!(modmask & priv->numlock_physical_mask))
+  {
+    ungrab_key_aux (x11_device, keycode, modmask | priv->numlock_physical_mask);
+    if (!(modmask & LockMask))
+      ungrab_key_aux (x11_device, keycode, modmask | LockMask | priv->numlock_physical_mask);
+  }
+}
+
 static void
 disable_key_grab (AtspiDeviceX11 *x11_device, AtspiX11KeyGrab *grab)
 {
@@ -290,6 +323,7 @@ do_event_dispatch (gpointer user_data)
   char text[10];
   KeySym keysym;
   XComposeStatus status;
+  guint modifiers;
  
   while (XPending (display))
   {
@@ -301,7 +335,13 @@ do_event_dispatch (gpointer user_data)
     case KeyPress:
     case KeyRelease:
       XLookupString(&xevent.xkey, text, sizeof (text), &keysym, &status);
-      atspi_device_notify_key (ATSPI_DEVICE (device), (xevent.type == KeyPress), xevent.xkey.keycode, 
keysym, xevent.xkey.state | priv->virtual_mods_enabled, text);
+      modifiers = xevent.xkey.state | priv->virtual_mods_enabled;
+      if (modifiers & priv->numlock_physical_mask)
+      {
+        modifiers |= (1 << ATSPI_MODIFIER_NUMLOCK);
+        modifiers &= ~priv->numlock_physical_mask;
+      }
+      atspi_device_notify_key (ATSPI_DEVICE (device), (xevent.type == KeyPress), xevent.xkey.keycode, 
keysym, modifiers, text);
       break;
     case GenericEvent:
       if (xevent.xcookie.extension == priv->xi_opcode)
@@ -326,8 +366,11 @@ do_event_dispatch (gpointer user_data)
           if (!priv->device_id)
             priv->device_id = xiDevEv->deviceid;
           set_virtual_modifier (device, xiRawEv->detail, xevent.xcookie.evtype == XI_KeyPress);
+          modifiers = keyevent.xkey.state | priv->virtual_mods_enabled;
+          if (modifiers & priv->numlock_physical_mask)
+            modifiers |= (1 << ATSPI_MODIFIER_NUMLOCK);
           if (xiDevEv->deviceid == priv->device_id)
-            atspi_device_notify_key (ATSPI_DEVICE (device), (xevent.xcookie.evtype == XI_KeyPress), 
xiRawEv->detail, keysym, keyevent.xkey.state, text);
+            atspi_device_notify_key (ATSPI_DEVICE (device), (xevent.xcookie.evtype == XI_KeyPress), 
xiRawEv->detail, keysym, modifiers, text);
           /* otherwise it's probably a duplicate event from a key grab */
           XFreeEventData (priv->display, &xevent.xcookie);
           break;
@@ -396,6 +439,9 @@ check_virtual_modifier (AtspiDeviceX11 *x11_device, guint modifier)
   AtspiDeviceX11Private *priv = atspi_device_x11_get_instance_private (x11_device);
   GSList *l;
 
+  if (modifier == (1 << ATSPI_MODIFIER_NUMLOCK))
+    return TRUE;
+
   for (l = priv->modifiers; l; l = l->next)
   {
     AtspiX11KeyModifier *entry = l->data;
@@ -534,6 +580,9 @@ atspi_device_x11_init (AtspiDeviceX11 *device)
       create_event_source (device);
     }
   }
+
+  priv->numlock_physical_mask = XkbKeysymToModifiers (priv->display,
+                                                     XK_Num_Lock);
 }
 
 static void
diff --git a/atspi/atspi-device.c b/atspi/atspi-device.c
index 5f62dc3..e4a564c 100644
--- a/atspi/atspi-device.c
+++ b/atspi/atspi-device.c
@@ -107,6 +107,19 @@ atspi_device_new ()
   return ATSPI_DEVICE (atspi_device_legacy_new ());
 }
 
+static gboolean
+key_matches_modifiers (guint key_mods, guint grab_mods)
+{
+  /* The presence or lack thereof of locking modifiers should make no
+     difference when testing, but other modifiers should match. If the
+     keypress has modifiers that (a) the grab does not check for and (b) are
+     not lock modifiers, then we reject the match. Alt + left arrow should not
+     match a grab on left arrow, for instance, but whether numlock is on or
+     off would be irrelevant. */
+  key_mods &= ~((1 << ATSPI_MODIFIER_SHIFTLOCK) | (1 << ATSPI_MODIFIER_NUMLOCK));
+  return (key_mods == grab_mods);
+}
+
 gboolean
 atspi_device_notify_key (AtspiDevice *device, gboolean pressed, int keycode, int keysym, gint state, gchar 
*text)
 {
@@ -123,8 +136,7 @@ atspi_device_notify_key (AtspiDevice *device, gboolean pressed, int keycode, int
   for (l = priv->keygrabs; l; l = l->next)
   {
     AtspiKeyGrab *grab = l->data;
-    //if (keycode == grab->keycode && (grab->modifiers & state) == grab->modifiers)
-    if (keycode == grab->keycode && grab->modifiers == state)
+    if (keycode == grab->keycode && key_matches_modifiers (state, grab->modifiers))
     {
       if (grab->callback)
         grab->callback (device, pressed, keycode, keysym, state, text, grab->callback_data);


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