diff options
| author | Po Lu | 2021-11-26 19:59:54 +0800 |
|---|---|---|
| committer | Po Lu | 2021-11-26 21:06:22 +0800 |
| commit | 673eadaeb55de71016fab371613d8e930f6d7c04 (patch) | |
| tree | 71223245090fdf3bc6a3ab8b2c0d50287aedbc21 /src | |
| parent | 824d31e3bf22d57bc8f8011e6719b15059bea55b (diff) | |
| download | emacs-673eadaeb55de71016fab371613d8e930f6d7c04.tar.gz emacs-673eadaeb55de71016fab371613d8e930f6d7c04.zip | |
Explain confusing aspects of XInput 2 scroll wheel reporting
* src/xterm.c (x_init_master_valuators): Explain how XInput 2
reports scroll wheel movement.
(handle_one_xevent): Explain why XI2 scroll valuators
are reset after each enter events.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/xterm.c b/src/xterm.c index 821c92c4dda..c7950c6f9fc 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -372,6 +372,29 @@ x_free_xi_devices (struct x_display_info *dpyinfo) | |||
| 372 | unblock_input (); | 372 | unblock_input (); |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | /* The code below handles the tracking of scroll valuators on XInput | ||
| 376 | 2, in order to support scroll wheels that report information more | ||
| 377 | granular than a screen line. | ||
| 378 | |||
| 379 | On X, when the XInput 2 extension is being utilized, the states of | ||
| 380 | the mouse wheels in each axis are stored as absolute values inside | ||
| 381 | "valuators" attached to each mouse device. To obtain the delta of | ||
| 382 | the scroll wheel from a motion event (which is used to report that | ||
| 383 | some valuator has changed), it is necessary to iterate over every | ||
| 384 | valuator that changed, and compare its previous value to the | ||
| 385 | current value of the valuator. | ||
| 386 | |||
| 387 | Each individual valuator also has an "interval", which is the | ||
| 388 | amount you must divide that delta by in order to obtain a delta in | ||
| 389 | the terms of scroll units. | ||
| 390 | |||
| 391 | This delta however is still intermediate, to make driver | ||
| 392 | implementations easier. The XInput developers recommend (and most | ||
| 393 | programs use) the following algorithm to convert from scroll unit | ||
| 394 | deltas to pixel deltas: | ||
| 395 | |||
| 396 | pixels_scrolled = pow (window_height, 2.0 / 3.0) * delta; */ | ||
| 397 | |||
| 375 | /* Setup valuator tracking for XI2 master devices on | 398 | /* Setup valuator tracking for XI2 master devices on |
| 376 | DPYINFO->display. */ | 399 | DPYINFO->display. */ |
| 377 | 400 | ||
| @@ -9874,6 +9897,19 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 9874 | x_display_set_last_user_time (dpyinfo, xi_event->time); | 9897 | x_display_set_last_user_time (dpyinfo, xi_event->time); |
| 9875 | x_detect_focus_change (dpyinfo, any, event, &inev.ie); | 9898 | x_detect_focus_change (dpyinfo, any, event, &inev.ie); |
| 9876 | 9899 | ||
| 9900 | /* One problem behind the design of XInput 2 scrolling is | ||
| 9901 | that valuators are not unique to each window, but only | ||
| 9902 | the window that has grabbed the valuator's device or | ||
| 9903 | the window that the device's pointer is on top of can | ||
| 9904 | receive motion events. There is also no way to | ||
| 9905 | retrieve the value of a valuator outside of each motion | ||
| 9906 | event. | ||
| 9907 | |||
| 9908 | As such, to prevent wildly inaccurate results when the | ||
| 9909 | valuators have changed outside Emacs, we reset our | ||
| 9910 | records of each valuator's value whenever the pointer | ||
| 9911 | re-enters a frame after its valuators have potentially | ||
| 9912 | been changed elsewhere. */ | ||
| 9877 | if (enter->detail != XINotifyInferior | 9913 | if (enter->detail != XINotifyInferior |
| 9878 | && enter->mode != XINotifyPassiveUngrab | 9914 | && enter->mode != XINotifyPassiveUngrab |
| 9879 | && enter->mode != XINotifyUngrab && any) | 9915 | && enter->mode != XINotifyUngrab && any) |
| @@ -9947,6 +9983,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 9947 | struct xi_scroll_valuator_t *val; | 9983 | struct xi_scroll_valuator_t *val; |
| 9948 | double delta, scroll_unit; | 9984 | double delta, scroll_unit; |
| 9949 | 9985 | ||
| 9986 | |||
| 9987 | /* See the comment on top of | ||
| 9988 | x_init_master_valuators for more details on how | ||
| 9989 | scroll wheel movement is reported on XInput 2. */ | ||
| 9950 | delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid, | 9990 | delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid, |
| 9951 | i, *values, &val); | 9991 | i, *values, &val); |
| 9952 | 9992 | ||
| @@ -9972,7 +10012,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 9972 | goto XI_OTHER; | 10012 | goto XI_OTHER; |
| 9973 | } | 10013 | } |
| 9974 | 10014 | ||
| 9975 | scroll_unit = pow (FRAME_PIXEL_HEIGHT (f), 2.0 / 3.0); | ||
| 9976 | found_valuator = true; | 10015 | found_valuator = true; |
| 9977 | 10016 | ||
| 9978 | if (signbit (delta) != signbit (val->emacs_value)) | 10017 | if (signbit (delta) != signbit (val->emacs_value)) |
| @@ -9999,6 +10038,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 9999 | |= x_x_to_emacs_modifiers (dpyinfo, | 10038 | |= x_x_to_emacs_modifiers (dpyinfo, |
| 10000 | xev->mods.effective); | 10039 | xev->mods.effective); |
| 10001 | 10040 | ||
| 10041 | scroll_unit = pow (FRAME_PIXEL_HEIGHT (f), 2.0 / 3.0); | ||
| 10042 | |||
| 10002 | if (val->horizontal) | 10043 | if (val->horizontal) |
| 10003 | { | 10044 | { |
| 10004 | inev.ie.arg | 10045 | inev.ie.arg |