]> code.delx.au - gnu-emacs/blobdiff - lisp/frame.el
* lisp/simple.el (save-mark-and-excursion): Add declare forms.
[gnu-emacs] / lisp / frame.el
index ffa01b4dcc158ae125e923e8c09f95706ac60367..09738d1e2ed4d9c123d27fa96f3ea53b671b3781 100644 (file)
@@ -1,6 +1,6 @@
 ;;; frame.el --- multi-frame management independent of window systems  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1993-1994, 1996-1997, 2000-2015 Free Software
+;; Copyright (C) 1993-1994, 1996-1997, 2000-2016 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -33,8 +33,12 @@ The window system startup file should add its frame creation
 function to this method, which should take an alist of parameters
 as its argument.")
 
-(cl-defmethod frame-creation-function (params
-                                       &context (window-system (eql nil)))
+(cl-generic-define-context-rewriter window-system (value)
+  ;; If `value' is a `consp', it's probably an old-style specializer,
+  ;; so just use it, and anyway `eql' isn't very useful on cons cells.
+  `(window-system ,(if (consp value) value `(eql ,value))))
+
+(cl-defmethod frame-creation-function (params &context (window-system nil))
   ;; It's tempting to get rid of tty-create-frame-with-faces and turn it into
   ;; this method (i.e. move this method to faces.el), but faces.el is loaded
   ;; much earlier from loadup.el (before cl-generic and even before
@@ -64,7 +68,7 @@ handles the corresponding kind of display.")
 You can set this in your init file; for example,
 
  (setq initial-frame-alist
-       '((top . 1) (left . 1) (width . 80) (height . 55)))
+       \\='((top . 1) (left . 1) (width . 80) (height . 55)))
 
 Parameters specified here supersede the values given in
 `default-frame-alist'.
@@ -99,7 +103,7 @@ initial minibuffer frame.
 You can set this in your init file; for example,
 
  (setq minibuffer-frame-alist
-       '((top . 1) (left . 1) (width . 80) (height . 2)))
+       \\='((top . 1) (left . 1) (width . 80) (height . 2)))
 
 It is not necessary to include (minibuffer . only); that is
 appended when the minibuffer frame is created."
@@ -461,7 +465,7 @@ there (in decreasing order of priority)."
                    (cons (1- (car frame-size-history))
                          (cons
                           (list frame-initial-frame
-                                "frame-notice-user-settings"
+                                "FRAME-NOTICE-USER"
                                 nil newparms)
                           (cdr frame-size-history)))))
 
@@ -702,7 +706,7 @@ the new frame according to its own rules."
     (when (numberp (car frame-size-history))
       (setq frame-size-history
            (cons (1- (car frame-size-history))
-                 (cons (list frame "make-frame")
+                 (cons (list frame "MAKE-FRAME")
                        (cdr frame-size-history)))))
 
     ;; We can run `window-configuration-change-hook' for this frame now.
@@ -907,7 +911,7 @@ 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))."
+e.g. (mapc \\='frame-set-background-mode (frame-list))."
   :group 'faces
   :set #'(lambda (var value)
           (set-default var value)
@@ -1312,6 +1316,157 @@ live frame and defaults to the selected one."
       (setq vertical default-frame-scroll-bars))
     (cons vertical (and horizontal 'bottom))))
 
+(declare-function x-frame-geometry "xfns.c" (&optional frame))
+(declare-function w32-frame-geometry "w32fns.c" (&optional frame))
+(declare-function ns-frame-geometry "nsfns.m" (&optional frame))
+
+(defun frame-geometry (&optional frame)
+  "Return geometric attributes of FRAME.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is an association list of the attributes listed below.  All height
+and width values are in pixels.
+
+`outer-position' is a cons of the outer left and top edges of FRAME
+  relative to the origin - the position (0, 0) - of FRAME's display.
+
+`outer-size' is a cons of the outer width and height of FRAME.  The
+  outer size includes the title bar and the external borders as well as
+  any menu and/or tool bar of frame.
+
+`external-border-size' is a cons of the horizontal and vertical width of
+  FRAME's external borders as supplied by the window manager.
+
+`title-bar-size' is a cons of the width and height of the title bar of
+  FRAME as supplied by the window manager.  If both of them are zero,
+  FRAME has no title bar.  If only the width is zero, Emacs was not
+  able to retrieve the width information.
+
+`menu-bar-external', if non-nil, means the menu bar is external (never
+  included in the inner edges of FRAME).
+
+`menu-bar-size' is a cons of the width and height of the menu bar of
+  FRAME.
+
+`tool-bar-external', if non-nil, means the tool bar is external (never
+  included in the inner edges of FRAME).
+
+`tool-bar-position' tells on which side the tool bar on FRAME is and can
+  be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
+  has no tool bar.
+
+`tool-bar-size' is a cons of the width and height of the tool bar of
+  FRAME.
+
+`internal-border-width' is the width of the internal border of
+  FRAME."
+  (let* ((frame (window-normalize-frame frame))
+        (frame-type (framep-on-display frame)))
+    (cond
+     ((eq frame-type 'x)
+      (x-frame-geometry frame))
+     ((eq frame-type 'w32)
+      (w32-frame-geometry frame))
+     ((eq frame-type 'ns)
+      (ns-frame-geometry frame))
+     (t
+      (list
+       '(outer-position 0 . 0)
+       (cons 'outer-size (cons (frame-width frame) (frame-height frame)))
+       '(external-border-size 0 . 0)
+       '(title-bar-size 0 . 0)
+       '(menu-bar-external . nil)
+       (let ((menu-bar-lines (frame-parameter frame 'menu-bar-lines)))
+        (cons 'menu-bar-size
+              (if menu-bar-lines
+                  (cons (frame-width frame) 1)
+                1 0)))
+       '(tool-bar-external . nil)
+       '(tool-bar-position . nil)
+       '(tool-bar-size 0 . 0)
+       (cons 'internal-border-width
+            (frame-parameter frame 'internal-border-width)))))))
+
+(defun frame--size-history (&optional frame)
+  "Print history of resize operations for FRAME.
+Print prettified version of `frame-size-history' into a buffer
+called *frame-size-history*.  Optional argument FRAME denotes the
+frame whose history will be printed.  FRAME defaults to the
+selected frame."
+  (let ((history (reverse frame-size-history))
+       entry)
+    (setq frame (window-normalize-frame frame))
+    (with-current-buffer (get-buffer-create "*frame-size-history*")
+      (erase-buffer)
+      (insert (format "Frame size history of %s\n" frame))
+      (while (listp (setq entry (pop history)))
+       (when (eq (car entry) frame)
+          (pop entry)
+          (insert (format "%s" (pop entry)))
+          (move-to-column 24 t)
+          (while entry
+            (insert (format " %s" (pop entry))))
+          (insert "\n"))))))
+
+(declare-function x-frame-edges "xfns.c" (&optional frame type))
+(declare-function w32-frame-edges "w32fns.c" (&optional frame type))
+(declare-function ns-frame-edges "nsfns.m" (&optional frame type))
+
+(defun frame-edges (&optional frame type)
+  "Return coordinates of FRAME's edges.
+FRAME must be a live frame and defaults to the selected one.  The
+list returned has the form (LEFT TOP RIGHT BOTTOM) where all
+values are in pixels relative to the origin - the position (0, 0)
+- of FRAME's display.  For terminal frames all values are
+relative to LEFT and TOP which are both zero.
+
+Optional argument TYPE specifies the type of the edges.  TYPE
+`outer-edges' means to return the outer edges of FRAME.  TYPE
+`native-edges' (or nil) means to return the native edges of
+FRAME.  TYPE `inner-edges' means to return the inner edges of
+FRAME."
+  (let* ((frame (window-normalize-frame frame))
+        (frame-type (framep-on-display frame)))
+    (cond
+     ((eq frame-type 'x)
+      (x-frame-edges frame type))
+     ((eq frame-type 'w32)
+      (w32-frame-edges frame type))
+     ((eq frame-type 'ns)
+      (ns-frame-edges frame type))
+     (t
+      (list 0 0 (frame-width frame) (frame-height frame))))))
+
+(declare-function w32-mouse-absolute-pixel-position "w32fns.c")
+(declare-function x-mouse-absolute-pixel-position "xfns.c")
+
+(defun mouse-absolute-pixel-position ()
+  "Return absolute position of mouse cursor in pixels.
+The position is returned as a cons cell (X . Y) of the
+coordinates of the mouse cursor position in pixels relative to a
+position (0, 0) of the selected frame's terminal."
+  (let ((frame-type (framep-on-display)))
+    (cond
+     ((eq frame-type 'x)
+      (x-mouse-absolute-pixel-position))
+     ((eq frame-type 'w32)
+      (w32-mouse-absolute-pixel-position))
+     (t
+      (cons 0 0)))))
+
+(declare-function w32-set-mouse-absolute-pixel-position "w32fns.c" (x y))
+(declare-function x-set-mouse-absolute-pixel-position "xfns.c" (x y))
+
+(defun set-mouse-absolute-pixel-position (x y)
+  "Move mouse pointer to absolute pixel position (X, Y).
+The coordinates X and Y are interpreted in pixels relative to a
+position (0, 0) of the selected frame's terminal."
+  (let ((frame-type (framep-on-display)))
+    (cond
+     ((eq frame-type 'x)
+      (x-set-mouse-absolute-pixel-position x y))
+     ((eq frame-type 'w32)
+      (w32-set-mouse-absolute-pixel-position x y)))))
+
 (defun frame-monitor-attributes (&optional frame)
   "Return the attributes of the physical monitor dominating FRAME.
 If FRAME is omitted or nil, describe the currently selected frame.
@@ -1756,47 +1911,29 @@ left untouched.  FRAME nil or omitted means use the selected frame."
   :group 'frames
   :group 'windows)
 
-(defvar frame--window-divider-previous-mode nil
-  "Previous value of `window-divider-mode'.
-This is the value seen when `window-divider-mode' was switched
-off the last time.  It's reused when `window-divider-mode' is
-switched on again.")
-
-(defcustom window-divider-mode nil
-  "Specify whether to display window dividers and where.
-Possible values are nil (no dividers), `bottom-only' (dividers on
-the bottom of each window only), `right-only' (dividers on the
-right of each window only), and t (dividers on the bottom and on
-the right of each window)."
-  :type '(choice (const :tag "None (nil)" nil)
-                (const :tag "Bottom only" bottom-only)
+(defcustom window-divider-default-places 'right-only
+  "Default positions of window dividers.
+Possible values are `bottom-only' (dividers on the bottom of each
+window only), `right-only' (dividers on the right of each window
+only), and t (dividers on the bottom and on the right of each
+window).  The default is `right-only'.
+
+The value takes effect if and only if dividers are enabled by
+`window-divider-mode'.
+
+To position dividers on frames individually, use the frame
+parameters `bottom-divider-width' and `right-divider-width'."
+  :type '(choice (const :tag "Bottom only" bottom-only)
                 (const :tag "Right only" right-only)
                 (const :tag "Bottom and right" t))
   :initialize 'custom-initialize-default
-  :set (lambda (_symbol value)
-         (frame--window-divider-mode-set-and-apply value))
-  :group 'window-divider
+  :set (lambda (symbol value)
+        (set-default symbol value)
+         (when window-divider-mode
+           (window-divider-mode-apply t)))
   :version "25.1")
 
-(define-minor-mode window-divider-mode
-  "Display dividers between windows (Window Divider mode).
-With a prefix argument ARG, enable Window Divider mode if ARG is
-positive, and disable it otherwise.  If called from Lisp, enable
-the mode if ARG is omitted or nil.
-
-The option `window-divider-default-width' allows to customize the
-width of dividers displayed by this mode."
-  :group 'window-divider
-  :global t
-  :variable (window-divider-mode
-             . (lambda (value)
-                 (frame--window-divider-mode-set-and-apply
-                  (and value
-                       (or frame--window-divider-previous-mode
-                           (default-value 'window-divider-mode)
-                           'right-only))))))
-
-(defun frame-window-divider-width-valid-p (value)
+(defun window-divider-width-valid-p (value)
   "Return non-nil if VALUE is a positive number."
   (and (numberp value) (> value 0)))
 
@@ -1808,14 +1945,13 @@ dividers are displayed by `window-divider-mode'.
 To adjust bottom dividers for frames individually, use the frame
 parameter `bottom-divider-width'."
   :type '(restricted-sexp
-          :tag "Default bottom divider width"
+          :tag "Default width of bottom dividers"
           :match-alternatives (frame-window-divider-width-valid-p))
-  :group 'window-divider
   :initialize 'custom-initialize-default
   :set (lambda (symbol value)
         (set-default symbol value)
-        (when window-divider-mode
-           (frame--window-divider-mode-apply)))
+         (when window-divider-mode
+           (window-divider-mode-apply t)))
   :version "25.1")
 
 (defcustom window-divider-default-right-width 6
@@ -1826,22 +1962,27 @@ dividers are displayed by `window-divider-mode'.
 To adjust right dividers for frames individually, use the frame
 parameter `right-divider-width'."
   :type '(restricted-sexp
-          :tag "Default right divider width"
+          :tag "Default width of right dividers"
           :match-alternatives (frame-window-divider-width-valid-p))
-  :group 'window-divider
   :initialize 'custom-initialize-default
   :set (lambda (symbol value)
         (set-default symbol value)
-        (when window-divider-mode
-          (frame--window-divider-mode-apply)))
+         (when window-divider-mode
+          (window-divider-mode-apply t)))
   :version "25.1")
 
-(defun frame--window-divider-mode-apply ()
-  "Apply window divider widths."
-  (let ((bottom (if (memq window-divider-mode '(bottom-only t))
+(defun window-divider-mode-apply (enable)
+  "Apply window divider places and widths to all frames.
+If ENABLE is nil, apply default places and widths.  Else reset
+all divider widths to zero."
+  (let ((bottom (if (and enable
+                         (memq window-divider-default-places
+                               '(bottom-only t)))
                     window-divider-default-bottom-width
                   0))
-        (right (if (memq window-divider-mode '(right-only t))
+        (right (if (and enable
+                        (memq window-divider-default-places
+                              '(right-only t)))
                    window-divider-default-right-width
                  0)))
     (modify-all-frames-parameters
@@ -1864,18 +2005,20 @@ parameter `right-divider-width'."
              (cons 'right-divider-width right)
              default-frame-alist)))))
 
-(defun frame--window-divider-mode-set-and-apply (value)
-  "Set window divider mode to VALUE and apply widths."
-  (unless value
-    ;; Remember current mode.
-    (setq frame--window-divider-previous-mode window-divider-mode))
-  (set-default 'window-divider-mode value)
-  ;; Pacify customize rigmarole.
-  (put 'window-divider-mode 'customized-value
-       (if (memq value '(nil t))
-           (list value)
-         (list (list 'quote value))))
-  (frame--window-divider-mode-apply))
+(define-minor-mode window-divider-mode
+  "Display dividers between windows (Window Divider mode).
+With a prefix argument ARG, enable Window Divider mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+The option `window-divider-default-places' specifies on which
+side of a window dividers are displayed.  The options
+`window-divider-default-bottom-width' and
+`window-divider-default-right-width' specify their respective
+widths."
+  :group 'window-divider
+  :global t
+  (window-divider-mode-apply window-divider-mode))
 \f
 ;; Blinking cursor
 
@@ -2088,6 +2231,18 @@ See also `toggle-frame-maximized'."
 (make-obsolete-variable
  'window-system-version "it does not give useful information." "24.3")
 
+;; Variables which should trigger redisplay of the current buffer.
+(setq redisplay--variables (make-hash-table :test 'eq :size 10))
+(mapc (lambda (var)
+        (puthash var 1 redisplay--variables))
+      '(line-spacing
+        overline-margin
+        line-prefix
+        wrap-prefix
+        truncate-lines
+        bidi-paragraph-direction
+        bidi-display-reordering))
+
 (provide 'frame)
 
 ;;; frame.el ends here