From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Alan Third Newsgroups: gmane.emacs.devel Subject: Re: Smoother macOS touchpad scrolling Date: Mon, 11 Sep 2017 19:09:20 +0100 Message-ID: <20170911180920.GA92807@breton.holly.idiocy.org> References: <20170908184634.GA20058@breton.holly.idiocy.org> <86y3pox258.fsf@misasa.okayama-u.ac.jp> <20170909081805.GA20275@breton.holly.idiocy.org> <86ingrl56v.fsf@misasa.okayama-u.ac.jp> <20170910083758.GA30315@breton.holly.idiocy.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="8P1HSweYDcXXzwPJ" Content-Transfer-Encoding: 8bit X-Trace: blaine.gmane.org 1505154043 31977 195.159.176.226 (11 Sep 2017 18:20:43 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 11 Sep 2017 18:20:43 +0000 (UTC) User-Agent: Mutt/1.7.2 (2016-11-26) Cc: Emacs-Devel devel To: Tak Kunihiro Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Sep 11 20:20:39 2017 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1drTK1-0007w1-5l for ged-emacs-devel@m.gmane.org; Mon, 11 Sep 2017 20:20:37 +0200 Original-Received: from localhost ([::1]:59718 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1drTK6-00047M-Sl for ged-emacs-devel@m.gmane.org; Mon, 11 Sep 2017 14:20:42 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:58149) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1drT9D-00024z-UY for emacs-devel@gnu.org; Mon, 11 Sep 2017 14:09:29 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1drT9C-0007DC-65 for emacs-devel@gnu.org; Mon, 11 Sep 2017 14:09:27 -0400 Original-Received: from mail-wm0-x236.google.com ([2a00:1450:400c:c09::236]:45021) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1drT9B-0007CS-QU for emacs-devel@gnu.org; Mon, 11 Sep 2017 14:09:26 -0400 Original-Received: by mail-wm0-x236.google.com with SMTP id 189so10596317wmh.1 for ; Mon, 11 Sep 2017 11:09:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=iOEQQHhmclFtbDJd3qgqUqJMHABnbYomLuU1Z2dOqjc=; b=pj61g2/O7PfYNWciVtavdpyhtbHuypFWpxfwoFUcsVbz3Iv3gEPGAPJEfgmsaRfLsE I7ZudA0DWoGT/yzV75tKr5YHK07gC9jv6UfzCZdwraZuNRsoGeApJMSO9o315kEq6Wgk fHuHkouKXyV6xIsS7bljwZTBviuppVLgeharLy7DDajRmmx/wYVa+r+qAFft21fGPxyU xfpQeuin7wlBSROu2DmaaUFc+dU07+fzJW5L8+jsvF15cOuXEQVuV+BZkEjOf165TIIp iZxTJkNDrLeTNEAvzo3DgMmNwLUM/u9T42f1EIZzt4oD3Lmbluop5fn+DIknHipUOXxV TWFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :references:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=iOEQQHhmclFtbDJd3qgqUqJMHABnbYomLuU1Z2dOqjc=; b=PzZmj+APvZu1f/8na5O+OtQbPZEVQctAPOaFSwx0L8zuvAJJXWaXwj+ZS4gOxurjIU psBFf6MN2qCjtvPjuzIpwScXrRsrU4UcuG8ZUJBwww77hdFqoefdh+WhKjmuxZPjKY+F ISBvgwufvKoQCTtwFmqGhKIVTHNnBHWg7Re67CY0LrCBednKZUPyErj4KFGL0Xoeuhcn yH5EkZ631SEB5+YYbtsUvyoy9emMEXlMX09UFCTXiKMvWBt+RMfsXoXXJnr+FRtKroxu LmDXFJgPQgefVJKrYsheYx0xADHpIMQQa2M1wIcAMJwDEdlwEgaDxaVz3DbDN6dJwdsg ce2g== X-Gm-Message-State: AHPjjUjrh2BWjpaLVbq6J754lR7k81la+VBIYbRbzsr8baP7LPRanEHl DzrEG3B5Ey+7Bg== X-Google-Smtp-Source: AOwi7QDWoAnwvsYcI8phqNZbcSpQscbQ9RUYOWFdukOEhxE09/qdbNAt5Rb6ohZTgTtwekb97skLjQ== X-Received: by 10.28.226.84 with SMTP id z81mr7882258wmg.108.1505153363506; Mon, 11 Sep 2017 11:09:23 -0700 (PDT) Original-Received: from breton.holly.idiocy.org (ip6-2001-08b0-03f8-8129-2cce-997a-55b7-29ff.holly.idiocy.org. [2001:8b0:3f8:8129:2cce:997a:55b7:29ff]) by smtp.gmail.com with ESMTPSA id l15sm12645969wmd.23.2017.09.11.11.09.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Sep 2017 11:09:22 -0700 (PDT) Content-Disposition: inline In-Reply-To: <20170910083758.GA30315@breton.holly.idiocy.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::236 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:218102 Archived-At: --8P1HSweYDcXXzwPJ Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On Sun, Sep 10, 2017 at 09:37:58AM +0100, Alan Third wrote: > How about instead of using the default font height, I provide a > variable that the user can use to set a ‘line height’ of their own > choosing? i.e. ‘(setq ns-touchpad-scroll-line-height 1)’ for one > pixel. Updated patch attached. I’ve modified mousewheel scrolling so it also makes use of macOS’s built‐in mousewheel acceleration. My thinking was that if we turn off Emacs progressive scrolling for touchpad, then mousewheels can feel awfully slow. ns-use-system-mwheel-acceleration allows you to turn it off if you don’t like the new behaviour, but it has no effect on touchpad scrolling. If anyone gives the patch a try, please let me know what you think. -- Alan Third --8P1HSweYDcXXzwPJ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-Provide-smoother-touchpad-scrolling-on-macOS.patch" >From 6cca3c21434d63f9be3ee4a45a34eebd6226cada 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 * etc/NEWS: Describe changes. * lisp/term/ns-win.el (mouse-wheel-scroll-amount, mouse-wheel-progressive-speed): Set to smarter values for macOS touchpads. * src/nsterm.m (emacsView::mouseDown): Use precise scrolling deltas to calculate scrolling for touchpads and mouse wheels. (syms_of_nsterm): Add variables 'ns-use-system-mwheel-acceleration', 'ns-touchpad-scroll-line-height' and 'ns-touchpad-use-momentum'. --- etc/NEWS | 6 ++ lisp/term/ns-win.el | 7 +++ src/nsterm.m | 165 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 163 insertions(+), 15 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 3f1df23ec3..0f4a3d7884 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1817,6 +1817,12 @@ of frame decorations on macOS 10.9+. --- ** 'process-attributes' on Darwin systems now returns more information. +--- +** Mousewheel and trackpad scrolling on macOS 10.7+ now behaves more +like the macOS default. The new variables +'ns-use-system-mwheel-acceleration', 'ns-touchpad-scroll-line-height' +and 'ns-touchpad-use-momentum' can be used to customise the behavior. + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index cfce83f892..dfdcdfe23e 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -736,6 +736,13 @@ ns-paste-secondary (global-unset-key [horizontal-scroll-bar drag-mouse-1]) +;;;; macOS-like defaults for trackpad and mouse wheel scrolling. + +(when (featurep 'cocoa) + (setq mouse-wheel-scroll-amount '(1 ((shift) . 5) ((control)))) + (setq mouse-wheel-progressive-speed nil)) + + ;;;; Color support. ;; Functions for color panel + drag diff --git a/src/nsterm.m b/src/nsterm.m index 001e4576e8..1c3847e6ff 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -6498,24 +6498,142 @@ - (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 MAC_OS_X_VERSION_MIN_REQUIRED < 1070 + if ([theEvent respondsToSelector:@(hasPreciseScrollingDeltas)]) { - delta = [theEvent deltaX]; - if (delta == 0) +#endif + /* 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, the deltas represent a ratio of whole + * lines, so round up the number of scroll events sent per + * click. This means we always send at least one scroll + * event per click, but can still scroll more than one line + * if the OS tells us to. + */ + bool horizontal; + int lines = 0; + int scrollUp = NO; + + /* FIXME: At the top or bottom of the buffer we should + * ignore momentum-phase events. */ + if (! ns_touchpad_use_momentum + && [theEvent momentumPhase] != NSEventPhaseNone) + return; + + if ([theEvent hasPreciseScrollingDeltas]) { - NSTRACE_MSG ("deltaIsZero"); - return; + static int totalDeltaX, totalDeltaY; + int lineHeight; + + if (NUMBERP (ns_touchpad_scroll_line_height)) + lineHeight = XINT (ns_touchpad_scroll_line_height); + else + { + /* FIXME: Use actual line height instead of the default. */ + 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; + scrollUp = totalDeltaX > 0; + + lines = abs (totalDeltaX / lineHeight); + totalDeltaX = totalDeltaX % lineHeight; + totalDeltaY = 0; + } + else if (abs (totalDeltaY) >= abs (totalDeltaX) + && abs (totalDeltaY) > lineHeight) + { + horizontal = NO; + scrollUp = totalDeltaY > 0; + + lines = abs (totalDeltaY / lineHeight); + totalDeltaY = totalDeltaY % lineHeight; + totalDeltaX = 0; + } } - emacs_event->kind = HORIZ_WHEEL_EVENT; + else + { + CGFloat delta; + + if ([theEvent scrollingDeltaY] == 0) + { + horizontal = YES; + delta = [theEvent scrollingDeltaX]; + } + else + { + horizontal = NO; + delta = [theEvent scrollingDeltaY]; + } + + lines = (ns_use_system_mwheel_acceleration) + ? ceil (fabs (delta)) : 1; + + scrollUp = delta > 0; + } + + for (int i = 0 ; i < lines ; i++) + { + emacs_event->kind = horizontal ? HORIZ_WHEEL_EVENT : WHEEL_EVENT; + + emacs_event->code = 0; + emacs_event->modifiers = EV_MODIFIERS (theEvent) | + (scrollUp ? up_modifier : down_modifier); + XSETINT (emacs_event->x, lrint (p.x)); + XSETINT (emacs_event->y, lrint (p.y)); + EV_TRAILER (theEvent); + } +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 } else - emacs_event->kind = WHEEL_EVENT; +#endif +#endif /* defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ +#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 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); + XSETINT (emacs_event->x, lrint (p.x)); + XSETINT (emacs_event->y, lrint (p.y)); + EV_TRAILER (theEvent); + } +#endif } else { @@ -6523,10 +6641,10 @@ - (void)mouseDown: (NSEvent *)theEvent emacs_event->code = EV_BUTTON (theEvent); emacs_event->modifiers = EV_MODIFIERS (theEvent) | EV_UDMODIFIERS (theEvent); + XSETINT (emacs_event->x, lrint (p.x)); + XSETINT (emacs_event->y, lrint (p.y)); + EV_TRAILER (theEvent); } - XSETINT (emacs_event->x, lrint (p.x)); - XSETINT (emacs_event->y, lrint (p.y)); - EV_TRAILER (theEvent); } @@ -9166,6 +9284,23 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with This variable is ignored on Mac OS X < 10.7 and GNUstep. */); ns_use_srgb_colorspace = YES; + DEFVAR_BOOL ("ns-use-system-mwheel-acceleration", + ns_use_system_mwheel_acceleration, + doc: /*Non-nil means use macOS's standard mouse wheel acceleration. +This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */); + ns_use_system_mwheel_acceleration = YES; + + DEFVAR_LISP ("ns-touchpad-scroll-line-height", ns_touchpad_scroll_line_height, + doc: /*The number of pixels touchpad scrolling considers a line. +Nil or a non-number means use the default frame line height. +This variable is ignored on macOS < 10.7 and GNUstep. Default is nil. */); + ns_touchpad_scroll_line_height = Qnil; + + DEFVAR_BOOL ("ns-touchpad-use-momentum", ns_touchpad_use_momentum, + doc: /*Non-nil means touchpad scrolling uses momentum. +This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */); + ns_touchpad_use_momentum = YES; + /* TODO: move to common code */ DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, doc: /* Which toolkit scroll bars Emacs uses, if any. -- 2.12.0 --8P1HSweYDcXXzwPJ--