aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-11-04 19:21:22 +0800
committerPo Lu2022-11-04 19:23:19 +0800
commit01471b5fdff21fcb23b7718d9cd99bf5c08645ba (patch)
treedb58de78daf1d609ab47d8dd8606527567d158a2
parenta248eb3d184d018795461b5d1a27a373fda4bce8 (diff)
downloademacs-01471b5fdff21fcb23b7718d9cd99bf5c08645ba.tar.gz
emacs-01471b5fdff21fcb23b7718d9cd99bf5c08645ba.zip
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)
-rw-r--r--src/xterm.c145
1 files changed, 117 insertions, 28 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 71ff69ece4c..4178526c318 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -13026,6 +13026,23 @@ xi_get_scroll_valuator (struct xi_device_t *device, int number)
13026 return NULL; 13026 return NULL;
13027} 13027}
13028 13028
13029/* Check if EVENT, a DeviceChanged event, contains any scroll
13030 valuators. */
13031
13032static bool
13033xi_has_scroll_valuators (XIDeviceChangedEvent *event)
13034{
13035 int i;
13036
13037 for (i = 0; i < event->num_classes; ++i)
13038 {
13039 if (event->classes[i]->type == XIScrollClass)
13040 return true;
13041 }
13042
13043 return false;
13044}
13045
13029#endif 13046#endif
13030 13047
13031/* Handle EVENT, a DeviceChanged event. Look up the device that 13048/* Handle EVENT, a DeviceChanged event. Look up the device that
@@ -13049,21 +13066,93 @@ xi_handle_device_changed (struct x_display_info *dpyinfo,
13049#endif 13066#endif
13050 13067
13051#ifdef HAVE_XINPUT2_1 13068#ifdef HAVE_XINPUT2_1
13052 /* When a DeviceChange event is received for a master device, we 13069 if (xi_has_scroll_valuators (event))
13053 don't get any scroll valuators along with it. This is possibly 13070 {
13054 an X server bug but I really don't want to dig any further, so 13071 /* Scroll valuators are provided by this event. Use the values
13055 fetch the scroll valuators manually. (bug#57020) */ 13072 provided in this event to populate the device's new scroll
13073 valuator list, as if this event's is a SlaveSwitch event
13074 caused by wheel movement, querying for the device info will
13075 probably return newer values, leading to a delta of 0 being
13076 computed when handling the subsequent XI_Motion event.
13077 (bug#58980) */
13056 13078
13057 x_catch_errors (dpyinfo->display); 13079 device->valuators = xrealloc (device->valuators,
13058 info = XIQueryDevice (dpyinfo->display, event->deviceid, 13080 (event->num_classes
13059 /* ndevices is always 1 if a deviceid is 13081 * sizeof *device->valuators));
13060 specified. If the request fails, NULL will 13082 device->scroll_valuator_count = 0;
13061 be returned. */ 13083#ifdef HAVE_XINPUT2_2
13062 &ndevices); 13084 device->direct_p = false;
13063 x_uncatch_errors (); 13085#endif
13086
13087 for (i = 0; i < event->num_classes; ++i)
13088 {
13089 switch (event->classes[i]->type)
13090 {
13091 case XIScrollClass:
13092 scroll = (XIScrollClassInfo *) event->classes[i];
13093
13094 valuator = &device->valuators[device->scroll_valuator_count++];
13095 valuator->horizontal = (scroll->scroll_type
13096 == XIScrollTypeHorizontal);
13097 valuator->invalid_p = true;
13098 valuator->emacs_value = 0;
13099 valuator->increment = scroll->increment;
13100 valuator->number = scroll->number;
13101 break;
13102
13103#ifdef HAVE_XINPUT2_2
13104 case XITouchClass:
13105 touch = (XITouchClassInfo *) event->classes[i];
13106
13107 if (touch->mode == XIDirectTouch)
13108 device->direct_p = true;
13109 break;
13110#endif
13111 }
13112 }
13113
13114 /* Restore the values of any scroll valuators that we already
13115 know about. */
13116
13117 for (i = 0; i < event->num_classes; ++i)
13118 {
13119 switch (event->classes[i]->type)
13120 {
13121 case XIValuatorClass:
13122 valuator_info = (XIValuatorClassInfo *) event->classes[i];
13123
13124 valuator = xi_get_scroll_valuator (device,
13125 valuator_info->number);
13126 if (valuator)
13127 {
13128 valuator->invalid_p = false;
13129 valuator->current_value = valuator_info->value;
13130 valuator->emacs_value = 0;
13131 }
13064 13132
13065 if (info) 13133 break;
13134 }
13135 }
13136 }
13137 else
13066 { 13138 {
13139 /* When a DeviceChange event is received for a master device,
13140 the X server sometimes does not send any scroll valuators
13141 along with it. This is possibly an X server bug but I really
13142 don't want to dig any further, so fetch the scroll valuators
13143 manually. (bug#57020) */
13144
13145 x_catch_errors (dpyinfo->display);
13146 info = XIQueryDevice (dpyinfo->display, event->deviceid,
13147 /* ndevices is always 1 if a deviceid is
13148 specified. If the request fails, NULL will
13149 be returned. */
13150 &ndevices);
13151 x_uncatch_errors ();
13152
13153 if (!info)
13154 return;
13155
13067 device->valuators = xrealloc (device->valuators, 13156 device->valuators = xrealloc (device->valuators,
13068 (info->num_classes 13157 (info->num_classes
13069 * sizeof *device->valuators)); 13158 * sizeof *device->valuators));
@@ -13115,32 +13204,32 @@ xi_handle_device_changed (struct x_display_info *dpyinfo,
13115 { 13204 {
13116 valuator->invalid_p = false; 13205 valuator->invalid_p = false;
13117 valuator->current_value = valuator_info->value; 13206 valuator->current_value = valuator_info->value;
13207 valuator->emacs_value = 0;
13118 } 13208 }
13119 13209
13120 break; 13210 break;
13121 } 13211 }
13122 } 13212 }
13123 13213
13124#ifdef HAVE_XINPUT2_2 13214 XIFreeDeviceInfo (info);
13125 /* The device is no longer a DirectTouch device, so 13215 }
13126 remove any touchpoints that we might have 13216#endif
13127 recorded. */
13128 if (!device->direct_p)
13129 {
13130 tem = device->touchpoints;
13131 13217
13132 while (tem) 13218#ifdef HAVE_XINPUT2_2
13133 { 13219 /* The device is no longer a DirectTouch device, so remove any
13134 last = tem; 13220 touchpoints that we might have recorded. */
13135 tem = tem->next; 13221 if (!device->direct_p)
13136 xfree (last); 13222 {
13137 } 13223 tem = device->touchpoints;
13138 13224
13139 device->touchpoints = NULL; 13225 while (tem)
13226 {
13227 last = tem;
13228 tem = tem->next;
13229 xfree (last);
13140 } 13230 }
13141#endif
13142 13231
13143 XIFreeDeviceInfo (info); 13232 device->touchpoints = NULL;
13144 } 13233 }
13145#endif 13234#endif
13146} 13235}