Ensure bad values don't leak into scroll valuators after DeviceChange
authorPo Lu <luangruo@yahoo.com>
Mon, 14 Feb 2022 05:13:13 +0000 (13:13 +0800)
committerPo Lu <luangruo@yahoo.com>
Mon, 14 Feb 2022 05:14:54 +0000 (13:14 +0800)
* src/xterm.c (xi_reset_scroll_valuators_for_device_id): New
argument `pending_only'.
(handle_one_xevent): Reset pending scroll valuators on XI_Enter
and mark valuators updated via DeviceChanged events as pending.

* src/xterm.h (struct xi_scroll_valuator_t): New field
`pending_enter_reset'.

src/xterm.c
src/xterm.h

index 98c8a224080fb64afd23bd1ff9166dd7711eeeb1..9cde6c9a6832f853c8e41b9b0372f8364feb1604 100644 (file)
@@ -791,7 +791,8 @@ xi_find_touch_point (struct xi_device_t *device, int detail)
 #endif /* XI_TouchBegin */
 
 static void
-xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id)
+xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id,
+                                        bool pending_only)
 {
   struct xi_device_t *device = xi_device_from_id (dpyinfo, id);
   struct xi_scroll_valuator_t *valuator;
@@ -805,6 +806,11 @@ xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id)
   for (int i = 0; i < device->scroll_valuator_count; ++i)
     {
       valuator = &device->valuators[i];
+
+      if (pending_only && !valuator->pending_enter_reset)
+       continue;
+
+      valuator->pending_enter_reset = false;
       valuator->invalid_p = true;
       valuator->emacs_value = 0.0;
     }
@@ -10853,6 +10859,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
            if (!any)
              any = x_any_window_to_frame (dpyinfo, enter->event);
 
+           xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid,
+                                                    true);
+
            {
 #ifdef HAVE_XWIDGETS
              struct xwidget_view *xwidget_view = xwidget_view_from_window (enter->event);
@@ -10916,7 +10925,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
               moves out of a frame (and not into one of its
               children, which we know about).  */
            if (leave->detail != XINotifyInferior && any)
-             xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid);
+             xi_reset_scroll_valuators_for_device_id (dpyinfo,
+                                                      enter->deviceid, false);
 
 #ifdef HAVE_XWIDGETS
            {
@@ -11937,6 +11947,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                            {
                              device->valuators[i].invalid_p = false;
                              device->valuators[i].current_value = info->value;
+
+                             /* Make sure that this is reset if the
+                                pointer moves into a window of ours.
+
+                                Otherwise the valuator state could be
+                                left invalid if the DeviceChange
+                                event happened with the pointer
+                                outside any Emacs frame. */
+                             device->valuators[i].pending_enter_reset = true;
                            }
                        }
                    }
index 99c86ced56caa1b88ab2eee30f808f63e3a27642..f58fa0fe54d4421676397feb8030c627bed0e4e6 100644 (file)
@@ -184,6 +184,7 @@ struct color_name_cache_entry
 struct xi_scroll_valuator_t
 {
   bool invalid_p;
+  bool pending_enter_reset;
   double current_value;
   double emacs_value;
   double increment;