diff --git a/drivers/sensors/navigator_trackpad.c b/drivers/sensors/navigator_trackpad.c index c0db6ca3a5..b1dd663486 100644 --- a/drivers/sensors/navigator_trackpad.c +++ b/drivers/sensors/navigator_trackpad.c @@ -357,36 +357,19 @@ report_mouse_t navigator_trackpad_get_report(report_mouse_t mouse_report) { scroll_inertia.vy -= friction_y; // Convert Q8 velocity to scroll value +# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING + // macOS mode: send raw velocity deltas (descriptor tells macOS the resolution) + int16_t scroll_x = scroll_inertia.vx / 256; + int16_t scroll_y = scroll_inertia.vy / 256; +# else + // Hi-res mode: apply multiplier for Windows/Linux int16_t scroll_x = (scroll_inertia.vx * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER) / 256; int16_t scroll_y = (scroll_inertia.vy * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER) / 256; +# endif -# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING - // macOS mode: accumulate scroll and only output when threshold is crossed - macos_scroll_accumulated_h += (float)scroll_x / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER; - macos_scroll_accumulated_v += (float)scroll_y / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER; - - float abs_h = (macos_scroll_accumulated_h < 0) ? -macos_scroll_accumulated_h : macos_scroll_accumulated_h; - float abs_v = (macos_scroll_accumulated_v < 0) ? -macos_scroll_accumulated_v : macos_scroll_accumulated_v; - - // Only output scroll when accumulated value crosses 1.0 - if (abs_h >= 1.0f) { - scroll_x = (macos_scroll_accumulated_h > 0) ? 1 : -1; - macos_scroll_accumulated_h -= (macos_scroll_accumulated_h > 0) ? 1.0f : -1.0f; - } else { - scroll_x = 0; - } - - if (abs_v >= 1.0f) { - scroll_y = (macos_scroll_accumulated_v > 0) ? 1 : -1; - macos_scroll_accumulated_v -= (macos_scroll_accumulated_v > 0) ? 1.0f : -1.0f; - } else { - scroll_y = 0; - } -# else - // Hi-res mode: clamp to int8_t range + // Clamp to int8_t range scroll_x = (scroll_x > 127) ? 127 : ((scroll_x < -127) ? -127 : scroll_x); scroll_y = (scroll_y > 127) ? 127 : ((scroll_y < -127) ? -127 : scroll_y); -# endif // Check if velocity is too low to continue 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) { if (delta_x != 0 || delta_y != 0) { # ifdef NAVIGATOR_TRACKPAD_SCROLL_WITH_TWO_FINGERS if (gesture.state == TP_SCROLLING) { - // Two-finger scroll: output directly to h/v for high-res scrolling - // With high-res scrolling enabled, the OS divides by 120 to get ticks - // Apply multiplier to adjust scroll speed +# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING + // macOS mode: send raw deltas, macOS handles scaling via HIDScrollResolution + // Apple trackpads report raw sensor deltas and let macOS apply acceleration + int16_t scroll_x = delta_x; + int16_t scroll_y = delta_y; +# else + // Hi-res mode: apply multiplier for Windows/Linux + // These OSes divide by the Resolution Multiplier (120) int16_t scroll_x = delta_x * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER; int16_t scroll_y = delta_y * NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER; +# endif # ifdef NAVIGATOR_TRACKPAD_SCROLL_INERTIA_ENABLE // 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) { } # endif -# ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING - // macOS mode: accumulate scroll and only output when threshold is crossed - // This provides fine-grained speed control via the divider - macos_scroll_accumulated_h += (float)scroll_x / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER; - macos_scroll_accumulated_v += (float)scroll_y / NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER; - - float abs_h = (macos_scroll_accumulated_h < 0) ? -macos_scroll_accumulated_h : macos_scroll_accumulated_h; - float abs_v = (macos_scroll_accumulated_v < 0) ? -macos_scroll_accumulated_v : macos_scroll_accumulated_v; - - // Only output scroll when accumulated value crosses 1.0 - if (abs_h >= 1.0f) { - scroll_x = (macos_scroll_accumulated_h > 0) ? 1 : -1; - macos_scroll_accumulated_h -= (macos_scroll_accumulated_h > 0) ? 1.0f : -1.0f; - } else { - scroll_x = 0; - } - - if (abs_v >= 1.0f) { - scroll_y = (macos_scroll_accumulated_v > 0) ? 1 : -1; - macos_scroll_accumulated_v -= (macos_scroll_accumulated_v > 0) ? 1.0f : -1.0f; - } else { - scroll_y = 0; - } -# else - // Hi-res mode: clamp to int8_t range for the report + // Clamp to int8_t range for the report scroll_x = (scroll_x > 127) ? 127 : ((scroll_x < -127) ? -127 : scroll_x); scroll_y = (scroll_y > 127) ? 127 : ((scroll_y < -127) ? -127 : scroll_y); -# endif // Apply scroll inversion if configured # ifdef NAVIGATOR_SCROLL_INVERT_X diff --git a/drivers/sensors/navigator_trackpad.h b/drivers/sensors/navigator_trackpad.h index c44c22b4b4..0f80034647 100644 --- a/drivers/sensors/navigator_trackpad.h +++ b/drivers/sensors/navigator_trackpad.h @@ -88,19 +88,12 @@ // #define NAVIGATOR_TRACKPAD_SCROLL_WITH_TWO_FINGERS // macOS scrolling mode (define to enable) -// macOS doesn't respect the HID Resolution Multiplier descriptor and expects -// small 1/-1 scroll reports instead. Enable this for macOS compatibility. -// When enabled, scroll values are normalized to 1/-1 with accumulation for smooth control. -// When disabled (default), uses hi-res scrolling with POINTING_DEVICE_HIRES_SCROLL_ENABLE +// macOS doesn't respect the HID Resolution Multiplier descriptor. +// When enabled, sends raw scroll deltas without the multiplier (like Apple trackpads). +// macOS applies its own HIDScrollResolution (400 DPI) and acceleration curves. +// When disabled (default), applies multiplier for Windows/Linux hi-res scrolling. // #define NAVIGATOR_TRACKPAD_MACOS_SCROLLING -// macOS scroll speed divider (higher = slower, default: 60) -// Only used when NAVIGATOR_TRACKPAD_MACOS_SCROLLING is enabled -// Adjust this value to control scroll speed on macOS -#ifndef NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER -# define NAVIGATOR_TRACKPAD_MACOS_SCROLL_DIVIDER 60 -#endif - // Scroll inversion configuration // Define these to invert scroll direction on respective axes // #define NAVIGATOR_SCROLL_INVERT_X diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index ceab9eef9a..55129af6c3 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -195,6 +195,20 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { HID_RI_LOGICAL_MAXIMUM(16, 32767), HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x10), +# endif +# ifdef POINTING_DEVICE_MACOS_SCROLL_RESOLUTION + // Add physical units for macOS scrolling + HID_RI_UNIT(8, 0x13), // English Linear (inches) + HID_RI_UNIT_EXPONENT(8, -4), // 10^-4 scale +# ifndef WHEEL_EXTENDED_REPORT + // Calculate: (127 / UNITS_PER_INCH) * 10000 for 10^-4 scale + HID_RI_PHYSICAL_MINIMUM(16, -(1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), + HID_RI_PHYSICAL_MAXIMUM(16, (1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), +# else + // Calculate: (32767 / UNITS_PER_INCH) * 10000 for 10^-4 scale + HID_RI_PHYSICAL_MINIMUM(16, -(327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), + HID_RI_PHYSICAL_MAXIMUM(16, (327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), +# endif # endif HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), @@ -211,6 +225,20 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { HID_RI_LOGICAL_MAXIMUM(16, 32767), HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x10), +# endif +# ifdef POINTING_DEVICE_MACOS_SCROLL_RESOLUTION + // Add physical units for macOS scrolling + HID_RI_UNIT(8, 0x13), // English Linear (inches) + HID_RI_UNIT_EXPONENT(8, -4), // 10^-4 scale +# ifndef WHEEL_EXTENDED_REPORT + // Calculate: (127 / UNITS_PER_INCH) * 10000 for 10^-4 scale + HID_RI_PHYSICAL_MINIMUM(16, -(1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), + HID_RI_PHYSICAL_MAXIMUM(16, (1270000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), +# else + // Calculate: (32767 / UNITS_PER_INCH) * 10000 for 10^-4 scale + HID_RI_PHYSICAL_MINIMUM(16, -(327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), + HID_RI_PHYSICAL_MAXIMUM(16, (327670000 / POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH)), +# endif # endif HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), diff --git a/tmk_core/protocol/usb_descriptor_common.h b/tmk_core/protocol/usb_descriptor_common.h index f782d83fbc..5c63d5b110 100644 --- a/tmk_core/protocol/usb_descriptor_common.h +++ b/tmk_core/protocol/usb_descriptor_common.h @@ -33,6 +33,17 @@ # define RAW_USAGE_ID 0x61 #endif +///////////////////// +// macOS Scroll Resolution (units per inch) +// Lower value = more sensitive scrolling (default: 200 for 2x Apple sensitivity) +// Apple trackpads use 400, but smaller trackpads need lower values + +#ifdef POINTING_DEVICE_MACOS_SCROLL_RESOLUTION +# ifndef POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH +# define POINTING_DEVICE_MACOS_SCROLL_UNITS_PER_INCH 200 +# endif +#endif + ///////////////////// // Hires Scroll Defaults