emacs-diffs
[Top][All Lists]
Advanced

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

master 01471b5fdf: Avoid using too up-to-date values when restoring valu


From: Po Lu
Subject: master 01471b5fdf: Avoid using too up-to-date values when restoring valuators
Date: Fri, 4 Nov 2022 07:23:31 -0400 (EDT)

branch: master
commit 01471b5fdff21fcb23b7718d9cd99bf5c08645ba
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Avoid using too up-to-date values when restoring valuators
    
    * src/xterm.c (xi_has_scroll_valuators): New function.
    (xi_handle_device_changed): If the device changed event provides
    scroll valuators, then use the values in there.  (bug#58980)
---
 src/xterm.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 117 insertions(+), 28 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index 71ff69ece4..4178526c31 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -13026,6 +13026,23 @@ xi_get_scroll_valuator (struct xi_device_t *device, 
int number)
   return NULL;
 }
 
+/* Check if EVENT, a DeviceChanged event, contains any scroll
+   valuators.  */
+
+static bool
+xi_has_scroll_valuators (XIDeviceChangedEvent *event)
+{
+  int i;
+
+  for (i = 0; i < event->num_classes; ++i)
+    {
+      if (event->classes[i]->type == XIScrollClass)
+       return true;
+    }
+
+  return false;
+}
+
 #endif
 
 /* Handle EVENT, a DeviceChanged event.  Look up the device that
@@ -13049,21 +13066,93 @@ xi_handle_device_changed (struct x_display_info 
*dpyinfo,
 #endif
 
 #ifdef HAVE_XINPUT2_1
-  /* When a DeviceChange event is received for a master device, we
-     don't get any scroll valuators along with it.  This is possibly
-     an X server bug but I really don't want to dig any further, so
-     fetch the scroll valuators manually.  (bug#57020) */
+  if (xi_has_scroll_valuators (event))
+    {
+      /* Scroll valuators are provided by this event.  Use the values
+        provided in this event to populate the device's new scroll
+        valuator list, as if this event's is a SlaveSwitch event
+        caused by wheel movement, querying for the device info will
+        probably return newer values, leading to a delta of 0 being
+        computed when handling the subsequent XI_Motion event.
+        (bug#58980) */
 
-  x_catch_errors (dpyinfo->display);
-  info = XIQueryDevice (dpyinfo->display, event->deviceid,
-                       /* ndevices is always 1 if a deviceid is
-                          specified.  If the request fails, NULL will
-                          be returned.  */
-                       &ndevices);
-  x_uncatch_errors ();
+      device->valuators = xrealloc (device->valuators,
+                                   (event->num_classes
+                                    * sizeof *device->valuators));
+      device->scroll_valuator_count = 0;
+#ifdef HAVE_XINPUT2_2
+      device->direct_p = false;
+#endif
+
+      for (i = 0; i < event->num_classes; ++i)
+       {
+         switch (event->classes[i]->type)
+           {
+           case XIScrollClass:
+             scroll = (XIScrollClassInfo *) event->classes[i];
+
+             valuator = &device->valuators[device->scroll_valuator_count++];
+             valuator->horizontal = (scroll->scroll_type
+                                     == XIScrollTypeHorizontal);
+             valuator->invalid_p = true;
+             valuator->emacs_value = 0;
+             valuator->increment = scroll->increment;
+             valuator->number = scroll->number;
+             break;
+
+#ifdef HAVE_XINPUT2_2
+           case XITouchClass:
+             touch = (XITouchClassInfo *) event->classes[i];
+
+             if (touch->mode == XIDirectTouch)
+               device->direct_p = true;
+             break;
+#endif
+           }
+       }
+
+      /* Restore the values of any scroll valuators that we already
+        know about.  */
+
+      for (i = 0; i < event->num_classes; ++i)
+       {
+         switch (event->classes[i]->type)
+           {
+           case XIValuatorClass:
+             valuator_info = (XIValuatorClassInfo *) event->classes[i];
+
+             valuator = xi_get_scroll_valuator (device,
+                                                valuator_info->number);
+             if (valuator)
+               {
+                 valuator->invalid_p = false;
+                 valuator->current_value = valuator_info->value;
+                 valuator->emacs_value = 0;
+               }
 
-  if (info)
+             break;
+           }
+       }
+    }
+  else
     {
+      /* When a DeviceChange event is received for a master device,
+        the X server sometimes does not send any scroll valuators
+        along with it.  This is possibly an X server bug but I really
+        don't want to dig any further, so fetch the scroll valuators
+        manually.  (bug#57020) */
+
+      x_catch_errors (dpyinfo->display);
+      info = XIQueryDevice (dpyinfo->display, event->deviceid,
+                           /* ndevices is always 1 if a deviceid is
+                              specified.  If the request fails, NULL will
+                              be returned.  */
+                           &ndevices);
+      x_uncatch_errors ();
+
+      if (!info)
+       return;
+
       device->valuators = xrealloc (device->valuators,
                                    (info->num_classes
                                     * sizeof *device->valuators));
@@ -13115,32 +13204,32 @@ xi_handle_device_changed (struct x_display_info 
*dpyinfo,
                {
                  valuator->invalid_p = false;
                  valuator->current_value = valuator_info->value;
+                 valuator->emacs_value = 0;
                }
 
              break;
            }
        }
 
-#ifdef HAVE_XINPUT2_2
-      /* The device is no longer a DirectTouch device, so
-        remove any touchpoints that we might have
-        recorded.  */
-      if (!device->direct_p)
-       {
-         tem = device->touchpoints;
+      XIFreeDeviceInfo (info);
+    }
+#endif
 
-         while (tem)
-           {
-             last = tem;
-             tem = tem->next;
-             xfree (last);
-           }
+#ifdef HAVE_XINPUT2_2
+  /* The device is no longer a DirectTouch device, so remove any
+     touchpoints that we might have recorded.  */
+  if (!device->direct_p)
+    {
+      tem = device->touchpoints;
 
-         device->touchpoints = NULL;
+      while (tem)
+       {
+         last = tem;
+         tem = tem->next;
+         xfree (last);
        }
-#endif
 
-      XIFreeDeviceInfo (info);
+      device->touchpoints = NULL;
     }
 #endif
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]