Skip to content

Commit 29ee055

Browse files
committed
feat(trackpad): macos scroll resolution hid descriptor
1 parent b246a7d commit 29ee055

File tree

4 files changed

+61
-65
lines changed

4 files changed

+61
-65
lines changed

drivers/sensors/navigator_trackpad.c

Lines changed: 18 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -357,36 +357,19 @@ report_mouse_t navigator_trackpad_get_report(report_mouse_t mouse_report) {
357357
scroll_inertia.vy -= friction_y;
358358

359359
// Convert Q8 velocity to scroll value
360+
# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING
361+
// macOS mode: send raw velocity deltas (descriptor tells macOS the resolution)
362+
int16_t scroll_x = scroll_inertia.vx / 256;
363+
int16_t scroll_y = scroll_inertia.vy / 256;
364+
# else
365+
// Hi-res mode: apply multiplier for Windows/Linux
360366
int16_t scroll_x = (scroll_inertia.vx * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER) / 256;
361367
int16_t scroll_y = (scroll_inertia.vy * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER) / 256;
368+
# endif
362369

363-
# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING
364-
// macOS mode: accumulate scroll and only output when threshold is crossed
365-
macos_scroll_accumulated_h += (float)scroll_x / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER;
366-
macos_scroll_accumulated_v += (float)scroll_y / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER;
367-
368-
float abs_h = (macos_scroll_accumulated_h < 0) ? -macos_scroll_accumulated_h : macos_scroll_accumulated_h;
369-
float abs_v = (macos_scroll_accumulated_v < 0) ? -macos_scroll_accumulated_v : macos_scroll_accumulated_v;
370-
371-
// Only output scroll when accumulated value crosses 1.0
372-
if (abs_h >= 1.0f) {
373-
scroll_x = (macos_scroll_accumulated_h > 0) ? 1 : -1;
374-
macos_scroll_accumulated_h -= (macos_scroll_accumulated_h > 0) ? 1.0f : -1.0f;
375-
} else {
376-
scroll_x = 0;
377-
}
378-
379-
if (abs_v >= 1.0f) {
380-
scroll_y = (macos_scroll_accumulated_v > 0) ? 1 : -1;
381-
macos_scroll_accumulated_v -= (macos_scroll_accumulated_v > 0) ? 1.0f : -1.0f;
382-
} else {
383-
scroll_y = 0;
384-
}
385-
# else
386-
// Hi-res mode: clamp to int8_t range
370+
// Clamp to int8_t range
387371
scroll_x = (scroll_x > 127) ? 127 : ((scroll_x < -127) ? -127 : scroll_x);
388372
scroll_y = (scroll_y > 127) ? 127 : ((scroll_y < -127) ? -127 : scroll_y);
389-
# endif
390373

391374
// Check if velocity is too low to continue
392375
int16_t abs_vx = scroll_inertia.vx < 0 ? -scroll_inertia.vx : scroll_inertia.vx;
@@ -604,11 +587,17 @@ report_mouse_t navigator_trackpad_get_report(report_mouse_t mouse_report) {
604587
if (delta_x != 0 || delta_y != 0) {
605588
# ifdef NAVIGATOR_TRACKPAD_SCROLL_WITH_TWO_FINGERS
606589
if (gesture.state == TP_SCROLLING) {
607-
// Two-finger scroll: output directly to h/v for high-res scrolling
608-
// With high-res scrolling enabled, the OS divides by 120 to get ticks
609-
// Apply multiplier to adjust scroll speed
590+
# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING
591+
// macOS mode: send raw deltas, macOS handles scaling via HIDScrollResolution
592+
// Apple trackpads report raw sensor deltas and let macOS apply acceleration
593+
int16_t scroll_x = delta_x;
594+
int16_t scroll_y = delta_y;
595+
# else
596+
// Hi-res mode: apply multiplier for Windows/Linux
597+
// These OSes divide by the Resolution Multiplier (120)
610598
int16_t scroll_x = delta_x * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER;
611599
int16_t scroll_y = delta_y * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER;
600+
# endif
612601

613602
# ifdef NAVIGATOR_TRACKPAD_SCROLL_INERTIA_ENABLE
614603
// Track velocity for inertia using exponential smoothing (Q8 fixed point)
@@ -638,34 +627,9 @@ report_mouse_t navigator_trackpad_get_report(report_mouse_t mouse_report) {
638627
}
639628
# endif
640629

641-
# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING
642-
// macOS mode: accumulate scroll and only output when threshold is crossed
643-
// This provides fine-grained speed control via the divider
644-
macos_scroll_accumulated_h += (float)scroll_x / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER;
645-
macos_scroll_accumulated_v += (float)scroll_y / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER;
646-
647-
float abs_h = (macos_scroll_accumulated_h < 0) ? -macos_scroll_accumulated_h : macos_scroll_accumulated_h;
648-
float abs_v = (macos_scroll_accumulated_v < 0) ? -macos_scroll_accumulated_v : macos_scroll_accumulated_v;
649-
650-
// Only output scroll when accumulated value crosses 1.0
651-
if (abs_h >= 1.0f) {
652-
scroll_x = (macos_scroll_accumulated_h > 0) ? 1 : -1;
653-
macos_scroll_accumulated_h -= (macos_scroll_accumulated_h > 0) ? 1.0f : -1.0f;
654-
} else {
655-
scroll_x = 0;
656-
}
657-
658-
if (abs_v >= 1.0f) {
659-
scroll_y = (macos_scroll_accumulated_v > 0) ? 1 : -1;
660-
macos_scroll_accumulated_v -= (macos_scroll_accumulated_v > 0) ? 1.0f : -1.0f;
661-
} else {
662-
scroll_y = 0;
663-
}
664-
# else
665-
// Hi-res mode: clamp to int8_t range for the report
630+
// Clamp to int8_t range for the report
666631
scroll_x = (scroll_x > 127) ? 127 : ((scroll_x < -127) ? -127 : scroll_x);
667632
scroll_y = (scroll_y > 127) ? 127 : ((scroll_y < -127) ? -127 : scroll_y);
668-
# endif
669633

670634
// Apply scroll inversion if configured
671635
# ifdef NAVIGATOR_SCROLL_INVERT_X

drivers/sensors/navigator_trackpad.h

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,12 @@
8888
// #define NAVIGATOR_TRACKPAD_SCROLL_WITH_TWO_FINGERS
8989

9090
// macOS scrolling mode (define to enable)
91-
// macOS doesn't respect the HID Resolution Multiplier descriptor and expects
92-
// small 1/-1 scroll reports instead. Enable this for macOS compatibility.
93-
// When enabled, scroll values are normalized to 1/-1 with accumulation for smooth control.
94-
// When disabled (default), uses hi-res scrolling with POINTING_DEVICE_HIRES_SCROLL_ENABLE
91+
// macOS doesn't respect the HID Resolution Multiplier descriptor.
92+
// When enabled, sends raw scroll deltas without the multiplier (like Apple trackpads).
93+
// macOS applies its own HIDScrollResolution (400 DPI) and acceleration curves.
94+
// When disabled (default), applies multiplier for Windows/Linux hi-res scrolling.
9595
// #define NAVIGATOR_TRACKPAD_MACOS_SCROLLING
9696

97-
// macOS scroll speed divider (higher = slower, default: 60)
98-
// Only used when NAVIGATOR_TRACKPAD_MACOS_SCROLLING is enabled
99-
// Adjust this value to control scroll speed on macOS
100-
#ifndef NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER
101-
# define NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER 60
102-
#endif
103-
10497
// Scroll inversion configuration
10598
// Define these to invert scroll direction on respective axes
10699
// #define NAVIGATOR_SCROLL_INVERT_X

tmk_core/protocol/usb_descriptor.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,20 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
195195
HID_RI_LOGICAL_MAXIMUM(16, 32767),
196196
HID_RI_REPORT_COUNT(8, 0x01),
197197
HID_RI_REPORT_SIZE(8, 0x10),
198+
# endif
199+
# ifdef POINTING_DEVICE_MACOS_SCROLL_RESOLUTION
200+
// Add physical units for macOS scrolling
201+
HID_RI_UNIT(8, 0x13), // English Linear (inches)
202+
HID_RI_UNIT_EXPONENT(8, -4), // 10^-4 scale
203+
# ifndef WHEEL_EXTENDED_REPORT
204+
// Calculate: (127 / UNITS_PER_INCH) * 10000 for 10^-4 scale
205+
HID_RI_PHYSICAL_MINIMUM(16, -(1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
206+
HID_RI_PHYSICAL_MAXIMUM(16, (1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
207+
# else
208+
// Calculate: (32767 / UNITS_PER_INCH) * 10000 for 10^-4 scale
209+
HID_RI_PHYSICAL_MINIMUM(16, -(327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
210+
HID_RI_PHYSICAL_MAXIMUM(16, (327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
211+
# endif
198212
# endif
199213
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
200214

@@ -211,6 +225,20 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
211225
HID_RI_LOGICAL_MAXIMUM(16, 32767),
212226
HID_RI_REPORT_COUNT(8, 0x01),
213227
HID_RI_REPORT_SIZE(8, 0x10),
228+
# endif
229+
# ifdef POINTING_DEVICE_MACOS_SCROLL_RESOLUTION
230+
// Add physical units for macOS scrolling
231+
HID_RI_UNIT(8, 0x13), // English Linear (inches)
232+
HID_RI_UNIT_EXPONENT(8, -4), // 10^-4 scale
233+
# ifndef WHEEL_EXTENDED_REPORT
234+
// Calculate: (127 / UNITS_PER_INCH) * 10000 for 10^-4 scale
235+
HID_RI_PHYSICAL_MINIMUM(16, -(1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
236+
HID_RI_PHYSICAL_MAXIMUM(16, (1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
237+
# else
238+
// Calculate: (32767 / UNITS_PER_INCH) * 10000 for 10^-4 scale
239+
HID_RI_PHYSICAL_MINIMUM(16, -(327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
240+
HID_RI_PHYSICAL_MAXIMUM(16, (327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)),
241+
# endif
214242
# endif
215243
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
216244

tmk_core/protocol/usb_descriptor_common.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@
3333
# define RAW_USAGE_ID 0x61
3434
#endif
3535

36+
/////////////////////
37+
// macOS Scroll Resolution (units per inch)
38+
// Lower value = more sensitive scrolling (default: 200 for 2x Apple sensitivity)
39+
// Apple trackpads use 400, but smaller trackpads need lower values
40+
41+
#ifdef POINTING_DEVICE_MACOS_SCROLL_RESOLUTION
42+
# ifndef POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH
43+
# define POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH 200
44+
# endif
45+
#endif
46+
3647
/////////////////////
3748
// Hires Scroll Defaults
3849

0 commit comments

Comments
 (0)