diff options
| author | Po Lu | 2021-11-26 17:42:45 +0800 |
|---|---|---|
| committer | Po Lu | 2021-11-26 21:06:22 +0800 |
| commit | 5d6e1c749a669d33db2936b106ae41ce59473ea1 (patch) | |
| tree | abf24c466996e9927720b51d6b802bbffe5b14e1 | |
| parent | 673eadaeb55de71016fab371613d8e930f6d7c04 (diff) | |
| download | emacs-5d6e1c749a669d33db2936b106ae41ce59473ea1.tar.gz emacs-5d6e1c749a669d33db2936b106ae41ce59473ea1.zip | |
Move the precision pixel scrolling feature to pixel-scroll.el
* etc/NEWS: Update NEWS entry for 'pixel-scroll-precision-mode'
* lisp/better-pixel-scroll.el: Remove file.
* src/pixel-scroll.el (x-coalesce-scroll-events): New variable
declaration.
(pixel-scroll-precision-mode-map): New variable.
(pixel-scroll-precision-scroll-down):
(pixel-scroll-precision-scroll-up):
(pixel-scroll-precision): New functions.
(pixel-scroll-precision-mode): New minor mode.
| -rw-r--r-- | etc/NEWS | 10 | ||||
| -rw-r--r-- | lisp/better-pixel-scroll.el | 147 | ||||
| -rw-r--r-- | lisp/pixel-scroll.el | 121 |
3 files changed, 127 insertions, 151 deletions
| @@ -94,10 +94,12 @@ This controls the thickness of the external borders of the menu bars | |||
| 94 | and pop-up menus. | 94 | and pop-up menus. |
| 95 | 95 | ||
| 96 | --- | 96 | --- |
| 97 | ** New minor mode 'better-pixel-scroll-mode'. | 97 | ** New minor mode 'pixel-scroll-precision-mode'. |
| 98 | When enabled, using this mode with a capable scroll wheel will result | 98 | When enabled, you can scroll the display up or down by individual |
| 99 | in the display being scrolled precisely according to the turning of | 99 | pixels in a way that corresponds with the movement of your mouse |
| 100 | that wheel. | 100 | wheel, if supported by the mouse wheel. Unlike 'pixel-scroll-mode', |
| 101 | this mode scrolls the display pixel-by-pixel, as opposed to only | ||
| 102 | animating line-by-line scrolls. | ||
| 101 | 103 | ||
| 102 | ** Terminal Emacs | 104 | ** Terminal Emacs |
| 103 | 105 | ||
diff --git a/lisp/better-pixel-scroll.el b/lisp/better-pixel-scroll.el deleted file mode 100644 index c1469108e05..00000000000 --- a/lisp/better-pixel-scroll.el +++ /dev/null | |||
| @@ -1,147 +0,0 @@ | |||
| 1 | ;;; better-pixel-scroll.el --- Pixel scrolling support -*- lexical-binding:t -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2021 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | ;; it under the terms of the GNU General Public License as published by | ||
| 9 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 10 | ;; (at your option) any later version. | ||
| 11 | |||
| 12 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;; GNU General Public License for more details. | ||
| 16 | |||
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ;;; Commentary: | ||
| 21 | |||
| 22 | ;; This enables the use of smooth scroll events provided by XInput 2 | ||
| 23 | ;; or NS to scroll the display according to the user's precise turning | ||
| 24 | ;; of the mouse wheel. | ||
| 25 | |||
| 26 | ;;; Code: | ||
| 27 | |||
| 28 | (require 'mwheel) | ||
| 29 | (require 'subr-x) | ||
| 30 | |||
| 31 | (defvar x-coalesce-scroll-events) | ||
| 32 | |||
| 33 | (defvar better-pixel-scroll-mode-map | ||
| 34 | (let ((map (make-sparse-keymap))) | ||
| 35 | (define-key map [wheel-down] #'better-pixel-scroll) | ||
| 36 | (define-key map [wheel-up] #'better-pixel-scroll) | ||
| 37 | map) | ||
| 38 | "The key map used by `better-pixel-scroll-mode'.") | ||
| 39 | |||
| 40 | (defun better-pixel-scroll-scroll-down (delta) | ||
| 41 | "Scroll the current window down by DELTA pixels. | ||
| 42 | Note that this function doesn't work if DELTA is larger than | ||
| 43 | the height of the current window." | ||
| 44 | (when-let* ((posn (posn-at-point)) | ||
| 45 | (current-y (cdr (posn-x-y posn))) | ||
| 46 | (min-y (+ (window-tab-line-height) | ||
| 47 | (window-header-line-height))) | ||
| 48 | (cursor-height (line-pixel-height)) | ||
| 49 | (window-height (window-text-height nil t)) | ||
| 50 | (next-height (save-excursion | ||
| 51 | (vertical-motion 1) | ||
| 52 | (line-pixel-height)))) | ||
| 53 | (if (and (> delta 0) | ||
| 54 | (<= cursor-height window-height)) | ||
| 55 | (while (< (- current-y min-y) delta) | ||
| 56 | (vertical-motion 1) | ||
| 57 | (setq current-y (+ current-y | ||
| 58 | (line-pixel-height))) | ||
| 59 | (when (eobp) | ||
| 60 | (error "End of buffer"))) | ||
| 61 | (when (< (- (cdr (posn-object-width-height posn)) | ||
| 62 | (cdr (posn-object-x-y posn))) | ||
| 63 | (- window-height next-height)) | ||
| 64 | (vertical-motion 1) | ||
| 65 | (setq posn (posn-at-point) | ||
| 66 | current-y (cdr (posn-x-y posn))) | ||
| 67 | (while (< (- current-y min-y) delta) | ||
| 68 | (vertical-motion 1) | ||
| 69 | (setq current-y (+ current-y | ||
| 70 | (line-pixel-height))) | ||
| 71 | (when (eobp) | ||
| 72 | (error "End of buffer"))))) | ||
| 73 | (let* ((desired-pos (posn-at-x-y 0 (+ delta | ||
| 74 | (window-tab-line-height) | ||
| 75 | (window-header-line-height)))) | ||
| 76 | (desired-start (posn-point desired-pos)) | ||
| 77 | (desired-vscroll (cdr (posn-object-x-y desired-pos)))) | ||
| 78 | (unless (eq (window-start) desired-start) | ||
| 79 | (set-window-start nil desired-start t)) | ||
| 80 | (set-window-vscroll nil desired-vscroll t)))) | ||
| 81 | |||
| 82 | (defun better-pixel-scroll-scroll-up (delta) | ||
| 83 | "Scroll the current window up by DELTA pixels." | ||
| 84 | (when-let* ((max-y (- (window-text-height nil t) | ||
| 85 | (window-tab-line-height) | ||
| 86 | (window-header-line-height))) | ||
| 87 | (posn (posn-at-point)) | ||
| 88 | (current-y (+ (cdr (posn-x-y posn)) | ||
| 89 | (cdr (posn-object-width-height posn))))) | ||
| 90 | (while (< (- max-y current-y) delta) | ||
| 91 | (vertical-motion -1) | ||
| 92 | (setq current-y (- current-y (line-pixel-height))))) | ||
| 93 | (let ((current-vscroll (window-vscroll nil t))) | ||
| 94 | (setq delta (- delta current-vscroll)) | ||
| 95 | (set-window-vscroll nil 0 t)) | ||
| 96 | (while (> delta 0) | ||
| 97 | (set-window-start nil (save-excursion | ||
| 98 | (goto-char (window-start)) | ||
| 99 | (when (zerop (vertical-motion -1)) | ||
| 100 | (set-window-vscroll nil 0) | ||
| 101 | (signal 'beginning-of-buffer nil)) | ||
| 102 | (setq delta (- delta (line-pixel-height))) | ||
| 103 | (point)) | ||
| 104 | t)) | ||
| 105 | (when (< delta 0) | ||
| 106 | (when-let* ((desired-pos (posn-at-x-y 0 (+ (- delta) | ||
| 107 | (window-tab-line-height) | ||
| 108 | (window-header-line-height)))) | ||
| 109 | (desired-start (posn-point desired-pos)) | ||
| 110 | (desired-vscroll (cdr (posn-object-x-y desired-pos)))) | ||
| 111 | (unless (eq (window-start) desired-start) | ||
| 112 | (set-window-start nil desired-start t)) | ||
| 113 | (set-window-vscroll nil desired-vscroll t)))) | ||
| 114 | |||
| 115 | (defun better-pixel-scroll (event &optional arg) | ||
| 116 | "Scroll the display according to EVENT. | ||
| 117 | Take into account any pixel deltas in EVENT to scroll the display | ||
| 118 | according to the user's turning the mouse wheel. If EVENT does | ||
| 119 | not have precise scrolling deltas, call `mwheel-scroll' instead. | ||
| 120 | ARG is passed to `mwheel-scroll', should that be called." | ||
| 121 | (interactive (list last-input-event current-prefix-arg)) | ||
| 122 | (let ((window (mwheel-event-window event))) | ||
| 123 | (if (and (nth 4 event) | ||
| 124 | (zerop (window-hscroll window))) | ||
| 125 | (let ((delta (round (cdr (nth 4 event))))) | ||
| 126 | (if (> (abs delta) (window-text-height window t)) | ||
| 127 | (mwheel-scroll event arg) | ||
| 128 | (with-selected-window window | ||
| 129 | (if (< delta 0) | ||
| 130 | (better-pixel-scroll-scroll-down (- delta)) | ||
| 131 | (better-pixel-scroll-scroll-up delta))))) | ||
| 132 | (mwheel-scroll event arg)))) | ||
| 133 | |||
| 134 | ;;;###autoload | ||
| 135 | (define-minor-mode better-pixel-scroll-mode | ||
| 136 | "Toggle pixel scrolling. | ||
| 137 | When enabled, this minor mode allows to scroll the display | ||
| 138 | precisely, according to the turning of the mouse wheel." | ||
| 139 | :global t | ||
| 140 | :group 'mouse | ||
| 141 | :keymap better-pixel-scroll-mode-map | ||
| 142 | (setq x-coalesce-scroll-events | ||
| 143 | (not better-pixel-scroll-mode))) | ||
| 144 | |||
| 145 | (provide 'better-pixel-scroll) | ||
| 146 | |||
| 147 | ;;; better-pixel-scroll.el ends here. | ||
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el index 249484cf581..f6d1d0ff8ca 100644 --- a/lisp/pixel-scroll.el +++ b/lisp/pixel-scroll.el | |||
| @@ -67,6 +67,7 @@ | |||
| 67 | ;;; Code: | 67 | ;;; Code: |
| 68 | 68 | ||
| 69 | (require 'mwheel) | 69 | (require 'mwheel) |
| 70 | (require 'subr-x) | ||
| 70 | 71 | ||
| 71 | (defvar pixel-wait 0 | 72 | (defvar pixel-wait 0 |
| 72 | "Idle time on each step of pixel scroll specified in second. | 73 | "Idle time on each step of pixel scroll specified in second. |
| @@ -90,6 +91,15 @@ is always with pixel resolution.") | |||
| 90 | (defvar pixel-last-scroll-time 0 | 91 | (defvar pixel-last-scroll-time 0 |
| 91 | "Time when the last scrolling was made, in second since the epoch.") | 92 | "Time when the last scrolling was made, in second since the epoch.") |
| 92 | 93 | ||
| 94 | (defvar x-coalesce-scroll-events) | ||
| 95 | |||
| 96 | (defvar pixel-scroll-precision-mode-map | ||
| 97 | (let ((map (make-sparse-keymap))) | ||
| 98 | (define-key map [wheel-down] #'pixel-scroll-precision) | ||
| 99 | (define-key map [wheel-up] #'pixel-scroll-precision) | ||
| 100 | map) | ||
| 101 | "The key map used by `pixel-scroll-precision-mode'.") | ||
| 102 | |||
| 93 | (defun pixel-scroll-in-rush-p () | 103 | (defun pixel-scroll-in-rush-p () |
| 94 | "Return non-nil if next scroll should be non-smooth. | 104 | "Return non-nil if next scroll should be non-smooth. |
| 95 | When scrolling request is delivered soon after the previous one, | 105 | When scrolling request is delivered soon after the previous one, |
| @@ -354,5 +364,116 @@ Otherwise, redisplay will reset the window's vscroll." | |||
| 354 | (set-window-start nil (pixel-point-at-unseen-line) t) | 364 | (set-window-start nil (pixel-point-at-unseen-line) t) |
| 355 | (set-window-vscroll nil vscroll t)) | 365 | (set-window-vscroll nil vscroll t)) |
| 356 | 366 | ||
| 367 | ;; FIXME: This doesn't work when DELTA is larger than the height | ||
| 368 | ;; of the current window, and someone should probably fix that | ||
| 369 | ;; at some point. | ||
| 370 | (defun pixel-scroll-precision-scroll-down (delta) | ||
| 371 | "Scroll the current window down by DELTA pixels. | ||
| 372 | Note that this function doesn't work if DELTA is larger than | ||
| 373 | the height of the current window." | ||
| 374 | (when-let* ((posn (posn-at-point)) | ||
| 375 | (current-y (cdr (posn-x-y posn))) | ||
| 376 | (min-y (+ (frame-char-height) | ||
| 377 | (window-tab-line-height) | ||
| 378 | (window-header-line-height))) | ||
| 379 | (cursor-height (line-pixel-height)) | ||
| 380 | (window-height (window-text-height nil t)) | ||
| 381 | (next-height (save-excursion | ||
| 382 | (vertical-motion 1) | ||
| 383 | (line-pixel-height)))) | ||
| 384 | (if (and (> delta 0) | ||
| 385 | (<= cursor-height window-height)) | ||
| 386 | (while (< (- current-y min-y) delta) | ||
| 387 | (vertical-motion 1) | ||
| 388 | (setq current-y (+ current-y | ||
| 389 | (line-pixel-height))) | ||
| 390 | (when (eobp) | ||
| 391 | (signal 'end-of-buffer nil))) | ||
| 392 | (when (< (- (cdr (posn-object-width-height posn)) | ||
| 393 | (cdr (posn-object-x-y posn))) | ||
| 394 | (- window-height next-height)) | ||
| 395 | (vertical-motion 1) | ||
| 396 | (setq posn (posn-at-point) | ||
| 397 | current-y (cdr (posn-x-y posn))) | ||
| 398 | (while (< (- current-y min-y) delta) | ||
| 399 | (vertical-motion 1) | ||
| 400 | (setq current-y (+ current-y | ||
| 401 | (line-pixel-height))) | ||
| 402 | (when (eobp) | ||
| 403 | (signal 'end-of-buffer nil))))) | ||
| 404 | (let* ((desired-pos (posn-at-x-y 0 (+ delta | ||
| 405 | (window-tab-line-height) | ||
| 406 | (window-header-line-height)))) | ||
| 407 | (desired-start (posn-point desired-pos)) | ||
| 408 | (desired-vscroll (cdr (posn-object-x-y desired-pos)))) | ||
| 409 | (unless (eq (window-start) desired-start) | ||
| 410 | (set-window-start nil desired-start t)) | ||
| 411 | (set-window-vscroll nil desired-vscroll t)))) | ||
| 412 | |||
| 413 | (defun pixel-scroll-precision-scroll-up (delta) | ||
| 414 | "Scroll the current window up by DELTA pixels." | ||
| 415 | (when-let* ((max-y (- (window-text-height nil t) | ||
| 416 | (frame-char-height) | ||
| 417 | (window-tab-line-height) | ||
| 418 | (window-header-line-height))) | ||
| 419 | (posn (posn-at-point)) | ||
| 420 | (current-y (+ (cdr (posn-x-y posn)) | ||
| 421 | (line-pixel-height)))) | ||
| 422 | (while (< (- max-y current-y) delta) | ||
| 423 | (vertical-motion -1) | ||
| 424 | (setq current-y (- current-y (line-pixel-height))))) | ||
| 425 | (let ((current-vscroll (window-vscroll nil t))) | ||
| 426 | (setq delta (- delta current-vscroll)) | ||
| 427 | (set-window-vscroll nil 0 t)) | ||
| 428 | (while (> delta 0) | ||
| 429 | (set-window-start nil (save-excursion | ||
| 430 | (goto-char (window-start)) | ||
| 431 | (when (zerop (vertical-motion -1)) | ||
| 432 | (set-window-vscroll nil 0) | ||
| 433 | (signal 'beginning-of-buffer nil)) | ||
| 434 | (setq delta (- delta (line-pixel-height))) | ||
| 435 | (point)) | ||
| 436 | t)) | ||
| 437 | (when (< delta 0) | ||
| 438 | (when-let* ((desired-pos (posn-at-x-y 0 (+ (- delta) | ||
| 439 | (window-tab-line-height) | ||
| 440 | (window-header-line-height)))) | ||
| 441 | (desired-start (posn-point desired-pos)) | ||
| 442 | (desired-vscroll (cdr (posn-object-x-y desired-pos)))) | ||
| 443 | (unless (eq (window-start) desired-start) | ||
| 444 | (set-window-start nil desired-start t)) | ||
| 445 | (set-window-vscroll nil desired-vscroll t)))) | ||
| 446 | |||
| 447 | ;; FIXME: This doesn't work when there's an image above the current | ||
| 448 | ;; line that is taller than the window. | ||
| 449 | (defun pixel-scroll-precision (event) | ||
| 450 | "Scroll the display vertically by pixels according to EVENT. | ||
| 451 | Move the display up or down by the pixel deltas in EVENT to | ||
| 452 | scroll the display according to the user's turning the mouse | ||
| 453 | wheel." | ||
| 454 | (interactive "e") | ||
| 455 | (let ((window (mwheel-event-window event))) | ||
| 456 | (if (and (nth 4 event) | ||
| 457 | (zerop (window-hscroll window))) | ||
| 458 | (let ((delta (round (cdr (nth 4 event))))) | ||
| 459 | (if (> (abs delta) (window-text-height window t)) | ||
| 460 | (mwheel-scroll event nil) | ||
| 461 | (with-selected-window window | ||
| 462 | (if (< delta 0) | ||
| 463 | (pixel-scroll-precision-scroll-down (- delta)) | ||
| 464 | (pixel-scroll-precision-scroll-up delta))))) | ||
| 465 | (mwheel-scroll event nil)))) | ||
| 466 | |||
| 467 | ;;;###autoload | ||
| 468 | (define-minor-mode pixel-scroll-precision-mode | ||
| 469 | "Toggle pixel scrolling. | ||
| 470 | When enabled, this minor mode allows to scroll the display | ||
| 471 | precisely, according to the turning of the mouse wheel." | ||
| 472 | :global t | ||
| 473 | :group 'mouse | ||
| 474 | :keymap pixel-scroll-precision-mode-map | ||
| 475 | (setq x-coalesce-scroll-events | ||
| 476 | (not pixel-scroll-precision-mode))) | ||
| 477 | |||
| 357 | (provide 'pixel-scroll) | 478 | (provide 'pixel-scroll) |
| 358 | ;;; pixel-scroll.el ends here | 479 | ;;; pixel-scroll.el ends here |