]> code.delx.au - gnu-emacs/blobdiff - lisp/frame.el
* lisp/simple.el (command-execute): Respect nil disabled-command-function.
[gnu-emacs] / lisp / frame.el
index 1ee9d966ef1da4e440695549bad87dc2c0cc4255..7b0a0a80082ddd79e2795f308cf1a1358a5d07fc 100644 (file)
@@ -1,9 +1,9 @@
 ;;; frame.el --- multi-frame management independent of window systems
 
-;; Copyright (C) 1993-1994, 1996-1997, 2000-2012
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 1996-1997, 2000-2014 Free Software
+;; Foundation, Inc.
 
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
 ;; Package: emacs
 
@@ -25,7 +25,7 @@
 ;;; Commentary:
 
 ;;; Code:
-(eval-when-compile (require 'cl))
+(eval-when-compile (require 'cl-lib))
 
 (defvar frame-creation-function-alist
   (list (cons nil
@@ -47,6 +47,12 @@ Then, for frames on WINDOW-SYSTEM, any parameters specified in
 ALIST supersede the corresponding parameters specified in
 `default-frame-alist'.")
 
+(defvar display-format-alist nil
+  "Alist of patterns to decode display names.
+The car of each entry is a regular expression matching a display
+name string.  The cdr is a symbol giving the window-system that
+handles the corresponding kind of display.")
+
 ;; The initial value given here used to ask for a minibuffer.
 ;; But that's not necessary, because the default is to have one.
 ;; By not specifying it here, we let an X resource specify it.
@@ -114,6 +120,23 @@ appended when the minibuffer frame is created."
        (delete-frame frame t)
       ;; Gildea@x.org says it is ok to ask questions before terminating.
       (save-buffers-kill-emacs))))
+
+(defun handle-focus-in (_event)
+  "Handle a focus-in event.
+Focus-in events are usually bound to this function.
+Focus-in events occur when a frame has focus, but a switch-frame event
+is not generated.
+This function runs the hook `focus-in-hook'."
+  (interactive "e")
+  (run-hooks 'focus-in-hook))
+
+(defun handle-focus-out (_event)
+  "Handle a focus-out event.
+Focus-out events are usually bound to this function.
+Focus-out events occur when no frame has focus.
+This function runs the hook `focus-out-hook'."
+  (interactive "e")
+  (run-hooks 'focus-out-hook))
 \f
 ;;;; Arrangement of frames at startup
 
@@ -187,6 +210,8 @@ appended when the minibuffer frame is created."
 
 (declare-function tool-bar-mode "tool-bar" (&optional arg))
 
+(defalias 'tool-bar-lines-needed 'tool-bar-height)
+
 ;; startup.el calls this function after loading the user's init
 ;; file.  Now default-frame-alist and initial-frame-alist contain
 ;; information to which we must react; do what needs to be done.
@@ -303,7 +328,7 @@ there (in decreasing order of priority)."
       ;; existing frame.  We need to explicitly include
       ;; default-frame-alist in the parameters of the screen we
       ;; create here, so that its new value, gleaned from the user's
-      ;; .emacs file, will be applied to the existing screen.
+      ;; init file, will be applied to the existing screen.
       (if (not (eq (cdr (or (assq 'minibuffer initial-frame-alist)
                            (assq 'minibuffer window-system-frame-alist)
                            (assq 'minibuffer default-frame-alist)
@@ -311,6 +336,9 @@ there (in decreasing order of priority)."
                   t))
          ;; Create the new frame.
          (let (parms new)
+           ;; MS-Windows needs this to avoid inflooping below.
+           (if (eq system-type 'windows-nt)
+               (sit-for 0 t))
            ;; If the frame isn't visible yet, wait till it is.
            ;; If the user has to position the window,
            ;; Emacs doesn't know its real position until
@@ -491,10 +519,7 @@ See help of `modify-frame-parameters' for more information."
   "Return some frame other than the current frame.
 Create one if necessary.  Note that the minibuffer frame, if separate,
 is not considered (see `next-frame')."
-  (let ((s (if (equal (next-frame (selected-frame)) (selected-frame))
-              (make-frame)
-            (next-frame (selected-frame)))))
-    s))
+  (if (equal (next-frame) (selected-frame)) (make-frame) (next-frame)))
 
 (defun next-multiframe-window ()
   "Select the next window, regardless of which frame it is on."
@@ -512,31 +537,23 @@ is not considered (see `next-frame')."
                                  0))
   (select-frame-set-input-focus (selected-frame)))
 
-(declare-function x-initialize-window-system "term/x-win" ())
-(declare-function ns-initialize-window-system "term/ns-win" ())
-(defvar x-display-name)                 ; term/x-win
+(defun window-system-for-display (display)
+  "Return the window system for DISPLAY.
+Return nil if we don't know how to interpret DISPLAY."
+  ;; MS-Windows doesn't know how to create a GUI frame in a -nw session.
+  (if (and (eq system-type 'windows-nt)
+          (null (window-system)))
+      nil
+    (cl-loop for descriptor in display-format-alist
+            for pattern = (car descriptor)
+            for system = (cdr descriptor)
+            when (string-match-p pattern display) return system)))
 
 (defun make-frame-on-display (display &optional parameters)
   "Make a frame on display DISPLAY.
 The optional argument PARAMETERS specifies additional frame parameters."
   (interactive "sMake frame on display: ")
-  (cond ((featurep 'ns)
-        (when (and (boundp 'ns-initialized) (not ns-initialized))
-          (setq x-display-name display)
-          (ns-initialize-window-system))
-        (make-frame `((window-system . ns)
-                      (display . ,display) . ,parameters)))
-       ((eq system-type 'windows-nt)
-        ;; On Windows, ignore DISPLAY.
-        (make-frame parameters))
-       (t
-        (unless (string-match-p "\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'" display)
-          (error "Invalid display, not HOST:SERVER or HOST:SERVER.SCREEN"))
-        (when (and (boundp 'x-initialized) (not x-initialized))
-          (setq x-display-name display)
-          (x-initialize-window-system))
-        (make-frame `((window-system . x)
-                      (display . ,display) . ,parameters)))))
+  (make-frame (cons (cons 'display display) parameters)))
 
 (declare-function x-close-connection "xfns.c" (terminal))
 
@@ -593,9 +610,10 @@ The functions are run with one arg, the newly created frame.")
 (define-obsolete-function-alias 'new-frame 'make-frame "22.1")
 
 (defvar frame-inherited-parameters '()
-  ;; FIXME: Shouldn't we add `font' here as well?
   "Parameters `make-frame' copies from the `selected-frame' to the new frame.")
 
+(defvar x-display-name)
+
 (defun make-frame (&optional parameters)
   "Return a newly created frame displaying the current buffer.
 Optional argument PARAMETERS is an alist of frame parameters for
@@ -618,6 +636,8 @@ neither or both.
  (window-system . nil) The frame should be displayed on a terminal device.
  (window-system . x)   The frame should be displayed in an X window.
 
+ (display . \":0\")     The frame should appear on display :0.
+
  (terminal . TERMINAL)  The frame should use the terminal object TERMINAL.
 
 In addition, any parameter specified in `default-frame-alist',
@@ -628,11 +648,15 @@ this function runs the hook `before-make-frame-hook'.  After
 creating the frame, it runs the hook `after-make-frame-functions'
 with one arg, the newly created frame.
 
+If a display parameter is supplied and a window-system is not,
+guess the window-system from the display.
+
 On graphical displays, this function does not itself make the new
 frame the selected frame.  However, the window system may select
 the new frame according to its own rules."
   (interactive)
-  (let* ((w (cond
+  (let* ((display (cdr (assq 'display parameters)))
+         (w (cond
             ((assq 'terminal parameters)
              (let ((type (terminal-live-p (cdr (assq 'terminal parameters)))))
                (cond
@@ -642,6 +666,10 @@ the new frame according to its own rules."
                 (t type))))
             ((assq 'window-system parameters)
              (cdr (assq 'window-system parameters)))
+             (display
+              (or (window-system-for-display display)
+                  (error "Don't know how to interpret display %S"
+                         display)))
             (t window-system)))
         (frame-creation-function (cdr (assq w frame-creation-function-alist)))
         (oldframe (selected-frame))
@@ -649,6 +677,12 @@ the new frame according to its own rules."
         frame)
     (unless frame-creation-function
       (error "Don't know how to create a frame on window system %s" w))
+
+    (unless (get w 'window-system-initialized)
+      (funcall (cdr (assq w window-system-initialization-alist)) display)
+      (setq x-display-name display)
+      (put w 'window-system-initialized t))
+
     ;; Add parameters from `window-system-default-frame-alist'.
     (dolist (p (cdr (assq w window-system-default-frame-alist)))
       (unless (assq (car p) params)
@@ -749,7 +783,7 @@ the user during startup."
        (nreverse frame-initial-geometry-arguments))
   (cdr param-list))
 
-(declare-function x-focus-frame "xfns.c" (frame))
+(declare-function x-focus-frame "frame.c" (frame))
 
 (defun select-frame-set-input-focus (frame &optional norecord)
   "Select FRAME, raise it, and set input focus, if possible.
@@ -862,8 +896,11 @@ If there is no frame by that name, signal an error."
   "The brightness of the background.
 Set this to the symbol `dark' if your background color is dark,
 `light' if your background is light, or nil (automatic by default)
-if you want Emacs to examine the brightness for you.  Don't set this
-variable with `setq'; this won't have the expected effect."
+if you want Emacs to examine the brightness for you.
+
+If you change this without using customize, you should use
+`frame-set-background-mode' to update existing frames;
+e.g. (mapc 'frame-set-background-mode (frame-list))."
   :group 'faces
   :set #'(lambda (var value)
           (set-default var value)
@@ -876,6 +913,9 @@ variable with `setq'; this won't have the expected effect."
 (declare-function x-get-resource "frame.c"
                  (attribute class &optional component subclass))
 
+;; Only used if window-system is not null.
+(declare-function x-display-grayscale-p "xfns.c" (&optional terminal))
+
 (defvar inhibit-frame-set-background-mode nil)
 
 (defun frame-set-background-mode (frame &optional keep-face-specs)
@@ -1053,10 +1093,12 @@ If FRAME is omitted, describe the currently selected frame."
 
 (define-obsolete-function-alias 'set-default-font 'set-frame-font "23.1")
 
-(defun set-frame-font (font-name &optional keep-size frames)
-  "Set the default font to FONT-NAME.
+(defun set-frame-font (font &optional keep-size frames)
+  "Set the default font to FONT.
 When called interactively, prompt for the name of a font, and use
-that font on the selected frame.
+that font on the selected frame.  When called from Lisp, FONT
+should be a font name (a string), a font object, font entity, or
+font spec.
 
 If KEEP-SIZE is nil, keep the number of frame lines and columns
 fixed.  If KEEP-SIZE is non-nil (or with a prefix argument), try
@@ -1078,7 +1120,7 @@ this session\", so that the font is applied to future frames."
                                  nil nil nil nil
                                  (frame-parameter nil 'font))))
      (list font current-prefix-arg nil)))
-  (when (stringp font-name)
+  (when (or (stringp font) (fontp font))
     (let* ((this-frame (selected-frame))
           ;; FRAMES nil means affect the selected frame.
           (frame-list (cond ((null frames)
@@ -1099,7 +1141,7 @@ this session\", so that the font is applied to future frames."
          ;; (:width, :weight, etc.) so reset them too (Bug#2476).
          (set-face-attribute 'default f
                              :width 'normal :weight 'normal
-                             :slant 'normal :font font-name)
+                             :slant 'normal :font font)
          (if keep-size
              (modify-frame-parameters
               f
@@ -1227,8 +1269,8 @@ often have their own features for raising or lowering frames."
 (defun set-frame-name (name)
   "Set the name of the selected frame to NAME.
 When called interactively, prompt for the name of the frame.
-The frame name is displayed on the modeline if the terminal displays only
-one frame, otherwise the name is displayed on the frame's caption bar."
+On text terminals, the frame name is displayed on the mode line.
+On graphical displays, it is displayed on the frame's title bar."
   (interactive "sFrame name: ")
   (modify-frame-parameters (selected-frame)
                           (list (cons 'name name))))
@@ -1244,11 +1286,25 @@ bars (top, bottom, or nil)."
     (unless (memq vert '(left right nil))
       (setq vert default-frame-scroll-bars))
     (cons vert hor)))
+
+(defun frame-monitor-attributes (&optional frame)
+  "Return the attributes of the physical monitor dominating FRAME.
+If FRAME is omitted, describe the currently selected frame.
+
+A frame is dominated by a physical monitor when either the
+largest area of the frame resides in the monitor, or the monitor
+is the closest to the frame if the frame does not intersect any
+physical monitors.
+
+See `display-monitor-attributes-list' for the list of attribute
+keys and their meanings."
+  (or frame (setq frame (selected-frame)))
+  (cl-loop for attributes in (display-monitor-attributes-list frame)
+          for frames = (cdr (assq 'frames attributes))
+          if (memq frame frames) return attributes))
+
 \f
 ;;;; Frame/display capabilities.
-(defun selected-terminal ()
-  "Return the terminal that is now selected."
-  (frame-terminal (selected-frame)))
 
 (declare-function msdos-mouse-p "dosfns.c")
 
@@ -1260,7 +1316,7 @@ frame's display)."
     (cond
      ((eq frame-type 'pc)
       (msdos-mouse-p))
-     ((eq system-type 'windows-nt)
+     ((eq frame-type 'w32)
       (with-no-warnings
        (> w32-num-mouse-buttons 0)))
      ((memq frame-type '(x ns))
@@ -1270,17 +1326,17 @@ frame's display)."
               xterm-mouse-mode)
          ;; t-mouse is distributed with the GPM package.  It doesn't have
          ;; a toggle.
-         (featurep 't-mouse))))))
+         (featurep 't-mouse)
+         ;; No way to check whether a w32 console has a mouse, assume
+         ;; it always does.
+         (boundp 'w32-use-full-screen-buffer))))))
 
 (defun display-popup-menus-p (&optional display)
   "Return non-nil if popup menus are supported on DISPLAY.
 DISPLAY can be a display name, a frame, or nil (meaning the selected
 frame's display).
 Support for popup menus requires that the mouse be available."
-  (and
-   (let ((frame-type (framep-on-display display)))
-     (memq frame-type '(x w32 pc ns)))
-   (display-mouse-p display)))
+  (display-mouse-p display))
 
 (defun display-graphic-p (&optional display)
   "Return non-nil if DISPLAY is a graphic display.
@@ -1317,14 +1373,15 @@ frame's display)."
       (with-no-warnings
        (not (null dos-windows-version))))
      ((memq frame-type '(x w32 ns))
-      t)    ;; FIXME?
+      t)
      (t
       nil))))
 
 (declare-function x-display-screens "xfns.c" (&optional terminal))
 
 (defun display-screens (&optional display)
-  "Return the number of screens associated with DISPLAY."
+  "Return the number of screens associated with DISPLAY.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1336,7 +1393,14 @@ frame's display)."
 
 (defun display-pixel-height (&optional display)
   "Return the height of DISPLAY's screen in pixels.
-For character terminals, each character counts as a single pixel."
+If DISPLAY is omitted or nil, it defaults to the selected frame's display.
+
+For character terminals, each character counts as a single pixel.
+
+For graphical terminals, note that on \"multi-monitor\" setups this
+refers to the pixel height for all physical monitors associated
+with DISPLAY.  To get information for each physical monitor, use
+`display-monitor-attributes-list'."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1348,7 +1412,14 @@ For character terminals, each character counts as a single pixel."
 
 (defun display-pixel-width (&optional display)
   "Return the width of DISPLAY's screen in pixels.
-For character terminals, each character counts as a single pixel."
+If DISPLAY is omitted or nil, it defaults to the selected frame's display.
+
+For character terminals, each character counts as a single pixel.
+
+For graphical terminals, note that on \"multi-monitor\" setups this
+refers to the pixel width for all physical monitors associated
+with DISPLAY.  To get information for each physical monitor, use
+`display-monitor-attributes-list'."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1358,14 +1429,14 @@ For character terminals, each character counts as a single pixel."
 
 (defcustom display-mm-dimensions-alist nil
   "Alist for specifying screen dimensions in millimeters.
-The dimensions will be used for `display-mm-height' and
-`display-mm-width' if defined for the respective display.
+The functions `display-mm-height' and `display-mm-width' consult
+this list before asking the system.
 
-Each element of the alist has the form (display . (width . height)),
-e.g. (\":0.0\" . (287 . 215)).
+Each element has the form (DISPLAY . (WIDTH . HEIGHT)), e.g.
+\(\":0.0\" . (287 . 215)).
 
-If `display' equals t, it specifies dimensions for all graphical
-displays not explicitly specified."
+If `display' is t, it specifies dimensions for all graphical displays
+not explicitly specified."
   :version "22.1"
   :type '(alist :key-type (choice (string :tag "Display name")
                                  (const :tag "Default" t))
@@ -1378,8 +1449,16 @@ displays not explicitly specified."
 
 (defun display-mm-height (&optional display)
   "Return the height of DISPLAY's screen in millimeters.
-System values can be overridden by `display-mm-dimensions-alist'.
-If the information is unavailable, value is nil."
+If the information is unavailable, this function returns nil.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display.
+
+You can override what the system thinks the result should be by
+adding an entry to `display-mm-dimensions-alist'.
+
+For graphical terminals, note that on \"multi-monitor\" setups this
+refers to the height in millimeters for all physical monitors
+associated with DISPLAY.  To get information for each physical
+monitor, use `display-monitor-attributes-list'."
   (and (memq (framep-on-display display) '(x w32 ns))
        (or (cddr (assoc (or display (frame-parameter nil 'display))
                        display-mm-dimensions-alist))
@@ -1390,8 +1469,16 @@ If the information is unavailable, value is nil."
 
 (defun display-mm-width (&optional display)
   "Return the width of DISPLAY's screen in millimeters.
-System values can be overridden by `display-mm-dimensions-alist'.
-If the information is unavailable, value is nil."
+If the information is unavailable, this function returns nil.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display.
+
+You can override what the system thinks the result should be by
+adding an entry to `display-mm-dimensions-alist'.
+
+For graphical terminals, note that on \"multi-monitor\" setups this
+refers to the width in millimeters for all physical monitors
+associated with DISPLAY.  To get information for each physical
+monitor, use `display-monitor-attributes-list'."
   (and (memq (framep-on-display display) '(x w32 ns))
        (or (cadr (assoc (or display (frame-parameter nil 'display))
                        display-mm-dimensions-alist))
@@ -1400,10 +1487,13 @@ If the information is unavailable, value is nil."
 
 (declare-function x-display-backing-store "xfns.c" (&optional terminal))
 
+;; In NS port, the return value may be `buffered', `retained', or
+;; `non-retained'.  See src/nsfns.m.
 (defun display-backing-store (&optional display)
   "Return the backing store capability of DISPLAY's screen.
 The value may be `always', `when-mapped', `not-useful', or nil if
-the question is inapplicable to a certain kind of display."
+the question is inapplicable to a certain kind of display.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1414,7 +1504,8 @@ the question is inapplicable to a certain kind of display."
 (declare-function x-display-save-under "xfns.c" (&optional terminal))
 
 (defun display-save-under (&optional display)
-  "Return non-nil if DISPLAY's screen supports the SaveUnder feature."
+  "Return non-nil if DISPLAY's screen supports the SaveUnder feature.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1425,7 +1516,8 @@ the question is inapplicable to a certain kind of display."
 (declare-function x-display-planes "xfns.c" (&optional terminal))
 
 (defun display-planes (&optional display)
-  "Return the number of planes supported by DISPLAY."
+  "Return the number of planes supported by DISPLAY.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1438,7 +1530,8 @@ the question is inapplicable to a certain kind of display."
 (declare-function x-display-color-cells "xfns.c" (&optional terminal))
 
 (defun display-color-cells (&optional display)
-  "Return the number of color cells supported by DISPLAY."
+  "Return the number of color cells supported by DISPLAY.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1453,7 +1546,8 @@ the question is inapplicable to a certain kind of display."
 (defun display-visual-class (&optional display)
   "Return the visual class of DISPLAY.
 The value is one of the symbols `static-gray', `gray-scale',
-`static-color', `pseudo-color', `true-color', or `direct-color'."
+`static-color', `pseudo-color', `true-color', or `direct-color'.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display."
   (let ((frame-type (framep-on-display display)))
     (cond
      ((memq frame-type '(x w32 ns))
@@ -1464,6 +1558,59 @@ The value is one of the symbols `static-gray', `gray-scale',
      (t
       'static-gray))))
 
+(declare-function x-display-monitor-attributes-list "xfns.c"
+                 (&optional terminal))
+(declare-function w32-display-monitor-attributes-list "w32fns.c"
+                 (&optional display))
+(declare-function ns-display-monitor-attributes-list "nsfns.m"
+                 (&optional terminal))
+
+(defun display-monitor-attributes-list (&optional display)
+  "Return a list of physical monitor attributes on DISPLAY.
+Each element of the list represents the attributes of each
+physical monitor.  The first element corresponds to the primary
+monitor.
+
+Attributes for a physical monitor is represented as an alist of
+attribute keys and values as follows:
+
+ geometry -- Position and size in pixels in the form of
+            (X Y WIDTH HEIGHT)
+ workarea -- Position and size of the workarea in pixels in the
+            form of (X Y WIDTH HEIGHT)
+ mm-size  -- Width and height in millimeters in the form of
+            (WIDTH HEIGHT)
+ frames   -- List of frames dominated by the physical monitor
+ name (*) -- Name of the physical monitor as a string
+
+where X, Y, WIDTH, and HEIGHT are integers.  Keys labeled
+with (*) are optional.
+
+A frame is dominated by a physical monitor when either the
+largest area of the frame resides in the monitor, or the monitor
+is the closest to the frame if the frame does not intersect any
+physical monitors.  Every non-tip frame (including invisible one)
+in a graphical display is dominated by exactly one physical
+monitor at a time, though it can span multiple (or no) physical
+monitors.
+If DISPLAY is omitted or nil, it defaults to the selected frame's display."
+  (let ((frame-type (framep-on-display display)))
+    (cond
+     ((eq frame-type 'x)
+      (x-display-monitor-attributes-list display))
+     ((eq frame-type 'w32)
+      (w32-display-monitor-attributes-list display))
+     ((eq frame-type 'ns)
+      (ns-display-monitor-attributes-list display))
+     (t
+      (let ((geometry (list 0 0 (display-pixel-width display)
+                           (display-pixel-height display))))
+       `(((geometry . ,geometry)
+          (workarea . ,geometry)
+          (mm-size . (,(display-mm-width display)
+                      ,(display-mm-height display)))
+          (frames . ,(frames-on-display-list display)))))))))
+
 \f
 ;;;; Frame geometry values
 
@@ -1574,6 +1721,16 @@ left untouched.  FRAME nil or omitted means use the selected frame."
   :type 'number
   :group 'cursor)
 
+(defcustom blink-cursor-blinks 10
+  "How many times to blink before using a solid cursor on NS and X.
+Use 0 or negative value to blink forever."
+  :version "24.4"
+  :type 'integer
+  :group 'cursor)
+
+(defvar blink-cursor-blinks-done 1
+  "Number of blinks done since we started blinking on NS and X")
+
 (defvar blink-cursor-idle-timer nil
   "Timer started after `blink-cursor-delay' seconds of Emacs idle time.
 The function `blink-cursor-start' is called when the timer fires.")
@@ -1591,6 +1748,7 @@ command starts, by installing a pre-command hook."
   (when (null blink-cursor-timer)
     ;; Set up the timer first, so that if this signals an error,
     ;; blink-cursor-end is not added to pre-command-hook.
+    (setq blink-cursor-blinks-done 1)
     (setq blink-cursor-timer
          (run-with-timer blink-cursor-interval blink-cursor-interval
                          'blink-cursor-timer-function))
@@ -1599,7 +1757,14 @@ command starts, by installing a pre-command hook."
 
 (defun blink-cursor-timer-function ()
   "Timer function of timer `blink-cursor-timer'."
-  (internal-show-cursor nil (not (internal-show-cursor-p))))
+  (internal-show-cursor nil (not (internal-show-cursor-p)))
+  ;; Each blink is two calls to this function.
+  (setq blink-cursor-blinks-done (1+ blink-cursor-blinks-done))
+  (when (and (> blink-cursor-blinks 0)
+             (<= (* 2 blink-cursor-blinks) blink-cursor-blinks-done))
+    (blink-cursor-suspend)
+    (add-hook 'post-command-hook 'blink-cursor-check)))
+
 
 (defun blink-cursor-end ()
   "Stop cursor blinking.
@@ -1612,6 +1777,30 @@ itself as a pre-command hook."
     (cancel-timer blink-cursor-timer)
     (setq blink-cursor-timer nil)))
 
+(defun blink-cursor-suspend ()
+  "Suspend cursor blinking.
+This is called when no frame has focus and timers can be suspended.
+Timers are restarted by `blink-cursor-check', which is called when a
+frame receives focus."
+  (blink-cursor-end)
+  (when blink-cursor-idle-timer
+    (cancel-timer blink-cursor-idle-timer)
+    (setq blink-cursor-idle-timer nil)))
+
+(defun blink-cursor-check ()
+  "Check if cursor blinking shall be restarted.
+This is done when a frame gets focus.  Blink timers may be stopped by
+`blink-cursor-suspend'."
+  (when (and blink-cursor-mode
+            (not blink-cursor-idle-timer))
+    (remove-hook 'post-command-hook 'blink-cursor-check)
+    (setq blink-cursor-idle-timer
+          (run-with-idle-timer blink-cursor-delay
+                               blink-cursor-delay
+                               'blink-cursor-start))))
+
+(define-obsolete-variable-alias 'blink-cursor 'blink-cursor-mode "22.1")
+
 (define-minor-mode blink-cursor-mode
   "Toggle cursor blinking (Blink Cursor mode).
 With a prefix argument ARG, enable Blink Cursor mode if ARG is
@@ -1630,15 +1819,60 @@ terminals, cursor blinking is controlled by the terminal."
   (if blink-cursor-idle-timer (cancel-timer blink-cursor-idle-timer))
   (setq blink-cursor-idle-timer nil)
   (blink-cursor-end)
+  (remove-hook 'focus-in-hook #'blink-cursor-check)
+  (remove-hook 'focus-out-hook #'blink-cursor-suspend)
   (when blink-cursor-mode
-    ;; Hide the cursor.
-    ;;(internal-show-cursor nil nil)
+    (add-hook 'focus-in-hook #'blink-cursor-check)
+    (add-hook 'focus-out-hook #'blink-cursor-suspend)
     (setq blink-cursor-idle-timer
           (run-with-idle-timer blink-cursor-delay
                                blink-cursor-delay
-                               'blink-cursor-start))))
+                               #'blink-cursor-start))))
 
-(define-obsolete-variable-alias 'blink-cursor 'blink-cursor-mode "22.1")
+\f
+;; Frame maximization/fullscreen
+
+(defun toggle-frame-maximized ()
+  "Toggle maximization state of the selected frame.
+Maximize the selected frame or un-maximize if it is already maximized.
+Respect window manager screen decorations.
+If the frame is in fullscreen mode, don't change its mode,
+just toggle the temporary frame parameter `maximized',
+so the frame will go to the right maximization state
+after disabling fullscreen mode.
+See also `toggle-frame-fullscreen'."
+  (interactive)
+  (if (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
+      (modify-frame-parameters
+       nil
+       `((maximized
+         . ,(unless (eq (frame-parameter nil 'maximized) 'maximized)
+              'maximized))))
+    (modify-frame-parameters
+     nil
+     `((fullscreen
+       . ,(unless (eq (frame-parameter nil 'fullscreen) 'maximized)
+            'maximized))))))
+
+(defun toggle-frame-fullscreen ()
+  "Toggle fullscreen mode of the selected frame.
+Enable fullscreen mode of the selected frame or disable if it is
+already fullscreen.  Ignore window manager screen decorations.
+When turning on fullscreen mode, remember the previous value of the
+maximization state in the temporary frame parameter `maximized'.
+Restore the maximization state when turning off fullscreen mode.
+See also `toggle-frame-maximized'."
+  (interactive)
+  (modify-frame-parameters
+   nil
+   `((maximized
+      . ,(unless (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
+          (frame-parameter nil 'fullscreen)))
+     (fullscreen
+      . ,(if (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
+            (if (eq (frame-parameter nil 'maximized) 'maximized)
+                'maximized)
+          'fullscreen)))))
 
 \f
 ;;;; Key bindings
@@ -1647,15 +1881,23 @@ terminals, cursor blinking is controlled by the terminal."
 (define-key ctl-x-5-map "1" 'delete-other-frames)
 (define-key ctl-x-5-map "0" 'delete-frame)
 (define-key ctl-x-5-map "o" 'other-frame)
+(define-key global-map [f11] 'toggle-frame-fullscreen)
+(define-key global-map [(meta f10)] 'toggle-frame-maximized)
+(define-key esc-map    [f10]        'toggle-frame-maximized)
 
 \f
 ;; Misc.
 
-;; Only marked as obsolete in 24.2.
-(define-obsolete-variable-alias 'automatic-hscrolling 'auto-hscroll-mode "22.1")
+;; Only marked as obsolete in 24.3.
+(define-obsolete-variable-alias 'automatic-hscrolling
+  'auto-hscroll-mode "22.1")
 
 (make-variable-buffer-local 'show-trailing-whitespace)
 
+;; Defined in dispnew.c.
+(make-obsolete-variable
+ 'window-system-version "it does not give useful information." "24.3")
+
 (provide 'frame)
 
 ;;; frame.el ends here