;;; mouse.el --- window system-independent mouse support
;; Copyright (C) 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003,
-;; 2004, 2005, 2006 Free Software Foundation, Inc.
+;; 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: hardware, mouse
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
(cons 'keymap
(cons (concat
(capitalize (subst-char-in-string
- ?- ?\ (symbol-name
+ ?- ?\s (symbol-name
minor-mode)))
" Menu")
(cdr menu)))))
should-enlarge-minibuffer event mouse y top bot edges wconfig growth)
(track-mouse
(progn
- ;; enlarge-window only works on the selected window, so
- ;; we must select the window where the start event originated.
- ;; unwind-protect will restore the old selected window later.
- (select-window start-event-window)
-
;; if this is the bottommost ordinary window, then to
;; move its modeline the minibuffer must be enlarged.
(setq should-enlarge-minibuffer
mode-line-p
(not (one-window-p t))
(= (nth 1 (window-edges minibuffer))
- (nth 3 (window-edges)))))
+ (nth 3 (window-edges start-event-window)))))
;; loop reading events and sampling the position of
;; the mouse.
;; - there is a scroll-bar-movement event
;; (same as mouse movement for our purposes)
;; quit if
- ;; - there is a keyboard event or some other unknown event
- ;; unknown event.
- (cond ((integerp event)
+ ;; - there is a keyboard event or some other unknown event.
+ (cond ((not (consp event))
(setq done t))
((memq (car event) '(switch-frame select-window))
((not (memq (car event) '(mouse-movement scroll-bar-movement)))
(when (consp event)
- (push event unread-command-events))
+ ;; Do not unread a drag-mouse-1 event since it will cause the
+ ;; selection of the window above when dragging the modeline
+ ;; above the selected window.
+ (unless (eq (car event) 'drag-mouse-1)
+ (push event unread-command-events)))
(setq done t))
((not (eq (car mouse) start-event-frame))
(t
(setq y (cdr (cdr mouse))
- edges (window-edges)
+ edges (window-edges start-event-window)
top (nth 1 edges)
bot (nth 3 edges))
(and (not should-enlarge-minibuffer)
(> growth 0)
mode-line-p
- (/= top (nth 1 (window-edges)))))
+ (/= top
+ (nth 1 (window-edges
+ ;; Choose right window.
+ start-event-window)))))
(set-window-configuration wconfig)))))))))
(defun mouse-drag-mode-line (start-event)
(error "Attempt to drag leftmost scrollbar")))
(track-mouse
(progn
- ;; enlarge-window only works on the selected window, so
- ;; we must select the window where the start event originated.
- ;; unwind-protect will restore the old selected window later.
- (select-window start-event-window)
;; loop reading events and sampling the position of
;; the mouse.
(while (not done)
;; If the scroll bar is on the window's left,
;; adjust the window on the left.
(if (eq which-side 'right)
- (selected-window)
+ start-event-window
(mouse-drag-vertical-line-rightward-window
- (selected-window)))))
+ start-event-window))))
(setq x (- (car (cdr mouse))
(if (eq which-side 'right) 0 2))
edges (window-edges window)
(defun mouse-posn-property (pos property)
- "Look for a property at click position."
+ "Look for a property at click position.
+POS may be either a buffer position or a click position like
+those returned from `event-start'. If the click position is on
+a string, the text property PROPERTY is examined.
+If this is nil or the click is not on a string, then
+the corresponding buffer position is searched for PROPERTY.
+If PROPERTY is encountered in one of those places,
+its value is returned."
(if (consp pos)
(let ((w (posn-window pos)) (pt (posn-point pos))
(str (posn-string pos)))
((eq action 'mouse-face)
(and (mouse-posn-property pos 'mouse-face) t))
((functionp action)
- ;; FIXME: This is wrong if the click is in a different buffer.
+ ;; FIXME: This seems questionable if the click is not in a buffer.
;; Should we instead decide that `action' takes a `posn'?
- (funcall action (if (consp pos) (posn-point pos) pos)))
+ (if (consp pos)
+ (with-current-buffer (window-buffer (posn-window pos))
+ (funcall action (posn-point pos)))
+ (funcall action pos)))
(t action))))
(defun mouse-fixup-help-message (msg)
(let ((range (mouse-start-end start end mode)))
(move-overlay ol (car range) (nth 1 range))))
-(defun mouse-drag-track (start-event &optional
+(defun mouse-drag-track (start-event &optional
do-mouse-drag-region-post-process)
"Track mouse drags by highlighting area between point and cursor.
The region will be defined with mark and point, and the overlay
(click-count (1- (event-click-count start-event)))
(remap-double-click (and on-link
(eq mouse-1-click-follows-link 'double)
- (= click-count 1))))
+ (= click-count 1)))
+ ;; Suppress automatic hscrolling, because that is a nuisance
+ ;; when setting point near the right fringe (but see below).
+ (automatic-hscrolling-saved automatic-hscrolling)
+ (automatic-hscrolling nil))
(setq mouse-selection-click-count click-count)
;; In case the down click is in the middle of some intangible text,
;; use the end of that text, and put it in START-POINT.
(memq (car-safe event) '(switch-frame select-window))))
(if (memq (car-safe event) '(switch-frame select-window))
nil
+ ;; Automatic hscrolling did not occur during the call to
+ ;; `read-event'; but if the user subsequently drags the
+ ;; mouse, go ahead and hscroll.
+ (let ((automatic-hscrolling automatic-hscrolling-saved))
+ (redisplay))
(setq end (event-end event)
end-point (posn-point end))
(if (numberp end-point)
(let* ((fun (key-binding (vector (car event))))
(do-multi-click (and (> (event-click-count event) 0)
(functionp fun)
- (not (memq fun
- '(mouse-set-point
+ (not (memq fun
+ '(mouse-set-point
mouse-set-region))))))
;; Run the binding of the terminating up-event, if possible.
(if (and (not (= (overlay-start mouse-drag-overlay)
(overlay-start mouse-drag-overlay))
region-termination))
last-command this-command)
+ (when (eq transient-mark-mode 'identity)
+ ;; Reset `transient-mark-mode' to avoid expanding the region
+ ;; while scrolling (compare thread on "Erroneous selection
+ ;; extension ..." on bug-gnu-emacs from 2007-06-10).
+ (setq transient-mark-mode nil))
(push-mark region-commencement t t)
(goto-char region-termination)
(if (not do-mouse-drag-region-post-process)
(if do-multi-click (goto-char start-point))
(delete-overlay mouse-drag-overlay)
(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 will contain a different
- ;; position due to the new window contents,
- ;; and point is set again.
- (or end-point
- (= (window-start start-window)
- start-window-start)))
- (when (and on-link
+ (= 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 will contain a different
+ ;; position due to the new window contents,
+ ;; and point is set again.
+ (or end-point
+ (= (window-start start-window)
+ start-window-start)))
+ (when (and on-link
(or (not end-point) (= end-point start-point))
(consp event)
(or remap-double-click
(not (eq mouse-1-click-follows-link 'double))
(= click-count 0)
(= (event-click-count event) 1)
- (not (input-pending-p))
(or (not (integerp mouse-1-click-follows-link))
(let ((t0 (posn-timestamp (event-start start-event)))
(t1 (posn-timestamp (event-end event))))
(unless ignore
;; For certain special keys, delete the region.
(if (member key mouse-region-delete-keys)
- (delete-region (mark t) (point))
+ (progn
+ ;; Since notionally this is a separate command,
+ ;; run all the hooks that would be run if it were
+ ;; executed separately.
+ (run-hooks 'post-command-hook)
+ (setq last-command this-command)
+ (setq this-original-command 'delete-region)
+ (setq this-command (or (command-remapping this-original-command)
+ this-original-command))
+ (run-hooks 'pre-command-hook)
+ (call-interactively this-command))
;; Otherwise, unread the key so it gets executed normally.
(setq unread-command-events
(nconc events unread-command-events))))
(with-current-buffer (window-buffer (posn-window posn))
(if (numberp (posn-point posn))
(setq beg (posn-point posn)))
- (move-overlay mouse-secondary-overlay beg (posn-point end)))))
+ (move-overlay mouse-secondary-overlay beg (posn-point end))
+ (x-set-selection
+ 'SECONDARY
+ (buffer-substring (overlay-start mouse-secondary-overlay)
+ (overlay-end mouse-secondary-overlay))))))
(defun mouse-drag-secondary (start-event)
"Set the secondary selection to the text that the mouse is dragged over.
;; 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))
- (insert (x-get-selection 'SECONDARY)))
+ (let ((secondary (x-get-selection 'SECONDARY)))
+ (if secondary
+ (insert (x-get-selection 'SECONDARY))
+ (error "No secondary selection"))))
(defun mouse-kill-secondary ()
"Kill the text in the secondary selection.
(setq tail buffers)
(while tail
(let ((elt (car tail)))
- (if (/= (aref (buffer-name elt) 0) ?\ )
+ (if (/= (aref (buffer-name elt) 0) ?\s)
(setq head
(cons
(cons
"X fonts suitable for use in Emacs.")
(defun mouse-set-font (&rest fonts)
- "Select an emacs font from a list of known good fonts and fontsets."
+ "Select an Emacs font from a list of known good fonts and fontsets."
(interactive
(progn (unless (display-multi-font-p)
(error "Cannot change fonts on this display"))
(global-set-key [mouse-2] 'mouse-yank-at-click)
;; Allow yanking also when the corresponding cursor is "in the fringe".
-(global-set-key [right-fringe mouse-2] [mouse-2])
+(global-set-key [right-fringe mouse-2] 'mouse-yank-at-click)
+(global-set-key [left-fringe mouse-2] 'mouse-yank-at-click)
(global-set-key [mouse-3] 'mouse-save-then-kill)
+(global-set-key [right-fringe mouse-3] 'mouse-save-then-kill)
+(global-set-key [left-fringe mouse-3] 'mouse-save-then-kill)
;; By binding these to down-going events, we let the user use the up-going
;; event to make the selection, saving a click.