>From 1c9ca5b5d38274eb1a2eb2aa28ef43ac4670d3a6 Mon Sep 17 00:00:00 2001 From: Alan Third Date: Fri, 8 Sep 2017 19:26:47 +0100 Subject: [PATCH] Provide smoother touchpad scrolling on macOS * lisp/term/ns-win.el (mouse-wheel-scroll-amount, mouse-wheel-progressive-speed): Set to smarter values for touchpads. * src/nsterm.m (emacsView::mouseDown): Use precise scrolling deltas to calculate scrolling for touchpads. --- lisp/term/ns-win.el | 9 ++++++ src/nsterm.m | 91 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index cfce83f892..488ea9cf0b 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -736,6 +736,15 @@ ns-paste-secondary (global-unset-key [horizontal-scroll-bar drag-mouse-1]) +;;;; Sane defaults for trackpad scrolling. + +;; These aren't so good for mousewheel scrolling, but we can't +;; differentiate between the two. + +(setq mouse-wheel-scroll-amount '(1 ((shift) . 5))) +(setq mouse-wheel-progressive-speed nil) + + ;;;; Color support. ;; Functions for color panel + drag diff --git a/src/nsterm.m b/src/nsterm.m index be97e94dd5..432e4ada86 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -6498,24 +6498,91 @@ - (void)mouseDown: (NSEvent *)theEvent if ([theEvent type] == NSEventTypeScrollWheel) { - CGFloat delta = [theEvent deltaY]; - /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */ - if (delta == 0) +#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + /* If the input device is a touchpad or similar, use precise + * scrolling deltas. These are measured in pixels, so we have + * to add them up until they exceed one line height, then we can + * send one, or more, scroll wheel events. + * + * If the device only has coarse scrolling deltas, like a real + * mousewheel, use the old method which sends one scroll event + * per mousewheel `click'. We could use precise deltas here + * too, but they can result in as little as one pixel change per + * `click', which would make it appear to the user as though + * nothing was happening. + */ + + if ([theEvent hasPreciseScrollingDeltas]) { - delta = [theEvent deltaX]; - if (delta == 0) + static int totalDeltaX, totalDeltaY; + bool horizontal; + int lines = 0; + int lineHeight = default_line_pixel_height(XWINDOW (FRAME_SELECTED_WINDOW (emacsframe))); + + if ([theEvent phase] == NSEventPhaseBegan) + { + totalDeltaX = 0; + totalDeltaY = 0; + } + + totalDeltaX += [theEvent scrollingDeltaX]; + totalDeltaY += [theEvent scrollingDeltaY]; + + /* Calculate the number of lines, if any, to scroll, and + * reset the total delta for the direction we're NOT + * scrolling so that small movements don't add up. */ + if (abs (totalDeltaX) > abs (totalDeltaY) + && abs (totalDeltaX) > lineHeight) + { + horizontal = YES; + lines = totalDeltaX / lineHeight; + totalDeltaX = totalDeltaX % lineHeight; + totalDeltaY = 0; + } + else if (abs (totalDeltaY) >= abs (totalDeltaX) + && abs (totalDeltaY) > lineHeight) + { + horizontal = NO; + lines = totalDeltaY / lineHeight; + totalDeltaY = totalDeltaY % lineHeight; + totalDeltaX = 0; + } + + for (int i = 0 ; i < abs (lines) ; i++) { - NSTRACE_MSG ("deltaIsZero"); - return; + emacs_event->kind = horizontal ? HORIZ_WHEEL_EVENT : WHEEL_EVENT; + + emacs_event->code = 0; + emacs_event->modifiers = EV_MODIFIERS (theEvent) | + ((lines > 0) ? up_modifier : down_modifier); + XSETINT (emacs_event->x, lrint (p.x)); + XSETINT (emacs_event->y, lrint (p.y)); + EV_TRAILER (theEvent); } - emacs_event->kind = HORIZ_WHEEL_EVENT; + return; } else - emacs_event->kind = WHEEL_EVENT; +#endif /* defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ + { + CGFloat delta = [theEvent deltaY]; + /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */ + if (delta == 0) + { + delta = [theEvent deltaX]; + if (delta == 0) + { + NSTRACE_MSG ("deltaIsZero"); + return; + } + emacs_event->kind = HORIZ_WHEEL_EVENT; + } + else + emacs_event->kind = WHEEL_EVENT; - emacs_event->code = 0; - emacs_event->modifiers = EV_MODIFIERS (theEvent) | - ((delta > 0) ? up_modifier : down_modifier); + emacs_event->code = 0; + emacs_event->modifiers = EV_MODIFIERS (theEvent) | + ((delta > 0) ? up_modifier : down_modifier); + } } else { -- 2.12.0