aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Rudalics2025-09-27 10:07:14 +0200
committerMartin Rudalics2025-09-27 10:07:14 +0200
commitb60e0f42941cf7db2dd396029437a1cbeec74d69 (patch)
tree646125263fe27c3a112824674b420ea43f1a65ac
parent6eaa1d279bab8b8c8bf0f16096dc22954a16a7fb (diff)
downloademacs-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/NEWS10
-rw-r--r--lisp/mouse.el218
2 files changed, 150 insertions, 78 deletions
diff --git a/etc/NEWS b/etc/NEWS
index a6f897c602f..a402811f473 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -288,6 +288,16 @@ to extend the boundaries of the active region by dragging the mouse pointer.
288The menu item enables sending current file(s) or region text to external 288The 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.
293Dragging a horizontal or vertical line like the mode line or the lines
294dividing side-by-side windows now by default happens in increments of
295the corresponding frame's character size again. This is the behavior
296described in the manual and was the default behavior before
297'window-resize-pixelwise' was added for Emacs 24.1. To drag in pixel
298increments 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.
858START-EVENT is the starting mouse event of the drag action. LINE 858START-EVENT is the starting mouse event of the drag action. LINE
859must be one of the symbols `header', `mode', or `vertical'." 859must 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)))