]> code.delx.au - gnu-emacs/blobdiff - lisp/window.el
(defcustom, x-color-defined-p, cperl-is-face)
[gnu-emacs] / lisp / window.el
index 0c50bc63a08c931790e714104759bd2a3c7b54a3..7a64588c076c85a033f0cfe55e439a89e6dcf95c 100644 (file)
@@ -1,7 +1,7 @@
 ;;; window.el --- GNU Emacs window commands aside from those written in C
 
 ;; Copyright (C) 1985, 1989, 1992, 1993, 1994, 2000, 2001, 2002,
-;;   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;;   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: internal
@@ -10,7 +10,7 @@
 
 ;; 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,
@@ -120,7 +120,7 @@ bars (top, bottom, or nil)."
 PROC is called with a window as argument.
 
 Optional second arg MINIBUF t means count the minibuffer window even
-if not active.  MINIBUF nil or omitted means count the minibuffer iff
+if not active.  MINIBUF nil or omitted means count the minibuffer only if
 it is active.  MINIBUF neither t nor nil means not to count the
 minibuffer even if it is active.
 
@@ -165,7 +165,7 @@ value is returned.  If no window satisfies PREDICATE, DEFAULT is
 returned.
 
 Optional second arg MINIBUF t means count the minibuffer window even
-if not active.  MINIBUF nil or omitted means count the minibuffer iff
+if not active.  MINIBUF nil or omitted means count the minibuffer only if
 it is active.  MINIBUF neither t nor nil means not to count the
 minibuffer even if it is active.
 
@@ -719,17 +719,25 @@ or if the window is the only window of its frame."
   "Kill the current buffer and delete the selected window."
   (interactive)
   (let ((window-to-delete (selected-window))
+       (buffer-to-kill (current-buffer))
        (delete-window-hook (lambda ()
                              (condition-case nil
                                  (delete-window)
                                (error nil)))))
-    (add-hook 'kill-buffer-hook delete-window-hook t t)
-    (if (kill-buffer (current-buffer))
-       ;; If `delete-window' failed before, we rerun it to regenerate
-       ;; the error so it can be seen in the minibuffer.
-       (when (eq (selected-window) window-to-delete)
-         (delete-window))
-      (remove-hook 'kill-buffer-hook delete-window-hook t))))
+    (unwind-protect
+       (progn
+         (add-hook 'kill-buffer-hook delete-window-hook t t)
+         (if (kill-buffer (current-buffer))
+             ;; If `delete-window' failed before, we rerun it to regenerate
+             ;; the error so it can be seen in the echo area.
+             (when (eq (selected-window) window-to-delete)
+               (delete-window))))
+      ;; If the buffer is not dead for some reason (probably because
+      ;; of a `quit' signal), remove the hook again.
+      (condition-case nil
+         (with-current-buffer buffer-to-kill
+           (remove-hook 'kill-buffer-hook delete-window-hook t))
+       (error nil)))))
 
 (defun quit-window (&optional kill window)
   "Quit the current buffer.  Bury it, and maybe delete the selected frame.
@@ -787,8 +795,11 @@ and the buffer that is killed or buried is the one in that window."
 (defvar mouse-autoselect-window-window nil
   "Last window recorded by delayed window autoselection.")
 
-(defvar mouse-autoselect-window-now nil
-  "When non-nil don't delay autoselection in `handle-select-window'.")
+(defvar mouse-autoselect-window-state nil
+  "When non-nil, special state of delayed window autoselection.
+Possible values are `suspend' \(suspend autoselection after a menu or
+scrollbar interaction\) and `select' \(the next invocation of
+'handle-select-window' shall select the window immediately\).")
 
 (defun mouse-autoselect-window-cancel (&optional force)
   "Cancel delayed window autoselection.
@@ -798,69 +809,74 @@ Optional argument FORCE means cancel unconditionally."
               (eq this-command 'scroll-bar-toolkit-scroll)
               (memq (nth 4 (event-end last-input-event))
                     '(handle end-scroll)))
-    (setq mouse-autoselect-window-now nil)
+    (setq mouse-autoselect-window-state nil)
     (when (timerp mouse-autoselect-window-timer)
       (cancel-timer mouse-autoselect-window-timer))
     (remove-hook 'pre-command-hook 'mouse-autoselect-window-cancel)))
 
-(defun mouse-autoselect-window-start (window)
+(defun mouse-autoselect-window-start (mouse-position &optional window suspend)
   "Start delayed window autoselection.
-Called when Emacs detects that the mouse has moved to the non-selected
-window WINDOW and the variable `mouse-autoselect-window' has a numeric,
-non-zero value.  The return value is non-nil iff delayed autoselection
-started successfully.  Delayed window autoselection is canceled when the
-mouse position has stabilized or a command is executed."
-  ;; Cancel any active window autoselection.
-  (mouse-autoselect-window-cancel t)
-  ;; Record current mouse position in `mouse-autoselect-window-position' and
-  ;; WINDOW in `mouse-autoselect-window-window'.
-  (setq mouse-autoselect-window-position (mouse-position))
-  (setq mouse-autoselect-window-window window)
-  ;; Install timer which runs `mouse-autoselect-window-select' every
+MOUSE-POSITION is the last position where the mouse was seen as returned
+by `mouse-position'.  Optional argument WINDOW non-nil denotes the
+window where the mouse was seen.  Optional argument SUSPEND non-nil
+means suspend autoselection."
+  ;; Record values for MOUSE-POSITION, WINDOW, and SUSPEND.
+  (setq mouse-autoselect-window-position mouse-position)
+  (when window (setq mouse-autoselect-window-window window))
+  (setq mouse-autoselect-window-state (when suspend 'suspend))
+  ;; Install timer which runs `mouse-autoselect-window-select' after
   ;; `mouse-autoselect-window' seconds.
   (setq mouse-autoselect-window-timer
        (run-at-time
-        (abs mouse-autoselect-window) (abs mouse-autoselect-window)
-        'mouse-autoselect-window-select))
-  ;; Executing a command cancels window autoselection.
-  (add-hook 'pre-command-hook 'mouse-autoselect-window-cancel))
+        (abs mouse-autoselect-window) nil 'mouse-autoselect-window-select)))
 
 (defun mouse-autoselect-window-select ()
   "Select window with delayed window autoselection.
 If the mouse position has stabilized in a non-selected window, select
-that window.  The minibuffer window is selected iff the minibuffer is
+that window.  The minibuffer window is selected only if the minibuffer is
 active.  This function is run by `mouse-autoselect-window-timer'."
   (condition-case nil
       (let* ((mouse-position (mouse-position))
-            (window (window-at (cadr mouse-position) (cddr mouse-position)
-                               (car mouse-position))))
+            (window
+             (condition-case nil
+                 (window-at (cadr mouse-position) (cddr mouse-position)
+                            (car mouse-position))
+               (error nil))))
        (cond
+        ((or (menu-or-popup-active-p)
+             (and window
+                  (not (coordinates-in-window-p (cdr mouse-position) window))))
+         ;; A menu / popup dialog is active or the mouse is on the scroll-bar
+         ;; of WINDOW, temporarily suspend delayed autoselection.
+         (mouse-autoselect-window-start mouse-position nil t))
+        ((eq mouse-autoselect-window-state 'suspend)
+         ;; Delayed autoselection was temporarily suspended, reenable it.
+         (mouse-autoselect-window-start mouse-position))
         ((and window (not (eq window (selected-window)))
               (or (not (numberp mouse-autoselect-window))
                   (and (> mouse-autoselect-window 0)
                        ;; If `mouse-autoselect-window' is positive, select
                        ;; window if the window is the same as before.
                        (eq window mouse-autoselect-window-window))
-                  ;; Otherwise select window iff the mouse is at the same
+                  ;; Otherwise select window if the mouse is at the same
                   ;; position as before.  Observe that the first test after
-                  ;; `mouse-autoselect-window-start' usually fails since the
-                  ;; value of `mouse-autoselect-window-position' recorded there
-                  ;; is the position where the mouse has entered the new window
-                  ;; and not necessarily where the mouse has stopped moving.
+                  ;; starting autoselection usually fails since the value of
+                  ;; `mouse-autoselect-window-position' recorded there is the
+                  ;; position where the mouse has entered the new window and
+                  ;; not necessarily where the mouse has stopped moving.
                   (equal mouse-position mouse-autoselect-window-position))
-              ;; The minibuffer is a candidate window iff it's active.
+              ;; The minibuffer is a candidate window if it's active.
               (or (not (window-minibuffer-p window))
                   (eq window (active-minibuffer-window))))
-         ;; Mouse position has stabilized in non-selected window: Cancel window
-         ;; autoselection and try to select that window.
+         ;; Mouse position has stabilized in non-selected window: Cancel
+         ;; delayed autoselection and try to select that window.
          (mouse-autoselect-window-cancel t)
          ;; Select window where mouse appears unless the selected window is the
          ;; minibuffer.  Use `unread-command-events' in order to execute pre-
          ;; and post-command hooks and trigger idle timers.  To avoid delaying
-         ;; autoselection again, temporarily set `mouse-autoselect-window-now'
-         ;; to t.
+         ;; autoselection again, set `mouse-autoselect-window-state'."
          (unless (window-minibuffer-p (selected-window))
-           (setq mouse-autoselect-window-now t)
+           (setq mouse-autoselect-window-state 'select)
            (setq unread-command-events
                  (cons (list 'select-window (list window))
                        unread-command-events))))
@@ -868,14 +884,12 @@ active.  This function is run by `mouse-autoselect-window-timer'."
              (not (numberp mouse-autoselect-window))
              (equal mouse-position mouse-autoselect-window-position))
          ;; Mouse position has either stabilized in the selected window or at
-         ;; `mouse-autoselect-window-position': Cancel window autoselection.
+         ;; `mouse-autoselect-window-position': Cancel delayed autoselection.
          (mouse-autoselect-window-cancel t))
         (t
-         ;; Mouse position has not stabilized yet, record new mouse position in
-         ;; `mouse-autoselect-window-position' and any window at that position
-         ;; in `mouse-autoselect-window-window'.
-         (setq mouse-autoselect-window-position mouse-position)
-         (setq mouse-autoselect-window-window window))))
+         ;; Mouse position has not stabilized yet, resume delayed
+         ;; autoselection.
+         (mouse-autoselect-window-start mouse-position window))))
     (error nil)))
 
 (defun handle-select-window (event)
@@ -893,14 +907,18 @@ active.  This function is run by `mouse-autoselect-window-timer'."
                   (minibuffer-window-active-p window)))
       (unless (and (numberp mouse-autoselect-window)
                   (not (zerop mouse-autoselect-window))
-                  (not mouse-autoselect-window-now)
-                  ;; When `mouse-autoselect-window' has a numeric, non-zero
-                  ;; value, delay window autoselection by that value.
-                  ;; `mouse-autoselect-window-start' returns non-nil iff it
-                  ;; successfully installed a timer for this purpose.
-                  (mouse-autoselect-window-start window))
-       ;; Re-enable delayed window autoselection.
-       (setq mouse-autoselect-window-now nil)
+                  (not (eq mouse-autoselect-window-state 'select))
+                  (progn
+                    ;; Cancel any delayed autoselection.
+                    (mouse-autoselect-window-cancel t)
+                    ;; Start delayed autoselection from current mouse position
+                    ;; and window.
+                    (mouse-autoselect-window-start (mouse-position) window)
+                    ;; Executing a command cancels delayed autoselection.
+                    (add-hook
+                     'pre-command-hook 'mouse-autoselect-window-cancel)))
+       ;; Reset state of delayed autoselection.
+       (setq mouse-autoselect-window-state nil)
        (when mouse-autoselect-window
          ;; Run `mouse-leave-buffer-hook' when autoselecting window.
          (run-hooks 'mouse-leave-buffer-hook))