diff options
| -rw-r--r-- | src/xterm.c | 145 |
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 | |||
| 13032 | static bool | ||
| 13033 | xi_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 | } |