-;;; mouse.el --- window system-independent mouse support
+;;; mouse.el --- window system-independent mouse support -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1995, 1999-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 1999-2013 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: hardware, mouse
"Popup the given menu and call the selected option.
MENU can be a keymap, an easymenu-style menu or a list of keymaps as for
`x-popup-menu'.
-POSITION can be a click event or ((XOFFSET YOFFSET) WINDOW) and defaults to
- the current mouse position.
+The menu is shown at the place where POSITION specifies. About
+the form of POSITION, see `popup-menu-normalize-position'.
PREFIX is the prefix argument (if any) to pass to the command."
(let* ((map (cond
((keymapp menu) menu)
(filter (when (symbolp map)
(plist-get (get map 'menu-prop) :filter))))
(if filter (funcall filter (symbol-function map)) map)))))
- event cmd)
- (unless position
- (let ((mp (mouse-pixel-position)))
- (setq position (list (list (cadr mp) (cddr mp)) (car mp)))))
+ event cmd
+ (position (popup-menu-normalize-position position)))
;; The looping behavior was taken from lmenu's popup-menu-popup
(while (and map (setq event
;; map could be a prefix key, in which case
binding)
(while (and map (null binding))
(setq binding (lookup-key (car map) mouse-click))
- (if (numberp binding) ; `too long'
+ (if (numberp binding) ; `too long'
(setq binding nil))
(setq map (cdr map)))
binding)
;; mouse-major-mode-menu was using `command-execute' instead.
(call-interactively cmd))))
+(defun popup-menu-normalize-position (position)
+ "Convert the POSITION to the form which `popup-menu' expects internally.
+POSITION can an event, a posn- value, a value having
+form ((XOFFSET YOFFSET) WINDOW), or nil.
+If nil, the current mouse position is used."
+ (pcase position
+ ;; nil -> mouse cursor position
+ (`nil
+ (let ((mp (mouse-pixel-position)))
+ (list (list (cadr mp) (cddr mp)) (car mp))))
+ ;; Value returned from `event-end' or `posn-at-point'.
+ ((pred posnp)
+ (let ((xy (posn-x-y position)))
+ (list (list (car xy) (cdr xy))
+ (posn-window position))))
+ ;; Event.
+ ((pred eventp)
+ (popup-menu-normalize-position (event-end position)))
+ (t position)))
+
(defun minor-mode-menu-from-indicator (indicator)
"Show menu for minor mode specified by INDICATOR.
Interactively, INDICATOR is read using completion.
(defun mouse-major-mode-menu (event &optional prefix)
"Pop up a mode-specific menu of mouse commands.
Default to the Edit menu if the major mode doesn't define a menu."
+ (declare (obsolete mouse-menu-major-mode-map "23.1"))
(interactive "@e\nP")
(run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
(popup-menu (mouse-menu-major-mode-map) event prefix))
-(make-obsolete 'mouse-major-mode-menu 'mouse-menu-major-mode-map "23.1")
(defun mouse-popup-menubar (event prefix)
"Pop up a menu equivalent to the menu bar for keyboard EVENT with PREFIX.
The contents are the items that would be in the menu bar whether or
not it is actually displayed."
+ (declare (obsolete mouse-menu-bar-map "23.1"))
(interactive "@e \nP")
(run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
(popup-menu (mouse-menu-bar-map) (unless (integerp event) event) prefix))
-(make-obsolete 'mouse-popup-menubar 'mouse-menu-bar-map "23.1")
(defun mouse-popup-menubar-stuff (event prefix)
"Popup a menu like either `mouse-major-mode-menu' or `mouse-popup-menubar'.
Use the former if the menu bar is showing, otherwise the latter."
+ (declare (obsolete nil "23.1"))
(interactive "@e\nP")
(run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
(popup-menu
(mouse-menu-bar-map)
(mouse-menu-major-mode-map))
event prefix))
-(make-obsolete 'mouse-popup-menubar-stuff nil "23.1")
\f
;; Commands that operate on windows.
;; until there is a non-mouse-movement event. Also,
;; scroll-bar-movement events are the same as mouse movement for
;; our purposes. (Why? -- cyd)
+ ;; If you change this, check that all of the following still work:
+ ;; Resizing windows by dragging mode-lines and header lines,
+ ;; and vertical lines (in windows without scroll bars).
+ ;; Doing this should not select another window, even if
+ ;; mouse-autoselect-window is non-nil.
+ ;; Mouse-1 clicks in Info header lines should advance position
+ ;; by one node at a time if mouse-1-click-follows-link is non-nil,
+ ;; otherwise they should just select the window.
(while (progn
(setq event (read-event))
- (memq (car-safe event) '(mouse-movement scroll-bar-movement)))
+ (memq (car-safe event)
+ '(mouse-movement scroll-bar-movement
+ switch-frame select-window)))
(setq position (mouse-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
(cond
- ((or (not (eq (car position) frame))
- (null (cadr position)))
+ ((memq (car event) '(switch-frame select-window))
+ nil)
+ ((not (and (eq (car position) frame)
+ (cadr position)))
nil)
((eq line 'vertical)
;; Drag vertical divider.
growth
(- growth)))))))
;; Process the terminating event.
- (when (and (mouse-event-p event) on-link (not dragged)
- (mouse--remap-link-click-p start-event event))
- ;; If mouse-2 has never been done by the user, it doesn't have
- ;; the necessary property to be interpreted correctly.
- (put 'mouse-2 'event-kind 'mouse-click)
- (setcar event 'mouse-2))
- (push event unread-command-events)))
-
+ (unless dragged
+ (when (and (mouse-event-p event) on-link
+ (mouse--remap-link-click-p start-event event))
+ ;; If mouse-2 has never been done by the user, it doesn't have
+ ;; the necessary property to be interpreted correctly.
+ (put 'mouse-2 'event-kind 'mouse-click)
+ (setcar event 'mouse-2))
+ (push event unread-command-events))))
(defun mouse-drag-mode-line (start-event)
"Change the height of a window by dragging on the mode line."
;; 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
(copy-region-as-kill (mark) (point)))))
;; Otherwise, run binding of terminating up-event.
+ (deactivate-mark)
(if do-multi-click
(goto-char start-point)
- (deactivate-mark)
(unless moved-off-start
(pop-mark)))
(or mouse-yank-at-point (mouse-set-point click))
(let ((primary
(cond
- ((eq system-type 'windows-nt)
+ ((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
(choice
;; Either choice == 'x-select-font, or choice is a
;; symbol whose name is a font.
- (buffer-face-mode-invoke (font-face-attributes
- (if (eq choice 'x-select-font)
- (x-select-font)
- (symbol-name choice)))
- t
- (called-interactively-p 'interactive))))))))
+ (let ((font (if (eq choice 'x-select-font)
+ (x-select-font)
+ (symbol-name choice))))
+ (buffer-face-mode-invoke
+ (if (fontp font 'font-spec)
+ (list :font font)
+ (font-face-attributes font))
+ t (called-interactively-p 'interactive)))))))))
\f
;;; Bindings for mouse commands.