Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[defaults] Improve scrolling with mouse wheel #14542

Closed
wants to merge 3 commits into from

Conversation

syl20bnr
Copy link
Owner

Thanks to Profpatsch.

Fixes #1781

@duianto
Copy link
Collaborator

duianto commented Mar 23, 2021

With the cursor at the top of: .spacemacs

In the screen recordings below

The scroll wheel is turned three times at "normal" speed.
The wheel turned about 5 ticks each time.

Before applying the PR

It scrolls to quickly, it's easy to lose sight of how far one has scrolled.

The right side of the modeline shows that it scrolled to line 221 (18%).

One "benefit" might be that it doesn't take long to scroll to the bottom.

Depending on how fast one scrolls, in this 1286 line .spacemacs file,
it only takes about 7 turns.

before PR

After applying the PR

It's easy to see what one has scrolled past.

The right side of the modeline shows that it scrolled to line 43 (4%).

One "issue" might be that it takes a while to scroll to the bottom.
At 14 turns, the buffer is only at 20%.

But it's most likely better to:

  • be able to reliably see what one scrolls past
  • having the scroll rate be similar to other applications:
    3 lines at a time: notepad, vim, browsers? (probably depends on the font size)
    slightly less than 3: vscode

after PR

@duianto
Copy link
Collaborator

duianto commented Mar 23, 2021

Maybe one way of mouse scrolling longer distances.
Could be to temporarily show the scroll bar for a couple of seconds after mouse wheel scrolling.

      (defun spacemacs//scroll-bar-hide () (scroll-bar-mode -1))

      (defun spacemacs//scroll-bar-show-delayed-hide (&rest _ignore)
        "Show the scroll bar for a couple of seconds, before hiding it.

This can be used to temporarily show the scroll bar when mouse wheel scrolling.
(advice-add 'mwheel-scroll :after #'spacemacs//scroll-bar-show-delayed-hide)

The advice can be removed with:
(advice-remove 'mwheel-scroll #'spacemacs//scroll-bar-show-delayed-hide)"
        (scroll-bar-mode 1)
        (run-with-idle-timer 3 nil #'spacemacs//scroll-bar-hide))

      (advice-add 'mwheel-scroll :after #'spacemacs//scroll-bar-show-delayed-hide)
      ;; (advice-remove 'mwheel-scroll #'spacemacs//scroll-bar-show-delayed-hide)

@duianto
Copy link
Collaborator

duianto commented Mar 23, 2021

Another alternative.

Change scroll speed based on which third of the frame height, the mouse pointer is on.

The minibuffer shows the message:
scroll speed: 4 (on frame top third)
scroll speed: 2 (on frame top third)
scroll speed: 1 (on frame top third)

Maybe 4 isn't fast enough at the top

      (defun spacemacs/mouse-y () (cddr (mouse-position)))

      (defun spacemacs//frame-height-third () (/ (frame-height) 3))

      (defun spacemacs//mouse-on-frame-top-third ()
        (< (spacemacs/mouse-y) (spacemacs//frame-height-third)))

      (defun spacemacs//mouse-on-frame-middle-third ()
        (and (> (spacemacs/mouse-y) (spacemacs//frame-height-third))
             (< (spacemacs/mouse-y) (* (spacemacs//frame-height-third) 2))))

      (defun spacemacs//mouse-on-frame-bottom-third ()
        (> (spacemacs/mouse-y) (* (spacemacs//frame-height-third) 2)))

      (defun spacemacs/mwheel-scroll-speed-on-frame-height-thirds (&rest ignore)
        "Set the mouse wheel scroll speed, based on which
frame third height the mouse pointer is on.
4 lines at a time on the frames top third.
2 lines at a time on the frames middle third.
1 lines at a time on the frames bottom third.

This can be used to advice the mouse wheel scrolling:
(advice-add 'mwheel-scroll :after #'spacemacs/mwheel-scroll-speed-on-frame-height-thirds)

The advice can be removed like this:
(advice-remove 'mwheel-scroll #'spacemacs/mwheel-scroll-speed-on-frame-height-thirds)"
        (cond ((spacemacs//mouse-on-frame-top-third)
               (setq mouse-wheel-scroll-amount '(4 ((shift) . 1)))
               (let (message-log-max)
                 (message "scroll speed: 4 (on frame top third)")))
              ((spacemacs//mouse-on-frame-middle-third)
               (setq mouse-wheel-scroll-amount '(2 ((shift) . 1)))
               (let (message-log-max)
                 (message "scroll speed: 2 (on frame middle third)")))
              ((spacemacs//mouse-on-frame-bottom-third)
               (setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
               (let (message-log-max)
                 (message "scroll speed: 1 (on frame bottom third)")))))

      (advice-add 'mwheel-scroll :after #'spacemacs/mwheel-scroll-speed-on-frame-height-thirds)
      ;; (advice-remove 'mwheel-scroll #'spacemacs/mwheel-scroll-speed-on-frame-height-thirds)

@syl20bnr
Copy link
Owner Author

Great proposal @duianto !

I added the advice for the scroll bar which seems to be a pretty neat solution for people wanting to scroll faster.
Also I tweaked the amount to 1.
At least on my system (macOS) it feels right like this, what about you ?

@duianto
Copy link
Collaborator

duianto commented Mar 24, 2021

Is this needed? Since it's t by default in Emacs:

;; scroll window under mouse
mouse-wheel-follow-mouse 't

It is smoother with a lower scroll amount.

But 1 might be on the slow side. (possibly because the default scroll speed is so fast)

Auto show/hiding the scroll bar has some issues:

  • If one doesn't start dragging the handle within the idle time,
    (which happens easily in large files where the scroll handle is small),
    then the scroll bar will auto hide from under the cursor,
    which won't be pleasant. When it happens more than once,
    then people probably will try to disable it.
  • And toggling on the scroll bar widens the Emacs frame.
    This means that if Emacs isn't maximized, and the frame is against the screens right edge,
    then the scroll bar opens outside the screens right edge.

Changing the scroll speed based on the mouse position relative to the frame height also has issues.

If the window is split top/bottom, then:

  • the top window can't scroll at the slowest speed
  • and the bottom window can't scroll at the fastest speed

It might be possible to change it to check for window thirds instead, with window-top-line,
but the scroll speed might feel inconsistent since the window thirds would become quite small.

@syl20bnr
Copy link
Owner Author

Speed consistency is more important. It is not natural to have different speeds relative the file position.

I really like the scroll bar to appear when mouse scrolling, we can make a new dotspacemacs option to make it easy to disable for people who does not like it.

I'll revert the speed to 2.

Also on my system if I hold Control while scrolling it speeds up the scrolling. But I bet this is not like that on all systems.

@syl20bnr
Copy link
Owner Author

I reverted to 2 and removed the mouse-wheel-follow-mouse 't.

What about the dotspacemacs variable ? I feel that we could add that and call it a day.

@duianto
Copy link
Collaborator

duianto commented Mar 26, 2021

Also on my system if I hold Control while scrolling it speeds up the scrolling. But I bet this is not like that on all systems.

For me in Windows 10, control scrolling, resizes the Emacs frame.


There's a typo in the comment above the scroll amount, if we are going to use 2

  ;; scroll one line at a time (less "jumpy" than defaults)
  (setq mouse-wheel-scroll-amount '(2)

I've got a working dotspacemacs variable: dotspacemacs-scroll-bar-while-scrolling
It accepts: t, nil and a number (integer or float).

Should I force push to this branch?
I edited the first commit, to fix the typo.
And added a separate commit for the dot variable.

@duianto
Copy link
Collaborator

duianto commented Mar 26, 2021

I'll post the diff as well, if something needs to be changed, then it can be handled directly.

4 files changed, 20 insertions(+), 2 deletions(-)
CHANGELOG.develop                             |  1 +
core/core-dotspacemacs.el                     |  6 ++++++
core/templates/.spacemacs.template            |  4 ++++
layers/+spacemacs/spacemacs-defaults/funcs.el | 11 +++++++++--

modified   CHANGELOG.develop
@@ -499,6 +499,7 @@ In org-agenda-mode
   - New variable =dotspacemacs-read-process-output-max= to optimise lsp
     performance in emacs 27 (thanks to Maximilian Wolff)
   - New variable =dotspacemacs-show-trailing-whitespace= (thanks to duianto)
+  - New variable =dotspacemacs-scroll-bar-while-scrolling= (thanks to duianto)
 - Removed Variables:
   - Removed unused variable =dotspacemacs-verbose-loading= from
     =.spacemacs.template= (thanks to Ying Qu)
modified   core/core-dotspacemacs.el
@@ -500,6 +500,12 @@ screen."
   'boolean
   'spacemacs-dotspacemacs-init)
 
+(spacemacs|defc dotspacemacs-scroll-bar-while-scrolling t
+  "Show the scroll bar while scrolling. The auto hide time can be configured by
+setting this variable to a number."
+  '(choice boolean number)
+  'spacemacs-dotspacemacs-init)
+
 (spacemacs|defc dotspacemacs-line-numbers nil
   "Control line numbers activation.
 If set to `t' or `relative' line numbers are turned on in all `prog-mode' and
modified   core/templates/.spacemacs.template
@@ -371,6 +371,10 @@ It should only modify the values of Spacemacs settings."
    ;; when it reaches the top or bottom of the screen. (default t)
    dotspacemacs-smooth-scrolling t
 
+   ;; Show the scroll bar while scrolling. The auto hide time can be configured
+   ;; by setting this variable to a number. (default t)
+   dotspacemacs-scroll-bar-while-scrolling t
+
    ;; Control line numbers activation.
    ;; If set to `t', `relative' or `visual' then line numbers are enabled in all
    ;; `prog-mode' and `text-mode' derivatives. If set to `relative', line
modified   layers/+spacemacs/spacemacs-defaults/funcs.el
@@ -1437,6 +1437,7 @@ using a visual block/rectangle selection."
 (defun spacemacs//scroll-bar-hide ()
   " Hide the scroll bar."
   (scroll-bar-mode -1))
+
 (defun spacemacs//scroll-bar-show-delayed-hide (&rest _ignore)
   "Show the scroll bar for a couple of seconds, before hiding it.
 
@@ -1446,8 +1447,14 @@ This can be used to temporarily show the scroll bar when mouse wheel scrolling.
 The advice can be removed with:
 (advice-remove 'mwheel-scroll #'spacemacs//scroll-bar-show-delayed-hide)"
   (scroll-bar-mode 1)
-  (run-with-idle-timer 3 nil #'spacemacs//scroll-bar-hide))
-(when (fboundp 'scroll-bar-mode)
+  (run-with-idle-timer
+   (if (numberp dotspacemacs-scroll-bar-while-scrolling)
+       dotspacemacs-scroll-bar-while-scrolling
+     3)
+   nil
+   #'spacemacs//scroll-bar-hide))
+(when (and (fboundp 'scroll-bar-mode)
+           dotspacemacs-scroll-bar-while-scrolling)
   (advice-add 'mwheel-scroll :after #'spacemacs//scroll-bar-show-delayed-hide))
 
 ;; BEGIN linum mouse helpers

@syl20bnr
Copy link
Owner Author

Should I force push to this branch?

Sure. Thank you.

So on Windows 10 the frame is always resized, even maximized ?
Is it acceptable or the resize is very annoying ?

@duianto
Copy link
Collaborator

duianto commented Mar 27, 2021

So on Windows 10 the frame is always resized, even maximized ?
Is it acceptable or the resize is very annoying ?

In Spacemacs in Windows 10:

 <C-wheel-down>                                     ;; spacemacs/zoom-frm-out
 <C-wheel-up>                                       ;; spacemacs/zoom-frm-in

In both Spacemacs and emacs -q in Manjaro, and in emacs -q in Windows 10:

 <C-wheel-down>		  ;; mouse-wheel-text-scale
 <C-wheel-up>		  ;; mouse-wheel-text-scale

Spacemacs binds control and the scroll wheel here:

;; Font size, either with ctrl + mouse wheel
(global-set-key (kbd "<C-wheel-up>") 'spacemacs/zoom-frm-in)
(global-set-key (kbd "<C-wheel-down>") 'spacemacs/zoom-frm-out))))

In Windows 10 the frame gets smaller when zooming both in and out.

2021-03-27_10-46-04

Even when Spacemacs is maximized.

2021-03-27_10-53-02

In emacs -q in Windows 10 (the same thing is observed in Manjaro in both Spacemacs and emacs -q),
only the text in the scrolled window is resized.

2021-03-27_10-48-04

@duianto
Copy link
Collaborator

duianto commented Mar 27, 2021

The frame also shrinks in Manjaro when zooming the frame in the: SPC z f
Zoom Frame Transient State

This treads author is/was using linux, and reported the same behavior as you describe.
Mouse wheel scrolling with control held scrolls window, rather than zooming the frame #12293

I'm not sure why different commands are called in Spacemacs in linux when control scrolling.

Copy link
Collaborator

@smile13241324 smile13241324 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels much better now, will be cherry picked in a minute.

@smile13241324
Copy link
Collaborator

Thank you for contributing to spacemacs 💜, I have cherry picked your commits into develop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Smooth scrolling [Enhancement]
3 participants