diff options
| author | eynsai <47629346+eynsai@users.noreply.github.com> | 2025-04-22 18:04:31 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-23 00:04:31 +0200 |
| commit | 7a2cd0fa962eb5e6e18ce8b0213a7171bc823c1f (patch) | |
| tree | d7c62b67ba4d9402b822768d7013803d99cb9484 | |
| parent | 83818d1d6f7d1f590946756ad552e407bf9a2e1f (diff) | |
High resolution scrolling (without feature report parsing) (#24423)
* hires scrolling without feature report parsing
* fix valid range for exponent
* fix incorrect minimum exponent value documentation
| -rw-r--r-- | docs/features/pointing_device.md | 26 | ||||
| -rw-r--r-- | quantum/pointing_device/pointing_device.c | 19 | ||||
| -rw-r--r-- | quantum/pointing_device/pointing_device.h | 4 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 24 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_descriptor_common.h | 20 | ||||
| -rw-r--r-- | tmk_core/protocol/vusb/vusb.c | 28 |
6 files changed, 119 insertions, 2 deletions
diff --git a/docs/features/pointing_device.md b/docs/features/pointing_device.md index 0ecf82c8df..a139df9dc4 100644 --- a/docs/features/pointing_device.md +++ b/docs/features/pointing_device.md | |||
| @@ -419,6 +419,32 @@ The `POINTING_DEVICE_CS_PIN`, `POINTING_DEVICE_SDIO_PIN`, and `POINTING_DEVICE_S | |||
| 419 | Any pointing device with a lift/contact status can integrate inertial cursor feature into its driver, controlled by `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE`. e.g. PMW3360 can use Lift_Stat from Motion register. Note that `POINTING_DEVICE_MOTION_PIN` cannot be used with this feature; continuous polling of `get_report()` is needed to generate glide reports. | 419 | Any pointing device with a lift/contact status can integrate inertial cursor feature into its driver, controlled by `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE`. e.g. PMW3360 can use Lift_Stat from Motion register. Note that `POINTING_DEVICE_MOTION_PIN` cannot be used with this feature; continuous polling of `get_report()` is needed to generate glide reports. |
| 420 | ::: | 420 | ::: |
| 421 | 421 | ||
| 422 | ## High Resolution Scrolling | ||
| 423 | |||
| 424 | | Setting | Description | Default | | ||
| 425 | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- | | ||
| 426 | | `POINTING_DEVICE_HIRES_SCROLL_ENABLE` | (Optional) Enables high resolution scrolling. | _not defined_ | | ||
| 427 | | `POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER`| (Optional) Resolution mutiplier value used by high resolution scrolling. Must be between 1 and 127, inclusive. | `120` | | ||
| 428 | | `POINTING_DEVICE_HIRES_SCROLL_EXPONENT` | (Optional) Resolution exponent value used by high resolution scrolling. Must be between 0 and 127, inclusive. | `0` | | ||
| 429 | |||
| 430 | The `POINTING_DEVICE_HIRES_SCROLL_ENABLE` setting enables smooth and continuous scrolling when using trackballs or high-end encoders as mouse wheels (as opposed to the typical stepped behavior of most mouse wheels). | ||
| 431 | This works by adding a resolution multiplier to the HID descriptor for mouse wheel reports, causing the host computer to interpret each wheel tick sent by the keyboard as a fraction of a normal wheel tick. | ||
| 432 | The resolution multiplier is set to `1 / (POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER * (10 ^ POINTING_DEVICE_HIRES_SCROLL_EXPONENT))`, which is `1 / 120` by default. | ||
| 433 | If even smoother scrolling than provided by this default value is desired, first try using `#define POINTING_DEVICE_HIRES_SCROLL_EXPONENT 1` which will result in a multiplier of `1 / 1200`. | ||
| 434 | |||
| 435 | The function `pointing_device_get_hires_scroll_resolution()` can be called to get the pre-computed resolution multiplier value as a `uint16_t`. | ||
| 436 | |||
| 437 | ::: warning | ||
| 438 | High resolution scrolling usually results in larger and/or more frequent mouse reports. This can result in overflow errors and overloading of the host computer's input buffer. | ||
| 439 | To deal with these issues, define `WHEEL_EXTENDED_REPORT` and throttle the rate at which mouse reports are sent. | ||
| 440 | ::: | ||
| 441 | |||
| 442 | ::: warning | ||
| 443 | Many programs, especially those that implement their own smoothing for scrolling, don't work well when they receive simultaneous vertical and horizontal wheel inputs (e.g. from high resolution drag-scroll using a trackball). | ||
| 444 | These programs typically implement their smoothing in a way that assumes the user will only scroll in one axis at a time, resulting in slow or jittery motion when trying to scroll at an angle. | ||
| 445 | This can be addressed by snapping scrolling to one axis at a time. | ||
| 446 | ::: | ||
| 447 | |||
| 422 | ## Split Keyboard Configuration | 448 | ## Split Keyboard Configuration |
| 423 | 449 | ||
| 424 | The following configuration options are only available when using `SPLIT_POINTING_ENABLE` see [data sync options](split_keyboard#data-sync-options). The rotation and invert `*_RIGHT` options are only used with `POINTING_DEVICE_COMBINED`. If using `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` use the common configuration above to configure your pointing device. | 450 | The following configuration options are only available when using `SPLIT_POINTING_ENABLE` see [data sync options](split_keyboard#data-sync-options). The rotation and invert `*_RIGHT` options are only used with `POINTING_DEVICE_COMBINED`. If using `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` use the common configuration above to configure your pointing device. |
diff --git a/quantum/pointing_device/pointing_device.c b/quantum/pointing_device/pointing_device.c index e26416f968..5ee65c9c61 100644 --- a/quantum/pointing_device/pointing_device.c +++ b/quantum/pointing_device/pointing_device.c | |||
| @@ -25,6 +25,10 @@ | |||
| 25 | # include "mousekey.h" | 25 | # include "mousekey.h" |
| 26 | #endif | 26 | #endif |
| 27 | 27 | ||
| 28 | #ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 29 | # include "usb_descriptor_common.h" | ||
| 30 | #endif | ||
| 31 | |||
| 28 | #if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1 | 32 | #if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1 |
| 29 | # error More than one rotation selected. This is not supported. | 33 | # error More than one rotation selected. This is not supported. |
| 30 | #endif | 34 | #endif |
| @@ -78,6 +82,9 @@ uint16_t pointing_device_get_shared_cpi(void) { | |||
| 78 | 82 | ||
| 79 | static report_mouse_t local_mouse_report = {}; | 83 | static report_mouse_t local_mouse_report = {}; |
| 80 | static bool pointing_device_force_send = false; | 84 | static bool pointing_device_force_send = false; |
| 85 | #ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 86 | static uint16_t hires_scroll_resolution; | ||
| 87 | #endif | ||
| 81 | 88 | ||
| 82 | #define POINTING_DEVICE_DRIVER_CONCAT(name) name##_pointing_device_driver | 89 | #define POINTING_DEVICE_DRIVER_CONCAT(name) name##_pointing_device_driver |
| 83 | #define POINTING_DEVICE_DRIVER(name) POINTING_DEVICE_DRIVER_CONCAT(name) | 90 | #define POINTING_DEVICE_DRIVER(name) POINTING_DEVICE_DRIVER_CONCAT(name) |
| @@ -176,6 +183,12 @@ __attribute__((weak)) void pointing_device_init(void) { | |||
| 176 | # endif | 183 | # endif |
| 177 | #endif | 184 | #endif |
| 178 | } | 185 | } |
| 186 | #ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 187 | hires_scroll_resolution = POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER; | ||
| 188 | for (int i = 0; i < POINTING_DEVICE_HIRES_SCROLL_EXPONENT; i++) { | ||
| 189 | hires_scroll_resolution *= 10; | ||
| 190 | } | ||
| 191 | #endif | ||
| 179 | 192 | ||
| 180 | pointing_device_init_kb(); | 193 | pointing_device_init_kb(); |
| 181 | pointing_device_init_user(); | 194 | pointing_device_init_user(); |
| @@ -523,3 +536,9 @@ __attribute__((weak)) void pointing_device_keycode_handler(uint16_t keycode, boo | |||
| 523 | pointing_device_send(); | 536 | pointing_device_send(); |
| 524 | } | 537 | } |
| 525 | } | 538 | } |
| 539 | |||
| 540 | #ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 541 | uint16_t pointing_device_get_hires_scroll_resolution(void) { | ||
| 542 | return hires_scroll_resolution; | ||
| 543 | } | ||
| 544 | #endif \ No newline at end of file | ||
diff --git a/quantum/pointing_device/pointing_device.h b/quantum/pointing_device/pointing_device.h index 7bc059e594..d8b583c87e 100644 --- a/quantum/pointing_device/pointing_device.h +++ b/quantum/pointing_device/pointing_device.h | |||
| @@ -122,6 +122,10 @@ uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, poi | |||
| 122 | report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report); | 122 | report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report); |
| 123 | void pointing_device_keycode_handler(uint16_t keycode, bool pressed); | 123 | void pointing_device_keycode_handler(uint16_t keycode, bool pressed); |
| 124 | 124 | ||
| 125 | #ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 126 | uint16_t pointing_device_get_hires_scroll_resolution(void); | ||
| 127 | #endif | ||
| 128 | |||
| 125 | #if defined(SPLIT_POINTING_ENABLE) | 129 | #if defined(SPLIT_POINTING_ENABLE) |
| 126 | void pointing_device_set_shared_report(report_mouse_t report); | 130 | void pointing_device_set_shared_report(report_mouse_t report); |
| 127 | uint16_t pointing_device_get_shared_cpi(void); | 131 | uint16_t pointing_device_get_shared_cpi(void); |
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index c7fb660b65..ceab9eef9a 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c | |||
| @@ -165,6 +165,24 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | |||
| 165 | # endif | 165 | # endif |
| 166 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), | 166 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), |
| 167 | 167 | ||
| 168 | # ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 169 | HID_RI_COLLECTION(8, 0x02), | ||
| 170 | // Feature report and padding (1 byte) | ||
| 171 | HID_RI_USAGE(8, 0x48), // Resolution Multiplier | ||
| 172 | HID_RI_REPORT_COUNT(8, 0x01), | ||
| 173 | HID_RI_REPORT_SIZE(8, 0x02), | ||
| 174 | HID_RI_LOGICAL_MINIMUM(8, 0x00), | ||
| 175 | HID_RI_LOGICAL_MAXIMUM(8, 0x01), | ||
| 176 | HID_RI_PHYSICAL_MINIMUM(8, 1), | ||
| 177 | HID_RI_PHYSICAL_MAXIMUM(8, POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER), | ||
| 178 | HID_RI_UNIT_EXPONENT(8, POINTING_DEVICE_HIRES_SCROLL_EXPONENT), | ||
| 179 | HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), | ||
| 180 | HID_RI_PHYSICAL_MINIMUM(8, 0x00), | ||
| 181 | HID_RI_PHYSICAL_MAXIMUM(8, 0x00), | ||
| 182 | HID_RI_REPORT_SIZE(8, 0x06), | ||
| 183 | HID_RI_FEATURE(8, HID_IOF_CONSTANT), | ||
| 184 | # endif | ||
| 185 | |||
| 168 | // Vertical wheel (1 or 2 bytes) | 186 | // Vertical wheel (1 or 2 bytes) |
| 169 | HID_RI_USAGE(8, 0x38), // Wheel | 187 | HID_RI_USAGE(8, 0x38), // Wheel |
| 170 | # ifndef WHEEL_EXTENDED_REPORT | 188 | # ifndef WHEEL_EXTENDED_REPORT |
| @@ -179,6 +197,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | |||
| 179 | HID_RI_REPORT_SIZE(8, 0x10), | 197 | HID_RI_REPORT_SIZE(8, 0x10), |
| 180 | # endif | 198 | # endif |
| 181 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), | 199 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), |
| 200 | |||
| 182 | // Horizontal wheel (1 or 2 bytes) | 201 | // Horizontal wheel (1 or 2 bytes) |
| 183 | HID_RI_USAGE_PAGE(8, 0x0C),// Consumer | 202 | HID_RI_USAGE_PAGE(8, 0x0C),// Consumer |
| 184 | HID_RI_USAGE(16, 0x0238), // AC Pan | 203 | HID_RI_USAGE(16, 0x0238), // AC Pan |
| @@ -194,6 +213,11 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | |||
| 194 | HID_RI_REPORT_SIZE(8, 0x10), | 213 | HID_RI_REPORT_SIZE(8, 0x10), |
| 195 | # endif | 214 | # endif |
| 196 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), | 215 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), |
| 216 | |||
| 217 | # ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 218 | HID_RI_END_COLLECTION(0), | ||
| 219 | # endif | ||
| 220 | |||
| 197 | HID_RI_END_COLLECTION(0), | 221 | HID_RI_END_COLLECTION(0), |
| 198 | HID_RI_END_COLLECTION(0), | 222 | HID_RI_END_COLLECTION(0), |
| 199 | # ifndef MOUSE_SHARED_EP | 223 | # ifndef MOUSE_SHARED_EP |
diff --git a/tmk_core/protocol/usb_descriptor_common.h b/tmk_core/protocol/usb_descriptor_common.h index 909c230a99..f782d83fbc 100644 --- a/tmk_core/protocol/usb_descriptor_common.h +++ b/tmk_core/protocol/usb_descriptor_common.h | |||
| @@ -32,3 +32,23 @@ | |||
| 32 | #ifndef RAW_USAGE_ID | 32 | #ifndef RAW_USAGE_ID |
| 33 | # define RAW_USAGE_ID 0x61 | 33 | # define RAW_USAGE_ID 0x61 |
| 34 | #endif | 34 | #endif |
| 35 | |||
| 36 | ///////////////////// | ||
| 37 | // Hires Scroll Defaults | ||
| 38 | |||
| 39 | #ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 40 | # ifdef POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER | ||
| 41 | # if POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER > 127 || POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER < 1 | ||
| 42 | # error "POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER must be between 1 and 127, inclusive!" | ||
| 43 | # endif | ||
| 44 | # else | ||
| 45 | # define POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER 120 | ||
| 46 | # endif | ||
| 47 | # ifdef POINTING_DEVICE_HIRES_SCROLL_EXPONENT | ||
| 48 | # if POINTING_DEVICE_HIRES_SCROLL_EXPONENT > 127 || POINTING_DEVICE_HIRES_SCROLL_EXPONENT < 0 | ||
| 49 | # error "POINTING_DEVICE_HIRES_SCROLL_EXPONENT must be between 0 and 127, inclusive!" | ||
| 50 | # endif | ||
| 51 | # else | ||
| 52 | # define POINTING_DEVICE_HIRES_SCROLL_EXPONENT 0 | ||
| 53 | # endif | ||
| 54 | #endif \ No newline at end of file | ||
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index fdbfcc17dc..56cf82e5a6 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c | |||
| @@ -520,6 +520,24 @@ const PROGMEM uchar shared_hid_report[] = { | |||
| 520 | # endif | 520 | # endif |
| 521 | 0x81, 0x06, // Input (Data, Variable, Relative) | 521 | 0x81, 0x06, // Input (Data, Variable, Relative) |
| 522 | 522 | ||
| 523 | # ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE | ||
| 524 | // Feature report and padding (1 byte) | ||
| 525 | 0xA1, 0x02, // Collection (Logical) | ||
| 526 | 0x09, 0x48, // Usage (Resolution Multiplier) | ||
| 527 | 0x95, 0x01, // Report Count (1) | ||
| 528 | 0x75, 0x02, // Report Size (2) | ||
| 529 | 0x15, 0x00, // Logical Minimum (0) | ||
| 530 | 0x25, 0x01, // Logical Maximum (1) | ||
| 531 | 0x35, 0x01, // Physical Minimum (1) | ||
| 532 | 0x45, POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER, // Physical Maximum (POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER) | ||
| 533 | 0x55, POINTING_DEVICE_HIRES_SCROLL_EXPONENT, // Unit Exponent (POINTING_DEVICE_HIRES_SCROLL_EXPONENT) | ||
| 534 | 0xB1, 0x02, // Feature (Data, Variable, Absolute) | ||
| 535 | 0x35, 0x00, // Physical Minimum (0) | ||
| 536 | 0x45, 0x00, // Physical Maximum (0) | ||
| 537 | 0x75, 0x06, // Report Size (6) | ||
| 538 | 0xB1, 0x03, // Feature (Constant) | ||
| 539 | # endif | ||
| 540 | |||
| 523 | // Vertical wheel (1 or 2 bytes) | 541 | // Vertical wheel (1 or 2 bytes) |
| 524 | 0x09, 0x38, // Usage (Wheel) | 542 | 0x09, 0x38, // Usage (Wheel) |
| 525 | # ifndef WHEEL_EXTENDED_REPORT | 543 | # ifndef WHEEL_EXTENDED_REPORT |
| @@ -534,6 +552,7 @@ const PROGMEM uchar shared_hid_report[] = { | |||
| 534 | 0x75, 0x10, // Report Size (16) | 552 | 0x75, 0x10, // Report Size (16) |
| 535 | # endif | 553 | # endif |
| 536 | 0x81, 0x06, // Input (Data, Variable, Relative) | 554 | 0x81, 0x06, // Input (Data, Variable, Relative) |
| 555 | |||
| 537 | // Horizontal wheel (1 or 2 bytes) | 556 | // Horizontal wheel (1 or 2 bytes) |
| 538 | 0x05, 0x0C, // Usage Page (Consumer) | 557 | 0x05, 0x0C, // Usage Page (Consumer) |
| 539 | 0x0A, 0x38, 0x02, // Usage (AC Pan) | 558 | 0x0A, 0x38, 0x02, // Usage (AC Pan) |
| @@ -549,8 +568,13 @@ const PROGMEM uchar shared_hid_report[] = { | |||
| 549 | 0x75, 0x10, // Report Size (16) | 568 | 0x75, 0x10, // Report Size (16) |
| 550 | # endif | 569 | # endif |
| 551 | 0x81, 0x06, // Input (Data, Variable, Relative) | 570 | 0x81, 0x06, // Input (Data, Variable, Relative) |
| 552 | 0xC0, // End Collection | 571 | |
| 553 | 0xC0, // End Collection | 572 | # ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE |
| 573 | 0xC0, // End Collection | ||
| 574 | # endif | ||
| 575 | |||
| 576 | 0xC0, // End Collection | ||
| 577 | 0xC0, // End Collection | ||
| 554 | #endif | 578 | #endif |
| 555 | 579 | ||
| 556 | #ifdef EXTRAKEY_ENABLE | 580 | #ifdef EXTRAKEY_ENABLE |
