;;; avoid.el --- make mouse pointer stay out of the way of editing
-;;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+;;; Copyright (C) 1993, 1994, 2000 Free Software Foundation, Inc.
-;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu>
+;; Author: Boris Goldowsky <boris@gnu.org>
;; Keywords: mouse
;; This file is part of GNU Emacs.
;; For those who are annoyed by the mouse pointer obscuring text,
;; this mode moves the mouse pointer - either just a little out of
-;; the way, or all the way to the corner of the frame.
+;; the way, or all the way to the corner of the frame.
;; To use, load or evaluate this file and type M-x mouse-avoidance-mode .
-;; To set up permanently, put the following in your .emacs:
+;; To set up permanently, put the following in your .emacs:
;;
-;; (if window-system (mouse-avoidance-mode 'animate))
+;; (if (display-mouse-p) (mouse-avoidance-mode 'animate))
;;
-;; The 'animate can be 'jump or 'banish or 'exile or 'protean if you prefer.
+;; Other legitimate alternatives include
+;; `banish', `exile', `jump', `cat-and-mouse', and `proteus'.
+;; They do somewhat different things.
;; See the documentation for function `mouse-avoidance-mode' for
;; details of the different modes.
;;
;; For added silliness, make the animatee animate...
;; put something similar to the following into your .emacs:
;;
-;; (if window-system
+;; (if (eq window-system 'x)
;; (mouse-avoidance-set-pointer-shape
;; (eval (nth (random 4)
;; '(x-pointer-man x-pointer-spider
;;
;; For completely random pointer shape, replace the setq above with:
;; (setq x-pointer-shape (mouse-avoidance-random-shape))
-;;
+;;
;; Bugs / Warnings / To-Do:
;;
;; - Using this code does slow emacs down. "banish" mode shouldn't
;; rather than always raising the frame.
;; Credits:
-;; This code was helped by all those who contributed suggestions,
+;; This code was helped by all those who contributed suggestions,
;; fixes, and additions
;; Joe Harrington (and his advisor), for the original inspiration.
;; Ken Manheimer, for dreaming up the Protean mode.
:prefix "mouse-avoidance-"
:group 'mouse)
+;;;###autoload
+(defcustom mouse-avoidance-mode nil
+ "Activate mouse avoidance mode.
+See function `mouse-avoidance-mode' for possible values.
+Setting this variable directly does not take effect;
+use either \\[customize] or the function `mouse-avoidance-mode'."
+ :set (lambda (symbol value)
+ ;; 'none below prevents toggling when value is nil.
+ (mouse-avoidance-mode (or value 'none)))
+ :initialize 'custom-initialize-default
+ :type '(choice (const :tag "none" nil) (const banish) (const jump)
+ (const animate) (const exile) (const proteus)
+ )
+ :group 'avoid
+ :require 'avoid
+ :version "20.3")
-(defvar mouse-avoidance-mode nil
- "Value is t or a symbol if the mouse pointer should avoid the cursor.
-See function `mouse-avoidance-mode' for possible values. Changing this
-variable is NOT the recommended way to change modes; use that function
-instead.")
(defcustom mouse-avoidance-nudge-dist 15
"*Average distance that mouse will be moved when approached by cursor.
(defvar mouse-avoidance-n-pointer-shapes 0)
(defvar mouse-avoidance-old-pointer-shape nil)
+;; This timer is used to run something when Emacs is idle.
+(defvar mouse-avoidance-timer nil)
+
;;; Functions:
(defsubst mouse-avoidance-set-pointer-shape (shape)
Analogous to mouse-position."
(let* ((w (selected-window))
(edges (window-edges w))
- (list
+ (list
(compute-motion (max (window-start w) (point-min)) ; start pos
;; window-start can be < point-min if the
- ;; latter has changed since the last redisplay
+ ;; latter has changed since the last redisplay
'(0 . 0) ; start XY
(point) ; stop pos
(cons (window-width) (window-height)); stop XY: none
;(defun mouse-avoidance-point-position-test ()
; (interactive)
-; (message (format "point=%s mouse=%s"
+; (message (format "point=%s mouse=%s"
; (cdr (mouse-avoidance-point-position))
; (cdr (mouse-position)))))
(raise-frame f)
(set-mouse-position f (car pos) (cdr pos))
t))
-
+
(defun mouse-avoidance-too-close-p (mouse)
- ;; Return t if mouse pointer and point cursor are too close.
- ;; Acceptable distance is defined by mouse-avoidance-threshold.
- (let ((point (mouse-avoidance-point-position)))
- (and (eq (car mouse) (car point))
- (car (cdr mouse))
- (< (abs (- (car (cdr mouse)) (car (cdr point))))
- mouse-avoidance-threshold)
- (< (abs (- (cdr (cdr mouse)) (cdr (cdr point))))
- mouse-avoidance-threshold))))
+ "Return t if mouse pointer and point cursor are too close.
+MOUSE is the current mouse position as returned by `mouse-position'.
+Acceptable distance is defined by `mouse-avoidance-threshold'."
+ (let* ((frame (car mouse))
+ (mouse-y (cdr (cdr mouse)))
+ (tool-bar-lines (frame-parameter nil 'tool-bar-lines)))
+ (if (and mouse-y (< mouse-y tool-bar-lines))
+ nil
+ (let ((point (mouse-avoidance-point-position))
+ (mouse-x (car (cdr mouse))))
+ (and (eq frame (car point))
+ (not (null mouse-x))
+ (< (abs (- mouse-x (car (cdr point))))
+ mouse-avoidance-threshold)
+ (< (abs (- mouse-y (cdr (cdr point))))
+ mouse-avoidance-threshold))))))
(defun mouse-avoidance-banish-destination ()
"The position to which mouse-avoidance-mode `banish' moves the mouse.
((or R1 L2))
(t 0))))
-(defun mouse-avoidance-nudge-mouse ()
+(defun mouse-avoidance-nudge-mouse ()
;; Push the mouse a little way away, possibly animating the move
;; For these modes, state keeps track of the total offset that we've
;; accumulated, and tries to keep it close to zero.
(let* ((cur (mouse-position))
(cur-frame (car cur))
(cur-pos (cdr cur))
- (deltax (mouse-avoidance-delta
+ (deltax (mouse-avoidance-delta
(car cur-pos) (- (random mouse-avoidance-nudge-var)
(car mouse-avoidance-state))
mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
0 (frame-width)))
- (deltay (mouse-avoidance-delta
+ (deltay (mouse-avoidance-delta
(cdr cur-pos) (- (random mouse-avoidance-nudge-var)
(cdr mouse-avoidance-state))
mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
(setq mouse-avoidance-state
(cons (+ (car mouse-avoidance-state) deltax)
(+ (cdr mouse-avoidance-state) deltay)))
- (if (or (eq mouse-avoidance-mode 'animate)
+ (if (or (eq mouse-avoidance-mode 'animate)
(eq mouse-avoidance-mode 'proteus))
(let ((i 0.0))
(while (<= i 1)
- (mouse-avoidance-set-mouse-position
+ (mouse-avoidance-set-mouse-position
(cons (+ (car cur-pos) (round (* i deltax)))
(+ (cdr cur-pos) (round (* i deltay)))))
(setq i (+ i (max .1 (/ 1.0 mouse-avoidance-nudge-dist))))
(if (eq mouse-avoidance-mode 'proteus)
- (mouse-avoidance-set-pointer-shape
+ (mouse-avoidance-set-pointer-shape
(mouse-avoidance-random-shape)))
(sit-for mouse-avoidance-animation-delay)))
(mouse-avoidance-set-mouse-position (cons (+ (car (cdr cur)) deltax)
(if (null mouse-avoidance-pointer-shapes)
(progn
(setq mouse-avoidance-pointer-shapes
- (mapcar '(lambda (x) (symbol-value (intern x)))
+ (mapcar (lambda (x) (symbol-value (intern x)))
(all-completions "x-pointer-" obarray
- '(lambda (x)
+ (lambda (x)
(and (boundp x)
(integerp (symbol-value x)))))))
- (setq mouse-avoidance-n-pointer-shapes
+ (setq mouse-avoidance-n-pointer-shapes
(length mouse-avoidance-pointer-shapes))))
(nth (random mouse-avoidance-n-pointer-shapes)
mouse-avoidance-pointer-shapes))
(defun mouse-avoidance-banish-hook ()
(if (and (not executing-kbd-macro) ; don't check inside macro
- (mouse-avoidance-kbd-command (this-command-keys)))
+ (cadr (mouse-position)) ; don't move unless in an Emacs frame
+ ;; Don't do anything if last event was a mouse event.
+ (not (and (consp last-input-event)
+ (symbolp (car last-input-event))
+ (let ((modifiers (event-modifiers (car last-input-event))))
+ (or (memq (car last-input-event)
+ '(mouse-movement scroll-bar-movement))
+ (memq 'click modifiers)
+ (memq 'drag modifiers)
+ (memq 'down modifiers))))))
(mouse-avoidance-banish-mouse)))
(defun mouse-avoidance-exile-hook ()
;; For exile mode, the state is nil when the mouse is in its normal
;; position, and set to the old mouse-position when the mouse is in exile.
(if (and (not executing-kbd-macro)
- (mouse-avoidance-kbd-command (this-command-keys)))
+ ;; Don't do anything if last event was a mouse event.
+ (not (and (consp last-input-event)
+ (symbolp (car last-input-event))
+ (let ((modifiers (event-modifiers (car last-input-event))))
+ (or (memq (car last-input-event)
+ '(mouse-movement scroll-bar-movement))
+ (memq 'click modifiers)
+ (memq 'drag modifiers)
+ (memq 'down modifiers))))))
(let ((mp (mouse-position)))
(cond ((and (not mouse-avoidance-state)
(mouse-avoidance-too-close-p mp))
(defun mouse-avoidance-fancy-hook ()
;; Used for the "fancy" modes, ie jump et al.
(if (and (not executing-kbd-macro) ; don't check inside macro
- (mouse-avoidance-kbd-command (this-command-keys))
+ ;; Don't do anything if last event was a mouse event.
+ (not (and (consp last-input-event)
+ (symbolp (car last-input-event))
+ (let ((modifiers (event-modifiers (car last-input-event))))
+ (or (memq (car last-input-event)
+ '(mouse-movement scroll-bar-movement))
+ (memq 'click modifiers)
+ (memq 'drag modifiers)
+ (memq 'down modifiers)))))
(mouse-avoidance-too-close-p (mouse-position)))
(let ((old-pos (mouse-position)))
(mouse-avoidance-nudge-mouse)
;; This should never happen.
(apply 'set-mouse-position old-pos)))))
-(defun mouse-avoidance-kbd-command (key)
- "Return t if the KEYSEQENCE is composed of keyboard events only.
-Return nil if there are any lists in the key sequence."
- (cond ((null key) nil) ; Null event seems to be
- ; returned occasionally.
- ((not (vectorp key)) t) ; Strings are keyboard events.
- ((catch 'done
- (let ((i 0)
- (l (length key)))
- (while (< i l)
- (if (listp (aref key i))
- (throw 'done nil))
- (setq i (1+ i))))
- t))))
-
;;;###autoload
(defun mouse-avoidance-mode (&optional mode)
"Set cursor avoidance mode to MODE.
MODE should be one of the symbols `banish', `exile', `jump', `animate',
`cat-and-mouse', `proteus', or `none'.
-If MODE is nil, toggle mouse avoidance between `none` and `banish'
+If MODE is nil, toggle mouse avoidance between `none' and `banish'
modes. Positive numbers and symbols other than the above are treated
as equivalent to `banish'; negative numbers and `-' are equivalent to `none'.
-Effects of the different modes:
+Effects of the different modes:
* banish: Move the mouse to the upper-right corner on any keypress.
* exile: Move the mouse to the corner only if the cursor gets too close,
and allow it to return once the cursor is out of the way.
nil t))))
(if (eq mode 'cat-and-mouse)
(setq mode 'animate))
- (remove-hook 'post-command-idle-hook 'mouse-avoidance-banish-hook)
- (remove-hook 'post-command-idle-hook 'mouse-avoidance-exile-hook)
- (remove-hook 'post-command-idle-hook 'mouse-avoidance-fancy-hook)
+ (if mouse-avoidance-timer
+ (cancel-timer mouse-avoidance-timer))
+ (setq mouse-avoidance-timer nil)
;; Restore pointer shape if necessary
(if (eq mouse-avoidance-mode 'proteus)
((or (eq mode 'jump)
(eq mode 'animate)
(eq mode 'proteus))
- (add-hook 'post-command-idle-hook 'mouse-avoidance-fancy-hook)
+ (setq mouse-avoidance-timer
+ (run-with-idle-timer 0.1 t 'mouse-avoidance-fancy-hook))
(setq mouse-avoidance-mode mode
mouse-avoidance-state (cons 0 0)
mouse-avoidance-old-pointer-shape x-pointer-shape))
((eq mode 'exile)
- (add-hook 'post-command-idle-hook 'mouse-avoidance-exile-hook)
+ (setq mouse-avoidance-timer
+ (run-with-idle-timer 0.1 t 'mouse-avoidance-exile-hook))
(setq mouse-avoidance-mode mode
mouse-avoidance-state nil))
- ((or (eq mode 'banish)
+ ((or (eq mode 'banish)
(eq mode t)
(and (null mode) (null mouse-avoidance-mode))
(and mode (> (prefix-numeric-value mode) 0)))
- (add-hook 'post-command-idle-hook 'mouse-avoidance-banish-hook)
+ (setq mouse-avoidance-timer
+ (run-with-idle-timer 0.1 t 'mouse-avoidance-banish-hook))
(setq mouse-avoidance-mode 'banish))
(t (setq mouse-avoidance-mode nil)))
(force-mode-line-update))
;; (setq minor-mode-alist (cons '(mouse-avoidance-mode " Avoid")
;; minor-mode-alist)))
-;;; End of avoid.el
+;; Needed for custom.
+(if mouse-avoidance-mode
+ (mouse-avoidance-mode mouse-avoidance-mode))
+
+;;; avoid.el ends here