diff options
| author | Martin Rudalics | 2025-09-27 10:07:14 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2025-09-27 10:07:14 +0200 |
| commit | b60e0f42941cf7db2dd396029437a1cbeec74d69 (patch) | |
| tree | 646125263fe27c3a112824674b420ea43f1a65ac | |
| parent | 6eaa1d279bab8b8c8bf0f16096dc22954a16a7fb (diff) | |
| download | emacs-b60e0f42941cf7db2dd396029437a1cbeec74d69.tar.gz emacs-b60e0f42941cf7db2dd396029437a1cbeec74d69.zip | |
Restore mouse line dragging in character increments (Bug#79351)
* lisp/mouse.el (mouse-drag-line): Restore dragging in character
increments and make it the default (Bug#79351).
* etc/NEWS: Mention restored behavior of mouse line dragging.
| -rw-r--r-- | etc/NEWS | 10 | ||||
| -rw-r--r-- | lisp/mouse.el | 218 |
2 files changed, 150 insertions, 78 deletions
| @@ -288,6 +288,16 @@ to extend the boundaries of the active region by dragging the mouse pointer. | |||
| 288 | The menu item enables sending current file(s) or region text to external | 288 | The menu item enables sending current file(s) or region text to external |
| 289 | (non-Emacs) applications or services. See send-to.el for customisations. | 289 | (non-Emacs) applications or services. See send-to.el for customisations. |
| 290 | 290 | ||
| 291 | --- | ||
| 292 | *** The mouse now drags lines in character increments again. | ||
| 293 | Dragging a horizontal or vertical line like the mode line or the lines | ||
| 294 | dividing side-by-side windows now by default happens in increments of | ||
| 295 | the corresponding frame's character size again. This is the behavior | ||
| 296 | described in the manual and was the default behavior before | ||
| 297 | 'window-resize-pixelwise' was added for Emacs 24.1. To drag in pixel | ||
| 298 | increments as with Emcas 24 through Emacs 30 you now have to set | ||
| 299 | 'window-resize-pixelwise' to t. | ||
| 300 | |||
| 291 | ** Windows | 301 | ** Windows |
| 292 | 302 | ||
| 293 | +++ | 303 | +++ |
diff --git a/lisp/mouse.el b/lisp/mouse.el index b8db801b422..f75800763e6 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el | |||
| @@ -854,40 +854,100 @@ This command must be bound to a mouse click." | |||
| 854 | (min (max new-width first-col) last-col))))))) | 854 | (min (max new-width first-col) last-col))))))) |
| 855 | 855 | ||
| 856 | (defun mouse-drag-line (start-event line) | 856 | (defun mouse-drag-line (start-event line) |
| 857 | "Drag a mode line, header line, or vertical line with the mouse. | 857 | "Drag a mode, header, tab or vertical line with the mouse. |
| 858 | START-EVENT is the starting mouse event of the drag action. LINE | 858 | START-EVENT is the starting mouse event of the drag action. LINE |
| 859 | must be one of the symbols `header', `mode', or `vertical'." | 859 | must be one of the symbols `header', `mode', `tab' or `vertical'." |
| 860 | ;; Give temporary modes such as isearch a chance to turn off. | 860 | ;; Give temporary modes such as isearch a chance to turn off. |
| 861 | (run-hooks 'mouse-leave-buffer-hook) | 861 | (run-hooks 'mouse-leave-buffer-hook) |
| 862 | ;; The earlier version of this was based on using the position of the | ||
| 863 | ;; start event for each sampled mouse movement. That approach had the | ||
| 864 | ;; disadvantage that when, for example, dragging the mode line down, | ||
| 865 | ;; the 'posn-window' of that event was usually the window below the | ||
| 866 | ;; mode line and its coordinates were relative to that window. So we | ||
| 867 | ;; had to add position and height of the window above the mode line in | ||
| 868 | ;; order to get a meaningful value for comparing the old and current | ||
| 869 | ;; mouse position. However, when a user changed the direction during | ||
| 870 | ;; dragging, the mouse moved into the window above the mode line and | ||
| 871 | ;; the relative position changed to one of that window too. Since | ||
| 872 | ;; keeping track of these changes was tricky, we now simply use | ||
| 873 | ;; absolute mouse positions and do not care about the window at the | ||
| 874 | ;; mouse position any more. | ||
| 862 | (let* ((echo-keystrokes 0) | 875 | (let* ((echo-keystrokes 0) |
| 863 | (start (event-start start-event)) | 876 | (start (event-start start-event)) |
| 864 | (window (posn-window start)) | 877 | (window (posn-window start)) |
| 865 | (frame (window-frame window)) | 878 | (frame (window-frame window)) |
| 866 | ;; `position' records the x- or y-coordinate of the last | 879 | ;; tty is needed because `mouse-absolute-pixel-position' does |
| 867 | ;; sampled position. | 880 | ;; not return a meaningful value on ttys so there we have to |
| 881 | ;; use `mouse-position-in-root-frame'. | ||
| 882 | (tty (tty-type frame)) | ||
| 883 | ;; 'charwise' means to drag by character sizes on graphical | ||
| 884 | ;; displays. | ||
| 885 | (charwise (not (or window-resize-pixelwise tty))) | ||
| 886 | ;; The initial absolute position of the mouse. We | ||
| 887 | ;; intentionally do not use the value of 'posn-x-y' of | ||
| 888 | ;; START-EVENT here because that would give us coordinates for | ||
| 889 | ;; 'posn-window' of that event and we don't want that (see the | ||
| 890 | ;; comment above). | ||
| 891 | (position-x-y (if tty | ||
| 892 | (mouse-position-in-root-frame) | ||
| 893 | (mouse-absolute-pixel-position))) | ||
| 894 | ;; 'position' records the x- (for vertical dragging) or y- (for | ||
| 895 | ;; mode, header and tab line dragging) coordinate of the | ||
| 896 | ;; current mouse position | ||
| 868 | (position (if (eq line 'vertical) | 897 | (position (if (eq line 'vertical) |
| 869 | (+ (window-pixel-left window) | 898 | (car position-x-y) |
| 870 | (car (posn-x-y start))) | 899 | (cdr position-x-y))) |
| 871 | (+ (window-pixel-top window) | 900 | ;; 'last-position' records the the x- or y-coordinate of the |
| 872 | (cdr (posn-x-y start))))) | 901 | ;; previously sampled position. The difference of 'position' |
| 873 | ;; `last-position' records the x- or y-coordinate of the | 902 | ;; and 'last-position' determines the size change of WINDOW. |
| 874 | ;; previously sampled position. The difference of `position' | ||
| 875 | ;; and `last-position' determines the size change of WINDOW. | ||
| 876 | (last-position position) | 903 | (last-position position) |
| 877 | posn-window growth dragged) | 904 | ;; The next two bindings are used for characterwise dragging |
| 878 | ;; Decide on whether we are allowed to track at all and whose | 905 | ;; only. 'residue' is the remainder of the difference between |
| 879 | ;; window's edge we drag. | 906 | ;; 'position' and 'last-position' divided by the frame's |
| 907 | ;; character size and will be considered in the next difference | ||
| 908 | ;; calculation. | ||
| 909 | (residue 0) | ||
| 910 | ;; 'forward' indicates the current dragging direction and is | ||
| 911 | ;; non-nil when dragging to the right or down. Its purpose is | ||
| 912 | ;; to detect changes in the dragging direction in order to keep | ||
| 913 | ;; the mouse cursor nearer to the dragged line. | ||
| 914 | (forward t) | ||
| 915 | ;; 'char-size' is the frame's character width) for vertical | ||
| 916 | ;; dragging) or character height (for mode, header, tab line | ||
| 917 | ;; dragging). | ||
| 918 | char-size | ||
| 919 | ;; 'growth' is the position change of the mouse in pixels if | ||
| 920 | ;; 'charwise' is nil, in characters if 'charwise' is non-nil. | ||
| 921 | growth | ||
| 922 | ;; `dragged' is initially nil and sticks to non-nil after the | ||
| 923 | ;; first time growth has become non-nil. Its purpose is to | ||
| 924 | ;; give characterwise dragging a head start to avoid that the | ||
| 925 | ;; mouse cursor moves to far away from the line to drag. | ||
| 926 | dragged) | ||
| 927 | ;; Set up the window whose edge to drag. | ||
| 880 | (cond | 928 | (cond |
| 881 | ((memq line '(header tab)) | 929 | ((memq line '(header tab)) |
| 882 | ;; Drag bottom edge of window above the header line. | 930 | ;; LINE is a header or tab line. Drag the bottom edge of the |
| 883 | (setq window (window-in-direction 'above window t))) | 931 | ;; window above it. |
| 884 | ((eq line 'mode)) | 932 | (setq window (window-in-direction 'above window t)) |
| 933 | (when charwise | ||
| 934 | (setq char-size (frame-char-height frame)))) | ||
| 935 | ((eq line 'mode) | ||
| 936 | ;; LINE is a mode line or a bottom window divider. Drag the bottom edge | ||
| 937 | ;; of its window. | ||
| 938 | (when charwise | ||
| 939 | (setq char-size (frame-char-height frame)))) | ||
| 885 | ((eq line 'vertical) | 940 | ((eq line 'vertical) |
| 941 | ;; LINE is a window divider on the right. Drag the right edge of | ||
| 942 | ;; the window on its left. | ||
| 886 | (let ((divider-width (frame-right-divider-width frame))) | 943 | (let ((divider-width (frame-right-divider-width frame))) |
| 887 | (when (and (or (not (numberp divider-width)) | 944 | (when (and (or (not (numberp divider-width)) |
| 888 | (zerop divider-width)) | 945 | (zerop divider-width)) |
| 889 | (eq (frame-parameter frame 'vertical-scroll-bars) 'left)) | 946 | (eq (frame-parameter frame 'vertical-scroll-bars) 'left)) |
| 890 | (setq window (window-in-direction 'left window t)))))) | 947 | (setq window (window-in-direction 'left window t)))) |
| 948 | (when charwise | ||
| 949 | (setq char-size (frame-char-width frame))))) | ||
| 950 | |||
| 891 | (let* ((exitfun nil) | 951 | (let* ((exitfun nil) |
| 892 | (move | 952 | (move |
| 893 | (lambda (event) (interactive "e") | 953 | (lambda (event) (interactive "e") |
| @@ -895,74 +955,76 @@ must be one of the symbols `header', `mode', or `vertical'." | |||
| 895 | ((not (consp event)) | 955 | ((not (consp event)) |
| 896 | nil) | 956 | nil) |
| 897 | ((eq line 'vertical) | 957 | ((eq line 'vertical) |
| 898 | ;; Drag right edge of `window'. | 958 | ;; Drag right edge of 'window'. |
| 899 | (setq start (event-start event)) | 959 | (setq position (if tty |
| 900 | (setq position (car (posn-x-y start))) | 960 | (car (mouse-position-in-root-frame)) |
| 901 | ;; Set `posn-window' to the window where `event' was recorded. | 961 | (car (mouse-absolute-pixel-position)))) |
| 902 | ;; This can be `window' or the window on the left or right of | 962 | (unless (zerop (setq growth (- position last-position))) |
| 903 | ;; `window'. | 963 | ;; When we drag characterwise and we either drag for |
| 904 | (when (window-live-p (setq posn-window (posn-window start))) | 964 | ;; the first time or the dragging direction changes, |
| 905 | ;; Add left edge of `posn-window' to `position'. | 965 | ;; try to keep in synch cursor and dragged line. |
| 906 | (setq position (+ (window-pixel-left posn-window) position)) | 966 | (when (and charwise |
| 907 | (unless (posn-area start) | 967 | (or (not dragged) |
| 908 | ;; Add width of objects on the left of the text area to | 968 | (if forward |
| 909 | ;; `position'. | 969 | (< growth 0) |
| 910 | (when (eq (window-current-scroll-bars posn-window) 'left) | 970 | (> growth 0)))) |
| 911 | (setq position (+ (window-scroll-bar-width posn-window) | 971 | (setq forward (> growth 0)) |
| 912 | position))) | 972 | (setq growth |
| 913 | (setq position (+ (car (window-fringes posn-window)) | 973 | (if (> growth 0) |
| 914 | (or (car (window-margins posn-window)) 0) | 974 | (+ growth (/ char-size 2)) |
| 915 | position)))) | 975 | (- growth (/ char-size 2))))) |
| 916 | ;; When the cursor overshoots after shrinking a window to its | 976 | |
| 917 | ;; minimum size and the dragging direction changes, have the | ||
| 918 | ;; cursor first catch up with the window edge. | ||
| 919 | (unless (or (zerop (setq growth (- position last-position))) | ||
| 920 | (and (> growth 0) | ||
| 921 | (< position (+ (window-pixel-left window) | ||
| 922 | (window-pixel-width window)))) | ||
| 923 | (and (< growth 0) | ||
| 924 | (> position (+ (window-pixel-left window) | ||
| 925 | (window-pixel-width window))))) | ||
| 926 | (setq dragged t) | 977 | (setq dragged t) |
| 927 | (adjust-window-trailing-edge window growth t t)) | 978 | (when charwise |
| 928 | (setq last-position position)) | 979 | (setq residue (% growth char-size)) |
| 980 | (setq growth (/ growth char-size))) | ||
| 981 | (unless (zerop growth) | ||
| 982 | (adjust-window-trailing-edge window growth t (not charwise))) | ||
| 983 | (setq last-position (- position residue)) | ||
| 984 | |||
| 985 | ;; ;; Debugging code. | ||
| 986 | ;; (message "last %s pos %s growth %s residue %s char-size %s" | ||
| 987 | ;; last-position position growth residue char-size) | ||
| 988 | |||
| 989 | )) | ||
| 929 | (t | 990 | (t |
| 930 | ;; Drag bottom edge of `window'. | 991 | ;; Drag bottom edge of 'window'. |
| 931 | (setq start (event-start event)) | 992 | (setq position (cdr (if tty |
| 932 | ;; Set `posn-window' to the window where `event' was recorded. | 993 | (mouse-position-in-root-frame) |
| 933 | ;; This can be either `window' or the window above or below of | 994 | (mouse-absolute-pixel-position)))) |
| 934 | ;; `window'. | 995 | (unless (zerop (setq growth (- position last-position))) |
| 935 | (setq posn-window (posn-window start)) | 996 | ;; When we drag characterwise and we either drag for |
| 936 | (setq position (cdr (posn-x-y start))) | 997 | ;; the first time or the dragging direction changes, |
| 937 | (when (window-live-p posn-window) | 998 | ;; try to keep in synch cursor and dragged line. |
| 938 | ;; Add top edge of `posn-window' to `position'. | 999 | (when (and charwise |
| 939 | (setq position (+ (window-pixel-top posn-window) position)) | 1000 | (or (not dragged) |
| 940 | ;; If necessary, add height of header and tab line to | 1001 | (if forward |
| 941 | ;; `position'. | 1002 | (< growth 0) |
| 942 | (when (memq (posn-area start) | 1003 | (> growth 0)))) |
| 943 | '(nil left-fringe right-fringe left-margin right-margin)) | 1004 | (setq forward (> growth 0)) |
| 944 | (setq position (+ (window-header-line-height posn-window) | 1005 | (setq growth |
| 945 | (window-tab-line-height posn-window) | 1006 | (if (> growth 0) |
| 946 | position)))) | 1007 | (+ growth (/ char-size 2)) |
| 947 | ;; When the cursor overshoots after shrinking a window to its | 1008 | (- growth (/ char-size 2))))) |
| 948 | ;; minimum size and the dragging direction changes, have the | 1009 | |
| 949 | ;; cursor first catch up with the window edge. | ||
| 950 | (unless (or (zerop (setq growth (- position last-position))) | ||
| 951 | (and (> growth 0) | ||
| 952 | (< position (+ (window-pixel-top window) | ||
| 953 | (window-pixel-height window)))) | ||
| 954 | (and (< growth 0) | ||
| 955 | (> position (+ (window-pixel-top window) | ||
| 956 | (window-pixel-height window))))) | ||
| 957 | (setq dragged t) | 1010 | (setq dragged t) |
| 958 | (adjust-window-trailing-edge window growth nil t)) | 1011 | (when charwise |
| 959 | (setq last-position position))))) | 1012 | (setq residue (% growth char-size)) |
| 1013 | (setq growth (/ growth char-size))) | ||
| 1014 | (unless (zerop growth) | ||
| 1015 | (adjust-window-trailing-edge window growth nil (not charwise))) | ||
| 1016 | (setq last-position (- position residue)) | ||
| 1017 | |||
| 1018 | ;; ;; Debugging code. | ||
| 1019 | ;; (message "last %s pos %s growth %s residue %s char-size %s" | ||
| 1020 | ;; last-position position growth residue char-size) | ||
| 1021 | |||
| 1022 | ))))) | ||
| 960 | (old-track-mouse track-mouse)) | 1023 | (old-track-mouse track-mouse)) |
| 961 | ;; Start tracking. The special value 'dragging' signals the | 1024 | ;; Start tracking. The special value 'dragging' signals the |
| 962 | ;; display engine to freeze the mouse pointer shape for as long | 1025 | ;; display engine to freeze the mouse pointer shape for as long |
| 963 | ;; as we drag. | 1026 | ;; as we drag. |
| 964 | (setq track-mouse 'dragging) | 1027 | (setq track-mouse 'dragging) |
| 965 | ;; Loop reading events and sampling the position of the mouse. | ||
| 966 | (setq exitfun | 1028 | (setq exitfun |
| 967 | (set-transient-map | 1029 | (set-transient-map |
| 968 | (let ((map (make-sparse-keymap))) | 1030 | (let ((map (make-sparse-keymap))) |