diff options
author | Po Lu <luangruo@yahoo.com> | 2021-12-02 11:01:59 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2021-12-02 11:01:59 +0800 |
commit | 603bdc8d38ce4325380d29423939e5287e8aac17 (patch) | |
tree | 15c661d1ea75de9fc0dde11f532a2ae22052ca73 /lisp/pixel-scroll.el | |
parent | 5001f4f91b9a959ddc345de36153689174df67a9 (diff) | |
download | emacs-603bdc8d38ce4325380d29423939e5287e8aac17.tar.gz emacs-603bdc8d38ce4325380d29423939e5287e8aac17.tar.bz2 emacs-603bdc8d38ce4325380d29423939e5287e8aac17.zip |
Add some primitive momentum-based precision scrolling
The algorithm used to scroll the display kinetically is very
simple and needs improvement. Someone should work on that
eventually.
* lisp/pixel-scroll.el (pixel-scroll-precision-use-momentum):
New user option.
(pixel-scroll-precision-mode-map): Add
`pixel-scroll-start-momentum'.
(pixel-scroll-kinetic-state):
(pixel-scroll-accumulate-velocity):
(pixel-scroll-calculate-velocity): New functions.
(pixel-scroll-start-momentum): New command.
* src/xterm.c (handle_one_xevent): Fix touch-end event
generation.
Diffstat (limited to 'lisp/pixel-scroll.el')
-rw-r--r-- | lisp/pixel-scroll.el | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el index 2d6531a2d17..092d7215d31 100644 --- a/lisp/pixel-scroll.el +++ b/lisp/pixel-scroll.el @@ -68,6 +68,7 @@ (require 'mwheel) (require 'subr-x) +(require 'ring) (defvar pixel-wait 0 "Idle time on each step of pixel scroll specified in second. @@ -97,9 +98,17 @@ is always with pixel resolution.") (let ((map (make-sparse-keymap))) (define-key map [wheel-down] #'pixel-scroll-precision) (define-key map [wheel-up] #'pixel-scroll-precision) + (define-key map [touch-end] #'pixel-scroll-start-momentum) map) "The key map used by `pixel-scroll-precision-mode'.") +(defcustom pixel-scroll-precision-use-momentum nil + "If non-nil, continue to scroll the display after wheel movement stops. +This is only effective if supported by your mouse or touchpad." + :group 'mouse + :type 'boolean + :version "29.1") + (defun pixel-scroll-in-rush-p () "Return non-nil if next scroll should be non-smooth. When scrolling request is delivered soon after the previous one, @@ -475,9 +484,11 @@ wheel." (mwheel-scroll event nil) (with-selected-window window (condition-case nil - (if (< delta 0) - (pixel-scroll-precision-scroll-down (- delta)) - (pixel-scroll-precision-scroll-up delta)) + (progn + (if (< delta 0) + (pixel-scroll-precision-scroll-down (- delta)) + (pixel-scroll-precision-scroll-up delta)) + (pixel-scroll-accumulate-velocity delta)) ;; Do not ding at buffer limits. Show a message instead. (beginning-of-buffer (message (error-message-string '(beginning-of-buffer)))) @@ -485,6 +496,61 @@ wheel." (message (error-message-string '(end-of-buffer))))))))) (mwheel-scroll event nil)))) +(defun pixel-scroll-kinetic-state () + "Return the kinetic scroll state of the current window. +It is a vector of the form [ VELOCITY TIME ]." + (or (window-parameter nil 'kinetic-state) + (set-window-parameter nil 'kinetic-state + (vector (make-ring 4) nil)))) + +(defun pixel-scroll-accumulate-velocity (delta) + "Accumulate DELTA into the current window's kinetic scroll state." + (let* ((state (pixel-scroll-kinetic-state)) + (time (aref state 1))) + (when (and time (> (- (float-time) time) 0.5)) + (aset state 0 (make-ring 45))) + (ring-insert (aref state 0) + (cons (aset state 1 (float-time)) + delta)))) + +(defun pixel-scroll-calculate-velocity (state) + "Calculate velocity from the kinetic state vector STATE." + (let* ((ring (aref state 0)) + (elts (ring-elements ring)) + (total 0)) + (dolist (tem elts) + (setq total (+ total (cdr tem)))) + (/ total (* (- (caar elts) + (caar (last elts))) + 100)))) + +(defun pixel-scroll-start-momentum (event) + "Start kinetic scrolling for the touch event EVENT." + (interactive "e") + (when pixel-scroll-precision-use-momentum + (let ((window (mwheel-event-window event)) + (state nil)) + (with-selected-window window + (setq state (pixel-scroll-kinetic-state)) + (when (aref state 1) + (unwind-protect (progn + (aset state 0 + (pixel-scroll-calculate-velocity state)) + (let ((velocity (aref state 0))) + (if (> velocity 0) + (while (> velocity 0) + (pixel-scroll-precision-scroll-up 1) + (setq velocity (1- velocity)) + (sit-for 0.1) + (redisplay t)) + (while (< velocity 0) + (pixel-scroll-precision-scroll-down 1) + (setq velocity (1+ velocity)) + (sit-for 0.1) + (redisplay t))))) + (aset state 0 (make-ring 45)) + (aset state 1 nil))))))) + ;;;###autoload (define-minor-mode pixel-scroll-precision-mode "Toggle pixel scrolling. |