unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Smoother macOS touchpad scrolling
@ 2017-09-08 18:46 Alan Third
  2017-09-08 22:21 ` Tak Kunihiro
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Third @ 2017-09-08 18:46 UTC (permalink / raw)
  To: Emacs-Devel devel

[-- Attachment #1: Type: text/plain, Size: 657 bytes --]

Attached is a patch to provide smoother scrolling with the touchpad on
macOS. It adds up the scrolling deltas and only sends a scroll event
when the total exceeds the frame’s default line‐height.

Scrolling quickly sometimes results in the screen stuttering a little.
I’m not sure if that’s just a result of scrolling quickly, or because
my code sends one scroll event for each line it wants to scroll and it
overloads Emacs redisplay or something.

Does anyone know if there’s a way, in C, to detect if we’re at the top
or bottom of the buffer? I’d rather not send momentum scroll events if
the buffer isn’t going to scroll.
-- 
Alan Third

[-- Attachment #2: 0001-Provide-smoother-touchpad-scrolling-on-macOS.patch --]
[-- Type: text/plain, Size: 5268 bytes --]

From 1c9ca5b5d38274eb1a2eb2aa28ef43ac4670d3a6 Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2017-09-19 19:12 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-08 18:46 Smoother macOS touchpad scrolling Alan Third
2017-09-08 22:21 ` Tak Kunihiro
2017-09-09  8:18   ` Alan Third
2017-09-10  1:20     ` Tak Kunihiro
2017-09-10  8:37       ` Alan Third
2017-09-11 18:09         ` Alan Third
2017-09-12  1:54           ` James Nguyen
2017-09-12 17:03             ` Alan Third
2017-09-12 23:13           ` Tak Kunihiro
2017-09-13 16:26             ` Better macOS scrolling (was: Smoother macOS touchpad scrolling) Alan Third
2017-09-13 22:52               ` Better macOS scrolling Tak Kunihiro
2017-09-16 22:33         ` Smoother macOS touchpad scrolling Alan Third
2017-09-18 18:10           ` Charles A. Roelli
2017-09-18 18:57             ` Charles A. Roelli
2017-09-18 19:03             ` Alan Third
2017-09-18 20:19               ` Charles A. Roelli
2017-09-19 19:12                 ` Alan Third

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).