diff options
Diffstat (limited to 'lisp/mouse.el')
-rw-r--r-- | lisp/mouse.el | 515 |
1 files changed, 238 insertions, 277 deletions
diff --git a/lisp/mouse.el b/lisp/mouse.el index e2674184f69..e78eca40bc5 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -102,8 +102,7 @@ Expects to be bound to `down-mouse-1' in `key-translation-map'." (or mouse-1-click-in-non-selected-windows (eq (selected-window) (posn-window (event-start last-input-event))))) - (let ((this-event last-input-event) - (timedout + (let ((timedout (sit-for (if (numberp mouse-1-click-follows-link) (/ (abs mouse-1-click-follows-link) 1000.0) 0)))) @@ -112,7 +111,7 @@ Expects to be bound to `down-mouse-1' in `key-translation-map'." timedout (not timedout)) nil - (let ((event (read-event))) + (let ((event (read-key))) ;Use read-key so it works for xterm-mouse-mode! (if (eq (car-safe event) (if (eq mouse-1-click-follows-link 'double) 'double-mouse-1 'mouse-1)) ;; Turn the mouse-1 into a mouse-2 to follow links. @@ -307,13 +306,14 @@ This command must be bound to a mouse click." (or (eq frame oframe) (set-mouse-position (selected-frame) (1- (frame-width)) 0)))) -(defun mouse-tear-off-window (click) - "Delete the window clicked on, and create a new frame displaying its buffer." +(define-obsolete-function-alias 'mouse-tear-off-window 'tear-off-window "24.4") +(defun tear-off-window (click) + "Delete the selected window, and create a new frame displaying its buffer." (interactive "e") (mouse-minibuffer-check click) (let* ((window (posn-window (event-start click))) (buf (window-buffer window)) - (frame (make-frame))) + (frame (make-frame))) ;FIXME: Use pop-to-buffer. (select-frame frame) (switch-to-buffer buf) (delete-window window))) @@ -355,24 +355,6 @@ This command must be bound to a mouse click." (split-window-horizontally (min (max new-width first-col) last-col)))))) -;; `mouse-drag-line' is now the common routine for handling all line -;; dragging events combining the earlier `mouse-drag-mode-line-1' and -;; `mouse-drag-vertical-line'. It should improve the behavior of line -;; dragging wrt Emacs 23 as follows: - -;; (1) Gratuitous error messages and restrictions have been (hopefully) -;; removed. (The help-echo that dragging the mode-line can resize a -;; one-window-frame's window will still show through via bindings.el.) - -;; (2) No gratuitous selection of other windows should happen. (This -;; has not been completely fixed for mouse-autoselected windows yet.) - -;; (3) Mouse clicks below a scroll-bar should pass through via unread -;; command events. - -;; Note that `window-in-direction' replaces `mouse-drag-window-above' -;; and `mouse-drag-vertical-line-rightward-window' with Emacs 24.1. - (defun mouse-drag-line (start-event line) "Drag a mode line, header line, or vertical line with the mouse. START-EVENT is the starting mouse-event of the drag action. LINE @@ -383,116 +365,136 @@ must be one of the symbols `header', `mode', or `vertical'." (start (event-start start-event)) (window (posn-window start)) (frame (window-frame window)) - (minibuffer-window (minibuffer-window frame)) - (side (and (eq line 'vertical) - (or (cdr (assq 'vertical-scroll-bars - (frame-parameters frame))) - 'right))) + ;; `position' records the x- or y-coordinate of the last + ;; sampled position. + (position (if (eq line 'vertical) + (+ (window-pixel-left window) + (car (posn-x-y start))) + (+ (window-pixel-top window) + (cdr (posn-x-y start))))) + ;; `last-position' records the x- or y-coordinate of the + ;; previously sampled position. The difference of `position' + ;; and `last-position' determines the size change of WINDOW. + (last-position position) (draggable t) - height finished event position growth dragged) + posn-window growth dragged) + ;; Decide on whether we are allowed to track at all and whose + ;; window's edge we drag. (cond ((eq line 'header) - ;; Check whether header-line can be dragged at all. (if (window-at-side-p window 'top) + ;; We can't drag the header line of a topmost window. (setq draggable nil) - ;; window-pixel-edges includes the header and mode lines, so - ;; we need to account for that when calculating window growth. - ;; On GUI frames, assume the mouse is approximately in the - ;; middle of the header/mode line, so we need only half the - ;; height in pixels. - (setq height - (cond - ((display-graphic-p frame) - (/ (window-header-line-height window) 2)) - (t (window-header-line-height window)))) + ;; Drag bottom edge of window above the header line. (setq window (window-in-direction 'above window t)))) ((eq line 'mode) - ;; Check whether mode-line can be dragged at all. (if (and (window-at-side-p window 'bottom) - ;; Allow resizing the minibuffer window if it's on the same - ;; frame as and immediately below the clicked window, and - ;; it's active or `resize-mini-windows' is nil. - (not (and (eq (window-frame minibuffer-window) frame) - (= (nth 1 (window-pixel-edges minibuffer-window)) - (nth 3 (window-pixel-edges window))) - (or (not resize-mini-windows) - (eq minibuffer-window - (active-minibuffer-window)))))) - (setq draggable nil) - (setq height + ;; Allow resizing the minibuffer window if it's on the + ;; same frame as and immediately below `window', and it's + ;; either active or `resize-mini-windows' is nil. + (let ((minibuffer-window (minibuffer-window frame))) + (not (and (eq (window-frame minibuffer-window) frame) + (or (not resize-mini-windows) + (eq minibuffer-window + (active-minibuffer-window))))))) + (setq draggable nil)))) + + (let* ((exitfun nil) + (move + (lambda (event) (interactive "e") (cond - ((display-graphic-p frame) - (/ (window-mode-line-height window) 2)) - (t (window-mode-line-height window)))))) - ((eq line 'vertical) - ;; Get the window to adjust for the vertical case. If the scroll - ;; bar is on the window's right or we drag a vertical divider, - ;; adjust the window where the start-event occurred. If the - ;; scroll bar is on the start-event window's left or there are no - ;; scrollbars, adjust the window on the left of it. - (unless (or (eq side 'right) - (not (zerop (window-right-divider-width window)))) - (setq window (window-in-direction 'left window t))))) - - ;; Start tracking. - (track-mouse + ((not (consp event)) + nil) + ((eq line 'vertical) + ;; Drag right edge of `window'. + (setq start (event-start event)) + (setq position (car (posn-x-y start))) + ;; Set `posn-window' to the window where `event' was recorded. + ;; This can be `window' or the window on the left or right of + ;; `window'. + (when (window-live-p (setq posn-window (posn-window start))) + ;; Add left edge of `posn-window' to `position'. + (setq position (+ (window-pixel-left posn-window) position)) + (unless (nth 1 start) + ;; Add width of objects on the left of the text area to + ;; `position'. + (when (eq (window-current-scroll-bars posn-window) 'left) + (setq position (+ (window-scroll-bar-width posn-window) + position))) + (setq position (+ (car (window-fringes posn-window)) + (or (car (window-margins posn-window)) 0) + position)))) + ;; When the cursor overshoots after shrinking a window to its + ;; minimum size and the dragging direction changes, have the + ;; cursor first catch up with the window edge. + (unless (or (zerop (setq growth (- position last-position))) + (and (> growth 0) + (< position (+ (window-pixel-left window) + (window-pixel-width window)))) + (and (< growth 0) + (> position (+ (window-pixel-left window) + (window-pixel-width window))))) + (setq dragged t) + (adjust-window-trailing-edge window growth t t)) + (setq last-position position)) + (draggable + ;; Drag bottom edge of `window'. + (setq start (event-start event)) + ;; Set `posn-window' to the window where `event' was recorded. + ;; This can be either `window' or the window above or below of + ;; `window'. + (setq posn-window (posn-window start)) + (setq position (cdr (posn-x-y start))) + (when (window-live-p posn-window) + ;; Add top edge of `posn-window' to `position'. + (setq position (+ (window-pixel-top posn-window) position)) + ;; If necessary, add height of header line to `position' + (when (memq (posn-area start) + '(nil left-fringe right-fringe left-margin right-margin)) + (setq position (+ (window-header-line-height posn-window) position)))) + ;; When the cursor overshoots after shrinking a window to its + ;; minimum size and the dragging direction changes, have the + ;; cursor first catch up with the window edge. + (unless (or (zerop (setq growth (- position last-position))) + (and (> growth 0) + (< position (+ (window-pixel-top window) + (window-pixel-height window)))) + (and (< growth 0) + (> position (+ (window-pixel-top window) + (window-pixel-height window))))) + (setq dragged t) + (adjust-window-trailing-edge window growth nil t)) + (setq last-position position)))))) + ;; Start tracking. + (setq track-mouse t) ;; Loop reading events and sampling the position of the mouse. - (while (not finished) - (setq event (read-event)) - (setq position (mouse-pixel-position)) - ;; Do nothing if - ;; - there is a switch-frame event. - ;; - the mouse isn't in the frame that we started in - ;; - the mouse isn't in any Emacs frame - ;; Drag if - ;; - there is a mouse-movement event - ;; - there is a scroll-bar-movement event (Why? -- cyd) - ;; (same as mouse movement for our purposes) - ;; Quit if - ;; - there is a keyboard event or some other unknown event. - (cond - ((not (consp event)) - (setq finished t)) - ((memq (car event) '(switch-frame select-window)) - nil) - ((not (memq (car event) '(mouse-movement scroll-bar-movement))) - (when (consp event) - ;; Do not unread a drag-mouse-1 event to avoid selecting - ;; some other window. For vertical line dragging do not - ;; unread mouse-1 events either (but only if we dragged at - ;; least once to allow mouse-1 clicks get through). - (unless (and dragged - (if (eq line 'vertical) - (memq (car event) '(drag-mouse-1 mouse-1)) - (eq (car event) 'drag-mouse-1))) - (push event unread-command-events))) - (setq finished t)) - ((not (and (eq (car position) frame) - (cadr position))) - nil) - ((eq line 'vertical) - ;; Drag vertical divider. This must be probably fixed like - ;; for the mode-line. - (setq growth (- (cadr position) - (if (eq side 'right) 0 2) - (nth 2 (window-pixel-edges window)) - -1)) - (unless (zerop growth) - (setq dragged t) - (adjust-window-trailing-edge window growth t t))) - (draggable - ;; Drag horizontal divider. - (setq growth - (if (eq line 'mode) - (- (+ (cddr position) height) - (nth 3 (window-pixel-edges window))) - ;; The window's top includes the header line! - (- (+ (nth 3 (window-pixel-edges window)) height) - (cddr position)))) - (unless (zerop growth) - (setq dragged t) - (adjust-window-trailing-edge - window (if (eq line 'mode) growth (- growth)) nil t)))))))) + (setq exitfun + (set-transient-map + (let ((map (make-sparse-keymap))) + (define-key map [switch-frame] #'ignore) + (define-key map [select-window] #'ignore) + (define-key map [scroll-bar-movement] #'ignore) + (define-key map [mouse-movement] move) + ;; Swallow drag-mouse-1 events to avoid selecting some other window. + (define-key map [drag-mouse-1] + (lambda () (interactive) (funcall exitfun))) + ;; For vertical line dragging swallow also a mouse-1 + ;; event (but only if we dragged at least once to allow mouse-1 + ;; clicks to get through). + (when (eq line 'vertical) + (define-key map [mouse-1] + `(menu-item "" ,(lambda () (interactive) (funcall exitfun)) + :filter ,(lambda (cmd) (if dragged cmd))))) + ;; Some of the events will of course end up looked up + ;; with a mode-line or header-line prefix ... + (define-key map [mode-line] map) + (define-key map [header-line] map) + ;; ... and some maybe even with a right- or bottom-divider + ;; prefix. + (define-key map [right-divider] map) + (define-key map [bottom-divider] map) + map) + t (lambda () (setq track-mouse nil))))))) (defun mouse-drag-mode-line (start-event) "Change the height of a window by dragging on the mode line." @@ -509,14 +511,18 @@ must be one of the symbols `header', `mode', or `vertical'." (interactive "e") (mouse-drag-line start-event 'vertical)) -(defun mouse-set-point (event) +(defun mouse-set-point (event &optional promote-to-region) "Move point to the position clicked on with the mouse. -This should be bound to a mouse click event type." - (interactive "e") +This should be bound to a mouse click event type. +If PROMOTE-TO-REGION is non-nil and event is a multiple-click, +select the corresponding element around point." + (interactive "e\np") (mouse-minibuffer-check event) - ;; Use event-end in case called from mouse-drag-region. - ;; If EVENT is a click, event-end and event-start give same value. - (posn-set-point (event-end event))) + (if (and promote-to-region (> (event-click-count event) 1)) + (mouse-set-region event) + ;; Use event-end in case called from mouse-drag-region. + ;; If EVENT is a click, event-end and event-start give same value. + (posn-set-point (event-end event)))) (defvar mouse-last-region-beg nil) (defvar mouse-last-region-end nil) @@ -529,6 +535,8 @@ This should be bound to a mouse click event type." (eq mouse-last-region-end (region-end)) (eq mouse-last-region-tick (buffer-modified-tick)))) +(defvar mouse--drag-start-event nil) + (defun mouse-set-region (click) "Set the region to the text dragged over, and copy to kill ring. This should be bound to a mouse drag event. @@ -538,7 +546,29 @@ command alters the kill ring or not." (mouse-minibuffer-check click) (select-window (posn-window (event-start click))) (let ((beg (posn-point (event-start click))) - (end (posn-point (event-end click)))) + (end (posn-point (event-end click))) + (click-count (event-click-count click))) + (let ((drag-start (terminal-parameter nil 'mouse-drag-start))) + (when drag-start + ;; Drag events don't come with a click count, sadly, so we hack + ;; our way around this problem by remembering the start-event in + ;; `mouse-drag-start' and fetching the click-count from there. + (when (and (<= click-count 1) + (equal beg (posn-point (event-start drag-start)))) + (setq click-count (event-click-count drag-start))) + ;; Occasionally we get spurious drag events where the user hasn't + ;; dragged his mouse, but instead Emacs has dragged the text under the + ;; user's mouse. Try to recover those cases (bug#17562). + (when (and (equal (posn-x-y (event-start click)) + (posn-x-y (event-end click))) + (not (eq (car drag-start) 'mouse-movement))) + (setq end beg)) + (setf (terminal-parameter nil 'mouse-drag-start) nil))) + (when (and (integerp beg) (integerp end)) + (let ((range (mouse-start-end beg end (1- click-count)))) + (if (< end beg) + (setq end (nth 0 range) beg (nth 1 range)) + (setq beg (nth 0 range) end (nth 1 range))))) (and mouse-drag-copy-region (integerp beg) (integerp end) ;; Don't set this-command to `kill-region', so a following ;; C-w won't double the text in the kill ring. Ignore @@ -558,10 +588,10 @@ command alters the kill ring or not." (defun mouse-set-region-1 () ;; Set transient-mark-mode for a little while. (unless (eq (car-safe transient-mark-mode) 'only) - (setq transient-mark-mode - (cons 'only - (unless (eq transient-mark-mode 'lambda) - transient-mark-mode)))) + (setq-local transient-mark-mode + (cons 'only + (unless (eq transient-mark-mode 'lambda) + transient-mark-mode)))) (setq mouse-last-region-beg (region-beginning)) (setq mouse-last-region-end (region-end)) (setq mouse-last-region-tick (buffer-modified-tick))) @@ -632,13 +662,11 @@ Upon exit, point is at the far edge of the newly visible text." Highlight the drag area as you move the mouse. This must be bound to a button-down mouse event. In Transient Mark mode, the highlighting remains as long as the mark -remains active. Otherwise, it remains until the next input event. - -If the click is in the echo area, display the `*Messages*' buffer." +remains active. Otherwise, it remains until the next input event." (interactive "e") ;; Give temporary modes such as isearch a chance to turn off. (run-hooks 'mouse-leave-buffer-hook) - (mouse-drag-track start-event t)) + (mouse-drag-track start-event)) (defun mouse-posn-property (pos property) @@ -655,10 +683,11 @@ its value is returned." (str (posn-string pos))) (or (and str (get-text-property (cdr str) property (car str))) - ;; FIXME: mouse clicks on the mode-line come with a position in - ;; (nth 5). Maybe we should change the C code instead so that - ;; mouse-clicks don't include a position there! - (and pt (not (memq (posn-area pos) '(mode-line header-line))) + ;; Mouse clicks in the fringe come with a position in + ;; (nth 5). This is useful but is not exactly where we clicked, so + ;; don't look up that position's properties! + (and pt (not (memq (posn-area pos) '(left-fringe right-fringe + left-margin right-margin))) (get-char-property pt property w)))) (get-char-property pos property))) @@ -745,12 +774,9 @@ at the same position." "mouse-1" (substring msg 7))))))) msg) -(defun mouse-drag-track (start-event &optional - do-mouse-drag-region-post-process) +(defun mouse-drag-track (start-event) "Track mouse drags by highlighting area between point and cursor. -The region will be defined with mark and point. -DO-MOUSE-DRAG-REGION-POST-PROCESS should only be used by -`mouse-drag-region'." +The region will be defined with mark and point." (mouse-minibuffer-check start-event) (setq mouse-selection-click-count-buffer (current-buffer)) (deactivate-mark) @@ -763,8 +789,6 @@ DO-MOUSE-DRAG-REGION-POST-PROCESS should only be used by (start-posn (event-start start-event)) (start-point (posn-point start-posn)) (start-window (posn-window start-posn)) - (start-window-start (window-start start-window)) - (start-hscroll (window-hscroll start-window)) (bounds (window-edges start-window)) (make-cursor-line-fully-visible nil) (top (nth 1 bounds)) @@ -775,9 +799,7 @@ DO-MOUSE-DRAG-REGION-POST-PROCESS should only be used by (click-count (1- (event-click-count start-event))) ;; Suppress automatic hscrolling, because that is a nuisance ;; when setting point near the right fringe (but see below). - (auto-hscroll-mode-saved auto-hscroll-mode) - (auto-hscroll-mode nil) - moved-off-start event end end-point) + (auto-hscroll-mode-saved auto-hscroll-mode)) (setq mouse-selection-click-count click-count) ;; In case the down click is in the middle of some intangible text, @@ -788,93 +810,51 @@ DO-MOUSE-DRAG-REGION-POST-PROCESS should only be used by ;; Activate the region, using `mouse-start-end' to determine where ;; to put point and mark (e.g., double-click will select a word). - (setq transient-mark-mode - (if (eq transient-mark-mode 'lambda) - '(only) - (cons 'only transient-mark-mode))) + (setq-local transient-mark-mode + (if (eq transient-mark-mode 'lambda) + '(only) + (cons 'only transient-mark-mode))) (let ((range (mouse-start-end start-point start-point click-count))) (push-mark (nth 0 range) t t) (goto-char (nth 1 range))) - ;; Track the mouse until we get a non-movement event. - (track-mouse - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - (memq (car-safe event) '(switch-frame select-window)))) - (unless (memq (car-safe event) '(switch-frame select-window)) - ;; Automatic hscrolling did not occur during the call to - ;; `read-event'; but if the user subsequently drags the - ;; mouse, go ahead and hscroll. - (let ((auto-hscroll-mode auto-hscroll-mode-saved)) - (redisplay)) - (setq end (event-end event) - end-point (posn-point end)) - ;; Note whether the mouse has left the starting position. - (unless (eq end-point start-point) - (setq moved-off-start t)) - (if (and (eq (posn-window end) start-window) - (integer-or-marker-p end-point)) - (mouse--drag-set-mark-and-point start-point - end-point click-count) - (let ((mouse-row (cdr (cdr (mouse-position))))) - (cond - ((null mouse-row)) - ((< mouse-row top) - (mouse-scroll-subr start-window (- mouse-row top) - nil start-point)) - ((>= mouse-row bottom) - (mouse-scroll-subr start-window (1+ (- mouse-row bottom)) - nil start-point)))))))) - - ;; Handle the terminating event if possible. - (when (consp event) - ;; Ensure that point is on the end of the last event. - (when (and (setq end-point (posn-point (event-end event))) - (eq (posn-window end) start-window) - (integer-or-marker-p end-point) - (/= start-point end-point)) - (mouse--drag-set-mark-and-point start-point - end-point click-count)) - - ;; Find its binding. - (let* ((fun (key-binding (vector (car event)))) - ;; FIXME This doesn't make sense, because - ;; event-click-count always returns something >= 1. - (do-multi-click (and (> (event-click-count event) 0) - (functionp fun) - (not (memq fun '(mouse-set-point - mouse-set-region)))))) - (if (and (/= (mark) (point)) - (not do-multi-click)) - - ;; If point has moved, finish the drag. - (let* (last-command this-command) - (and mouse-drag-copy-region - do-mouse-drag-region-post-process - (let (deactivate-mark) - (copy-region-as-kill (mark) (point))))) - - ;; Otherwise, run binding of terminating up-event. + (setf (terminal-parameter nil 'mouse-drag-start) start-event) + (setq track-mouse t) + (setq auto-hscroll-mode nil) + + (set-transient-map + (let ((map (make-sparse-keymap))) + (define-key map [switch-frame] #'ignore) + (define-key map [select-window] #'ignore) + (define-key map [mouse-movement] + (lambda (event) (interactive "e") + (let* ((end (event-end event)) + (end-point (posn-point end))) + (unless (eq end-point start-point) + ;; As soon as the user moves, we can re-enable auto-hscroll. + (setq auto-hscroll-mode auto-hscroll-mode-saved) + ;; And remember that we have moved, so mouse-set-region can know + ;; its event is really a drag event. + (setcar start-event 'mouse-movement)) + (if (and (eq (posn-window end) start-window) + (integer-or-marker-p end-point)) + (mouse--drag-set-mark-and-point start-point + end-point click-count) + (let ((mouse-row (cdr (cdr (mouse-position))))) + (cond + ((null mouse-row)) + ((< mouse-row top) + (mouse-scroll-subr start-window (- mouse-row top) + nil start-point)) + ((>= mouse-row bottom) + (mouse-scroll-subr start-window (1+ (- mouse-row bottom)) + nil start-point)))))))) + map) + t (lambda () + (setq track-mouse nil) + (setq auto-hscroll-mode auto-hscroll-mode-saved) (deactivate-mark) - (if do-multi-click - (goto-char start-point) - (unless moved-off-start - (pop-mark))) - - (when (and (functionp fun) - (= start-hscroll (window-hscroll start-window)) - ;; Don't run the up-event handler if the window - ;; start changed in a redisplay after the - ;; mouse-set-point for the down-mouse event at - ;; the beginning of this function. When the - ;; window start has changed, the up-mouse event - ;; contains a different position due to the new - ;; window contents, and point is set again. - (or end-point - (= (window-start start-window) - start-window-start))) - (push event unread-command-events))))))) + (pop-mark))))) (defun mouse--drag-set-mark-and-point (start click click-count) (let* ((range (mouse-start-end start click click-count)) @@ -1089,24 +1069,7 @@ regardless of where you click." (let (select-active-regions) (deactivate-mark))) (or mouse-yank-at-point (mouse-set-point click)) - (let ((primary - (if (fboundp 'x-get-selection-value) - (if (eq (framep (selected-frame)) 'w32) - ;; MS-Windows emulates PRIMARY in x-get-selection, but not - ;; in x-get-selection-value (the latter only accesses the - ;; clipboard). So try PRIMARY first, in case they selected - ;; something with the mouse in the current Emacs session. - (or (x-get-selection 'PRIMARY) - (x-get-selection-value)) - ;; Else MS-DOS or X. - ;; On X, x-get-selection-value supports more formats and - ;; encodings, so use it in preference to x-get-selection. - (or (x-get-selection-value) - (x-get-selection 'PRIMARY))) - ;; FIXME: What about xterm-mouse-mode etc.? - (x-get-selection 'PRIMARY)))) - (unless primary - (error "No selection is available")) + (let ((primary (gui-get-primary-selection))) (push-mark (point)) (insert-for-yank primary))) @@ -1293,7 +1256,7 @@ This must be bound to a mouse drag event." (if (numberp (posn-point posn)) (setq beg (posn-point posn))) (move-overlay mouse-secondary-overlay beg (posn-point end)) - (x-set-selection + (gui-set-selection 'SECONDARY (buffer-substring (overlay-start mouse-secondary-overlay) (overlay-end mouse-secondary-overlay)))))) @@ -1330,6 +1293,7 @@ The function returns a non-nil value if it creates a secondary selection." (setq mouse-secondary-start (make-marker))) (set-marker mouse-secondary-start start-point) (delete-overlay mouse-secondary-overlay)) + ;; FIXME: Use mouse-drag-track! (let (event end end-point) (track-mouse (while (progn @@ -1368,13 +1332,13 @@ The function returns a non-nil value if it creates a secondary selection." (if (marker-position mouse-secondary-start) (save-window-excursion (delete-overlay mouse-secondary-overlay) - (x-set-selection 'SECONDARY nil) + (gui-set-selection 'SECONDARY nil) (select-window start-window) (save-excursion (goto-char mouse-secondary-start) (sit-for 1) nil)) - (x-set-selection + (gui-set-selection 'SECONDARY (buffer-substring (overlay-start mouse-secondary-overlay) (overlay-end mouse-secondary-overlay))))))))) @@ -1388,7 +1352,7 @@ regardless of where you click." ;; Give temporary modes such as isearch a chance to turn off. (run-hooks 'mouse-leave-buffer-hook) (or mouse-yank-at-point (mouse-set-point click)) - (let ((secondary (x-get-selection 'SECONDARY))) + (let ((secondary (gui-get-selection 'SECONDARY))) (if secondary (insert-for-yank secondary) (error "No secondary selection")))) @@ -1507,7 +1471,7 @@ CLICK position, kill the secondary selection." (setq str (buffer-substring (overlay-start mouse-secondary-overlay) (overlay-end mouse-secondary-overlay))) (> (length str) 0) - (x-set-selection 'SECONDARY str)))) + (gui-set-selection 'SECONDARY str)))) (defcustom mouse-buffer-menu-maxlen 20 @@ -1552,8 +1516,17 @@ This switches buffers in the window that you clicked on, and selects that window." (interactive "e") (mouse-minibuffer-check event) - (let ((buffers (buffer-list)) alist menu split-by-major-mode sum-of-squares) - ;; Make an alist of elements that look like (MENU-ITEM . BUFFER). + (let ((buf (x-popup-menu event (mouse-buffer-menu-map))) + (window (posn-window (event-start event)))) + (when buf + (select-window + (if (framep window) (frame-selected-window window) + window)) + (switch-to-buffer buf)))) + +(defun mouse-buffer-menu-map () + ;; Make an alist of elements that look like (MENU-ITEM . BUFFER). + (let ((buffers (buffer-list)) split-by-major-mode sum-of-squares) (dolist (buf buffers) ;; Divide all buffers into buckets for various major modes. ;; Each bucket looks like (MODE NAMESTRING BUFFERS...). @@ -1617,18 +1590,10 @@ and selects that window." (setq subdivided-menus (cons (cons "Others" others-list) subdivided-menus))))) - (setq menu (cons "Buffer Menu" (nreverse subdivided-menus)))) - (progn - (setq alist (mouse-buffer-menu-alist buffers)) - (setq menu (cons "Buffer Menu" - (mouse-buffer-menu-split "Select Buffer" alist))))) - (let ((buf (x-popup-menu event menu)) - (window (posn-window (event-start event)))) - (when buf - (select-window - (if (framep window) (frame-selected-window window) - window)) - (switch-to-buffer buf))))) + (cons "Buffer Menu" (nreverse subdivided-menus))) + (cons "Buffer Menu" + (mouse-buffer-menu-split "Select Buffer" + (mouse-buffer-menu-alist buffers)))))) (defun mouse-buffer-menu-alist (buffers) (let (tail @@ -1902,14 +1867,10 @@ choose a font." ;;; Bindings for mouse commands. -(define-key global-map [down-mouse-1] 'mouse-drag-region) +(global-set-key [down-mouse-1] 'mouse-drag-region) (global-set-key [mouse-1] 'mouse-set-point) (global-set-key [drag-mouse-1] 'mouse-set-region) -;; These are tested for in mouse-drag-region. -(global-set-key [double-mouse-1] 'mouse-set-point) -(global-set-key [triple-mouse-1] 'mouse-set-point) - (defun mouse--strip-first-event (_prompt) (substring (this-single-command-raw-keys) 1)) |