comparison lisp/mouse.el @ 109112:a46a2b77a8b1

Simplify mouse-dragging implementation. Now that DEL deletes active regions, we can handle it by using the ordinary region instead of a separate overlay. * mouse.el (mouse-drag-overlay): Variable deleted. (mouse-move-drag-overlay, mouse-show-mark): Functions deleted. (mouse--remap-link-click-p): New function. (mouse-drag-track): Handle dragging by using temporary Transient Mark mode, instead of a special overlay. (mouse-kill-ring-save, mouse-save-then-kill): Don't call mouse-show-mark. * mouse-sel.el (mouse-sel-selection-alist): mouse-drag-overlay deleted.
author Chong Yidong <cyd@stupidchicken.com>
date Fri, 02 Jul 2010 23:07:48 -0400
parents d8144fe7f3f8
children 6b22e0739484
comparison
equal deleted inserted replaced
109111:52b76722152a 109112:a46a2b77a8b1
770 (goto-char opoint)) 770 (goto-char opoint))
771 (sit-for mouse-scroll-delay))))) 771 (sit-for mouse-scroll-delay)))))
772 (or (eq window (selected-window)) 772 (or (eq window (selected-window))
773 (goto-char opoint)))) 773 (goto-char opoint))))
774 774
775 ;; Create an overlay and immediately delete it, to get "overlay in no buffer".
776 (defconst mouse-drag-overlay
777 (let ((ol (make-overlay (point-min) (point-min))))
778 (delete-overlay ol)
779 (overlay-put ol 'face 'region)
780 ol))
781
782 (defvar mouse-selection-click-count 0) 775 (defvar mouse-selection-click-count 0)
783 776
784 (defvar mouse-selection-click-count-buffer nil) 777 (defvar mouse-selection-click-count-buffer nil)
785 778
786 (defun mouse-drag-region (start-event) 779 (defun mouse-drag-region (start-event)
903 (< mouse-1-click-follows-link 0)) "Long ") 896 (< mouse-1-click-follows-link 0)) "Long ")
904 (t "")) 897 (t ""))
905 "mouse-1" (substring msg 7))))))) 898 "mouse-1" (substring msg 7)))))))
906 msg) 899 msg)
907 900
908 (defun mouse-move-drag-overlay (ol start end mode)
909 (unless (= start end)
910 ;; Go to START first, so that when we move to END, if it's in the middle
911 ;; of intangible text, point jumps in the direction away from START.
912 ;; Don't do it if START=END otherwise a single click risks selecting
913 ;; a region if it's on intangible text. This exception was originally
914 ;; only applied on entry to mouse-drag-region, which had the problem
915 ;; that a tiny move during a single-click would cause the intangible
916 ;; text to be selected.
917 (goto-char start)
918 (goto-char end)
919 (setq end (point)))
920 (let ((range (mouse-start-end start end mode)))
921 (move-overlay ol (car range) (nth 1 range))))
922
923 (defun mouse-drag-track (start-event &optional 901 (defun mouse-drag-track (start-event &optional
924 do-mouse-drag-region-post-process) 902 do-mouse-drag-region-post-process)
925 "Track mouse drags by highlighting area between point and cursor. 903 "Track mouse drags by highlighting area between point and cursor.
926 The region will be defined with mark and point, and the overlay 904 The region will be defined with mark and point.
927 will be deleted after return. DO-MOUSE-DRAG-REGION-POST-PROCESS 905 DO-MOUSE-DRAG-REGION-POST-PROCESS should only be used by
928 should only be used by mouse-drag-region." 906 `mouse-drag-region'."
929 (mouse-minibuffer-check start-event) 907 (mouse-minibuffer-check start-event)
930 (setq mouse-selection-click-count-buffer (current-buffer)) 908 (setq mouse-selection-click-count-buffer (current-buffer))
931 ;; We must call deactivate-mark before repositioning point. 909 ;; We must call deactivate-mark before repositioning point.
932 ;; Otherwise, for `select-active-regions' non-nil, we get the wrong 910 ;; Otherwise, for `select-active-regions' non-nil, we get the wrong
933 ;; selection if the user drags a region, clicks elsewhere to 911 ;; selection if the user drags a region, clicks elsewhere to
956 (eq start-window original-window)) 934 (eq start-window original-window))
957 ;; Use start-point before the intangibility 935 ;; Use start-point before the intangibility
958 ;; treatment, in case we click on a link inside an 936 ;; treatment, in case we click on a link inside an
959 ;; intangible text. 937 ;; intangible text.
960 (mouse-on-link-p start-posn))) 938 (mouse-on-link-p start-posn)))
961 (click-count (1- (event-click-count start-event)))
962 (remap-double-click (and on-link
963 (eq mouse-1-click-follows-link 'double)
964 (= click-count 1)))
965 ;; Suppress automatic hscrolling, because that is a nuisance 939 ;; Suppress automatic hscrolling, because that is a nuisance
966 ;; when setting point near the right fringe (but see below). 940 ;; when setting point near the right fringe (but see below).
967 (automatic-hscrolling-saved automatic-hscrolling) 941 (automatic-hscrolling-saved automatic-hscrolling)
968 (automatic-hscrolling nil)) 942 (automatic-hscrolling nil)
969 (setq mouse-selection-click-count click-count) 943 event end end-point)
944
945 (setq mouse-selection-click-count (1- (event-click-count start-event)))
970 ;; In case the down click is in the middle of some intangible text, 946 ;; In case the down click is in the middle of some intangible text,
971 ;; use the end of that text, and put it in START-POINT. 947 ;; use the end of that text, and put it in START-POINT.
972 (if (< (point) start-point) 948 (if (< (point) start-point)
973 (goto-char start-point)) 949 (goto-char start-point))
974 (setq start-point (point)) 950 (setq start-point (point))
975 (if remap-double-click ;; Don't expand mouse overlay in links 951
976 (setq click-count 0)) 952 ;; Activate the mark.
977 (mouse-move-drag-overlay mouse-drag-overlay start-point start-point 953 (setq transient-mark-mode
978 click-count) 954 (if (eq transient-mark-mode 'lambda)
979 (overlay-put mouse-drag-overlay 'window start-window) 955 '(only)
980 (let (event end end-point last-end-point) 956 (cons 'only transient-mark-mode)))
981 (track-mouse 957 (push-mark nil nil t)
982 (while (progn 958
983 (setq event (read-event)) 959 ;; Track the mouse until we get a non-movement event.
984 (or (mouse-movement-p event) 960 (track-mouse
985 (memq (car-safe event) '(switch-frame select-window)))) 961 (while (progn
986 (if (memq (car-safe event) '(switch-frame select-window)) 962 (setq event (read-event))
987 nil 963 (or (mouse-movement-p event)
988 ;; Automatic hscrolling did not occur during the call to 964 (memq (car-safe event) '(switch-frame select-window))))
989 ;; `read-event'; but if the user subsequently drags the 965 (unless (memq (car-safe event) '(switch-frame select-window))
990 ;; mouse, go ahead and hscroll. 966 ;; Automatic hscrolling did not occur during the call to
991 (let ((automatic-hscrolling automatic-hscrolling-saved)) 967 ;; `read-event'; but if the user subsequently drags the
992 (redisplay)) 968 ;; mouse, go ahead and hscroll.
993 (setq end (event-end event) 969 (let ((automatic-hscrolling automatic-hscrolling-saved))
994 end-point (posn-point end)) 970 (redisplay))
995 (if (numberp end-point) 971 (setq end (event-end event)
996 (setq last-end-point end-point)) 972 end-point (posn-point end))
997 973 (if (and (eq (posn-window end) start-window)
998 (cond
999 ;; Are we moving within the original window?
1000 ((and (eq (posn-window end) start-window)
1001 (integer-or-marker-p end-point)) 974 (integer-or-marker-p end-point))
1002 (mouse-move-drag-overlay mouse-drag-overlay start-point end-point click-count)) 975 ;; If moving in the original window, move point by going
1003 976 ;; to start first, so that if end is in intangible text,
1004 (t 977 ;; point jumps away from start. Don't do it if
1005 (let ((mouse-row (cdr (cdr (mouse-position))))) 978 ;; start=end, or a single click would select a region if
1006 (cond 979 ;; it's on intangible text.
1007 ((null mouse-row)) 980 (unless (= start-point end-point)
1008 ((< mouse-row top) 981 (goto-char start-point)
1009 (mouse-scroll-subr start-window (- mouse-row top) 982 (goto-char end-point))
1010 mouse-drag-overlay start-point)) 983 (let ((mouse-row (cdr (cdr (mouse-position)))))
1011 ((>= mouse-row bottom) 984 (cond
1012 (mouse-scroll-subr start-window (1+ (- mouse-row bottom)) 985 ((null mouse-row))
1013 mouse-drag-overlay start-point))))))))) 986 ((< mouse-row top)
1014 987 (mouse-scroll-subr start-window (- mouse-row top)
1015 ;; In case we did not get a mouse-motion event 988 nil start-point))
1016 ;; for the final move of the mouse before a drag event 989 ((>= mouse-row bottom)
1017 ;; pretend that we did get one. 990 (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
1018 (when (and (memq 'drag (event-modifiers (car-safe event))) 991 nil start-point))))))))
1019 (setq end (event-end event) 992
1020 end-point (posn-point end)) 993 ;; Handle the terminating event if possible.
994 (when (consp event)
995 ;; Ensure that point is on the end of the last event.
996 (when (and (setq end-point (posn-point (event-end event)))
1021 (eq (posn-window end) start-window) 997 (eq (posn-window end) start-window)
1022 (integer-or-marker-p end-point)) 998 (integer-or-marker-p end-point)
1023 (mouse-move-drag-overlay mouse-drag-overlay start-point end-point click-count)) 999 (/= start-point end-point))
1024 1000 (goto-char start-point)
1025 ;; Handle the terminating event 1001 (goto-char end-point))
1026 (if (consp event) 1002 ;; Find its binding.
1027 (let* ((fun (key-binding (vector (car event)))) 1003 (let* ((fun (key-binding (vector (car event))))
1028 (do-multi-click (and (> (event-click-count event) 0) 1004 (do-multi-click (and (> (event-click-count event) 0)
1029 (functionp fun) 1005 (functionp fun)
1030 (not (memq fun 1006 (not (memq fun '(mouse-set-point
1031 '(mouse-set-point 1007 mouse-set-region))))))
1032 mouse-set-region)))))) 1008 (if (and (/= (mark) (point))
1033 ;; Run the binding of the terminating up-event, if possible. 1009 (not do-multi-click))
1034 (if (and (not (= (overlay-start mouse-drag-overlay) 1010 ;; If point has moved, finish the drag.
1035 (overlay-end mouse-drag-overlay))) 1011 (let* (last-command this-command)
1036 (not do-multi-click)) 1012 ;; Copy the region so that `select-active-regions' can
1037 (let* ((stop-point 1013 ;; override `copy-region-as-kill'.
1038 (if (numberp (posn-point (event-end event))) 1014 (and mouse-drag-copy-region
1039 (posn-point (event-end event)) 1015 do-mouse-drag-region-post-process
1040 last-end-point)) 1016 (let (deactivate-mark)
1041 ;; The end that comes from where we ended the drag. 1017 (copy-region-as-kill (mark) (point)))))
1042 ;; Point goes here. 1018 ;; If point hasn't moved, run the binding of the
1043 (region-termination 1019 ;; terminating up-event.
1044 (if (and stop-point (< stop-point start-point)) 1020 (if do-multi-click (goto-char start-point))
1045 (overlay-start mouse-drag-overlay) 1021 (deactivate-mark)
1046 (overlay-end mouse-drag-overlay))) 1022 (when (and (functionp fun)
1047 ;; The end that comes from where we started the drag. 1023 (= start-hscroll (window-hscroll start-window))
1048 ;; Mark goes there. 1024 ;; Don't run the up-event handler if the window
1049 (region-commencement 1025 ;; start changed in a redisplay after the
1050 (- (+ (overlay-end mouse-drag-overlay) 1026 ;; mouse-set-point for the down-mouse event at
1051 (overlay-start mouse-drag-overlay)) 1027 ;; the beginning of this function. When the
1052 region-termination)) 1028 ;; window start has changed, the up-mouse event
1053 last-command this-command) 1029 ;; contains a different position due to the new
1054 ;; We copy the region before setting the mark so 1030 ;; window contents, and point is set again.
1055 ;; that `select-active-regions' can override 1031 (or end-point
1056 ;; `copy-region-as-kill'. 1032 (= (window-start start-window)
1057 (and mouse-drag-copy-region 1033 start-window-start)))
1058 do-mouse-drag-region-post-process 1034 (when (and on-link
1059 (let (deactivate-mark) 1035 (= start-point (point))
1060 (copy-region-as-kill region-commencement 1036 (mouse--remap-link-click-p start-event event))
1061 region-termination))) 1037 ;; If we rebind to mouse-2, reselect previous selected
1062 (push-mark region-commencement t t) 1038 ;; window, so that the mouse-2 event runs in the same
1063 (goto-char region-termination) 1039 ;; situation as if user had clicked it directly. Fixes
1064 (if (not do-mouse-drag-region-post-process) 1040 ;; the bug reported by juri@jurta.org on 2005-12-27.
1065 ;; Skip all post-event handling, return immediately. 1041 (if (or (vectorp on-link) (stringp on-link))
1066 (delete-overlay mouse-drag-overlay) 1042 (setq event (aref on-link 0))
1067 (let ((buffer (current-buffer))) 1043 (select-window original-window)
1068 (mouse-show-mark) 1044 (setcar event 'mouse-2)
1069 ;; mouse-show-mark can call read-event, 1045 ;; If this mouse click has never been done by the
1070 ;; and that means the Emacs server could switch buffers 1046 ;; user, it doesn't have the necessary property to be
1071 ;; under us. If that happened, 1047 ;; interpreted correctly.
1072 ;; avoid trying to use the region. 1048 (put 'mouse-2 'event-kind 'mouse-click)))
1073 (and (mark t) mark-active 1049 (push event unread-command-events)))))))
1074 (eq buffer (current-buffer)) 1050
1075 (mouse-set-region-1))))) 1051 (defun mouse--remap-link-click-p (start-event end-event)
1076 ;; Run the binding of the terminating up-event. 1052 (or (and (eq mouse-1-click-follows-link 'double)
1077 ;; If a multiple click is not bound to mouse-set-point, 1053 (= (event-click-count start-event) 2))
1078 ;; cancel the effects of mouse-move-drag-overlay to 1054 (and
1079 ;; avoid producing wrong results. 1055 (not (eq mouse-1-click-follows-link 'double))
1080 (if do-multi-click (goto-char start-point)) 1056 (= (event-click-count start-event) 1)
1081 (delete-overlay mouse-drag-overlay) 1057 (= (event-click-count end-event) 1)
1082 (when (and (functionp fun) 1058 (or (not (integerp mouse-1-click-follows-link))
1083 (= start-hscroll (window-hscroll start-window)) 1059 (let ((t0 (posn-timestamp (event-start start-event)))
1084 ;; Don't run the up-event handler if the 1060 (t1 (posn-timestamp (event-end end-event))))
1085 ;; window start changed in a redisplay after 1061 (and (integerp t0) (integerp t1)
1086 ;; the mouse-set-point for the down-mouse 1062 (if (> mouse-1-click-follows-link 0)
1087 ;; event at the beginning of this function. 1063 (<= (- t1 t0) mouse-1-click-follows-link)
1088 ;; When the window start has changed, the 1064 (< (- t0 t1) mouse-1-click-follows-link))))))))
1089 ;; up-mouse event will contain a different 1065
1090 ;; position due to the new window contents,
1091 ;; and point is set again.
1092 (or end-point
1093 (= (window-start start-window)
1094 start-window-start)))
1095 (when (and on-link
1096 (or (not end-point) (= end-point start-point))
1097 (consp event)
1098 (or remap-double-click
1099 (and
1100 (not (eq mouse-1-click-follows-link 'double))
1101 (= click-count 0)
1102 (= (event-click-count event) 1)
1103 (or (not (integerp mouse-1-click-follows-link))
1104 (let ((t0 (posn-timestamp (event-start start-event)))
1105 (t1 (posn-timestamp (event-end event))))
1106 (and (integerp t0) (integerp t1)
1107 (if (> mouse-1-click-follows-link 0)
1108 (<= (- t1 t0) mouse-1-click-follows-link)
1109 (< (- t0 t1) mouse-1-click-follows-link))))))))
1110 ;; If we rebind to mouse-2, reselect previous selected window,
1111 ;; so that the mouse-2 event runs in the same
1112 ;; situation as if user had clicked it directly.
1113 ;; Fixes the bug reported by juri@jurta.org on 2005-12-27.
1114 (if (or (vectorp on-link) (stringp on-link))
1115 (setq event (aref on-link 0))
1116 (select-window original-window)
1117 (setcar event 'mouse-2)
1118 ;; If this mouse click has never been done by
1119 ;; the user, it doesn't have the necessary
1120 ;; property to be interpreted correctly.
1121 (put 'mouse-2 'event-kind 'mouse-click)))
1122 (push event unread-command-events))))
1123
1124 ;; Case where the end-event is not a cons cell (it's just a boring
1125 ;; char-key-press).
1126 (delete-overlay mouse-drag-overlay)))))
1127 1066
1128 ;; Commands to handle xterm-style multiple clicks. 1067 ;; Commands to handle xterm-style multiple clicks.
1129 (defun mouse-skip-word (dir) 1068 (defun mouse-skip-word (dir)
1130 "Skip over word, over whitespace, or over identical punctuation. 1069 "Skip over word, over whitespace, or over identical punctuation.
1131 If DIR is positive skip forward; if negative, skip backward." 1070 If DIR is positive skip forward; if negative, skip backward."
1261 (setcar last event) 1200 (setcar last event)
1262 nil))) 1201 nil)))
1263 1202
1264 ;; Momentarily show where the mark is, if highlighting doesn't show it. 1203 ;; Momentarily show where the mark is, if highlighting doesn't show it.
1265 1204
1266 (defun mouse-show-mark ()
1267 (let ((inhibit-quit t)
1268 (echo-keystrokes 0)
1269 event events key ignore
1270 (x-lost-selection-functions
1271 (when (boundp 'x-lost-selection-functions)
1272 (copy-sequence x-lost-selection-functions))))
1273 (add-hook 'x-lost-selection-functions
1274 (lambda (seltype)
1275 (when (eq seltype 'PRIMARY)
1276 (setq ignore t)
1277 (throw 'mouse-show-mark t))))
1278 (if transient-mark-mode
1279 (delete-overlay mouse-drag-overlay)
1280 (move-overlay mouse-drag-overlay (point) (mark t)))
1281 (catch 'mouse-show-mark
1282 ;; In this loop, execute scroll bar and switch-frame events.
1283 ;; Should we similarly handle `select-window' events? --Stef
1284 ;; Also ignore down-events that are undefined.
1285 (while (progn (setq event (read-event))
1286 (setq events (append events (list event)))
1287 (setq key (apply 'vector events))
1288 (or (and (consp event)
1289 (eq (car event) 'switch-frame))
1290 (and (consp event)
1291 (eq (posn-point (event-end event))
1292 'vertical-scroll-bar))
1293 (and (memq 'down (event-modifiers event))
1294 (not (key-binding key))
1295 (not (mouse-undouble-last-event events)))))
1296 (and (consp event)
1297 (or (eq (car event) 'switch-frame)
1298 (eq (posn-point (event-end event))
1299 'vertical-scroll-bar))
1300 (let ((keys (vector 'vertical-scroll-bar event)))
1301 (and (key-binding keys)
1302 (progn
1303 (call-interactively (key-binding keys)
1304 nil keys)
1305 (setq events nil)))))))
1306 ;; If we lost the selection, just turn off the highlighting.
1307 (unless ignore
1308 ;; Unread the key so it gets executed normally.
1309 (setq unread-command-events
1310 (nconc events unread-command-events)))
1311 (setq quit-flag nil)
1312 (unless transient-mark-mode
1313 (delete-overlay mouse-drag-overlay))))
1314
1315 (defun mouse-set-mark (click) 1205 (defun mouse-set-mark (click)
1316 "Set mark at the position clicked on with the mouse. 1206 "Set mark at the position clicked on with the mouse.
1317 Display cursor at that position for a second. 1207 Display cursor at that position for a second.
1318 This must be bound to a mouse click." 1208 This must be bound to a mouse click."
1319 (interactive "e") 1209 (interactive "e")
1383 "Copy the region between point and the mouse click in the kill ring. 1273 "Copy the region between point and the mouse click in the kill ring.
1384 This does not delete the region; it acts like \\[kill-ring-save]." 1274 This does not delete the region; it acts like \\[kill-ring-save]."
1385 (interactive "e") 1275 (interactive "e")
1386 (mouse-set-mark-fast click) 1276 (mouse-set-mark-fast click)
1387 (let (this-command last-command) 1277 (let (this-command last-command)
1388 (kill-ring-save (point) (mark t))) 1278 (kill-ring-save (point) (mark t))))
1389 (mouse-show-mark))
1390 1279
1391 ;; This function used to delete the text between point and the mouse 1280 ;; This function used to delete the text between point and the mouse
1392 ;; whenever it was equal to the front of the kill ring, but some 1281 ;; whenever it was equal to the front of the kill ring, but some
1393 ;; people found that confusing. 1282 ;; people found that confusing.
1394 1283
1474 ;; (It would be annoying to make a separate entry.) 1363 ;; (It would be annoying to make a separate entry.)
1475 (kill-new (buffer-substring (point) (mark t)) t) 1364 (kill-new (buffer-substring (point) (mark t)) t)
1476 (mouse-set-region-1) 1365 (mouse-set-region-1)
1477 ;; Arrange for a repeated mouse-3 to kill this region. 1366 ;; Arrange for a repeated mouse-3 to kill this region.
1478 (setq mouse-save-then-kill-posn 1367 (setq mouse-save-then-kill-posn
1479 (list (car kill-ring) (point) click-posn)) 1368 (list (car kill-ring) (point) click-posn)))
1480 (mouse-show-mark))
1481 ;; If we click this button again without moving it, 1369 ;; If we click this button again without moving it,
1482 ;; that time kill. 1370 ;; that time kill.
1483 (mouse-save-then-kill-delete-region (mark) (point)) 1371 (mouse-save-then-kill-delete-region (mark) (point))
1484 (setq mouse-selection-click-count 0) 1372 (setq mouse-selection-click-count 0)
1485 (setq mouse-save-then-kill-posn nil)) 1373 (setq mouse-save-then-kill-posn nil))
1519 (mouse-set-mark-fast click) 1407 (mouse-set-mark-fast click)
1520 (if before-scroll 1408 (if before-scroll
1521 (goto-char before-scroll)) 1409 (goto-char before-scroll))
1522 (exchange-point-and-mark) ;Why??? --Stef 1410 (exchange-point-and-mark) ;Why??? --Stef
1523 (kill-new (buffer-substring (point) (mark t)))) 1411 (kill-new (buffer-substring (point) (mark t))))
1524 (mouse-show-mark)
1525 (mouse-set-region-1) 1412 (mouse-set-region-1)
1526 (setq mouse-save-then-kill-posn 1413 (setq mouse-save-then-kill-posn
1527 (list (car kill-ring) (point) click-posn))))))) 1414 (list (car kill-ring) (point) click-posn)))))))
1528 1415
1529 (global-set-key [M-mouse-1] 'mouse-start-secondary) 1416 (global-set-key [M-mouse-1] 'mouse-start-secondary)