* configure.ac: Fix CC detection for xcrun case.
[bpt/emacs.git] / lisp / frame.el
CommitLineData
55535639 1;;; frame.el --- multi-frame management independent of window systems
c88ab9ce 2
ab422c4d
PE
3;; Copyright (C) 1993-1994, 1996-1997, 2000-2013 Free Software
4;; Foundation, Inc.
3a801d0c 5
fc68affa 6;; Maintainer: FSF
fd7fa35a 7;; Keywords: internal
bd78fa1d 8;; Package: emacs
fc68affa 9
b578f267
EN
10;; This file is part of GNU Emacs.
11
eb3fa2cf 12;; GNU Emacs is free software: you can redistribute it and/or modify
b578f267 13;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
b578f267
EN
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
eb3fa2cf 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
64c669bc 24
55535639
PJ
25;;; Commentary:
26
fc68affa 27;;; Code:
efc3dd3c
DC
28(eval-when-compile (require 'cl-lib))
29
2246281f
KL
30(defvar frame-creation-function-alist
31 (list (cons nil
32 (if (fboundp 'tty-create-frame-with-faces)
33 'tty-create-frame-with-faces
06b60517 34 (lambda (_parameters)
371fed4e 35 (error "Can't create multiple frames without a window system")))))
2246281f
KL
36 "Alist of window-system dependent functions to call to create a new frame.
37The window system startup file should add its frame creation
38function to this list, which should take an alist of parameters
39as its argument.")
114a8b8c 40
bf1ba39f 41(defvar window-system-default-frame-alist nil
5b95ee8a
CY
42 "Window-system dependent default frame parameters.
43The value should be an alist of elements (WINDOW-SYSTEM . ALIST),
44where WINDOW-SYSTEM is a window system symbol (see `window-system')
45and ALIST is a frame parameter alist like `default-frame-alist'.
46Then, for frames on WINDOW-SYSTEM, any parameters specified in
47ALIST supersede the corresponding parameters specified in
dca6c418 48`default-frame-alist'.")
bf1ba39f 49
efc3dd3c
DC
50(defvar display-format-alist nil
51 "Alist of patterns to decode display names.
52The car of each entry is a regular expression matching a display
53name string. The cdr is a symbol giving the window-system that
54handles the corresponding kind of display.")
55
7e573c4a
SM
56;; The initial value given here used to ask for a minibuffer.
57;; But that's not necessary, because the default is to have one.
58;; By not specifying it here, we let an X resource specify it.
fac580eb 59(defcustom initial-frame-alist nil
dca6c418
MR
60 "Alist of parameters for the initial X window frame.
61You can set this in your init file; for example,
62
63 (setq initial-frame-alist
64 '((top . 1) (left . 1) (width . 80) (height . 55)))
65
66Parameters specified here supersede the values given in
67`default-frame-alist'.
68
69If the value calls for a frame without a minibuffer, and you have
70not created a minibuffer frame on your own, a minibuffer frame is
71created according to `minibuffer-frame-alist'.
72
73You can specify geometry-related options for just the initial
74frame by setting this variable in your init file; however, they
75won't take effect until Emacs reads your init file, which happens
76after creating the initial frame. If you want the initial frame
77to have the proper geometry as soon as it appears, you need to
78use this three-step process:
de17da15
RS
79* Specify X resources to give the geometry you want.
80* Set `default-frame-alist' to override these options so that they
81 don't affect subsequent frames.
82* Set `initial-frame-alist' in a way that matches the X resources,
0c966f88
RS
83 to override what you put in `default-frame-alist'."
84 :type '(repeat (cons :format "%v"
85 (symbol :tag "Parameter")
86 (sexp :tag "Value")))
87 :group 'frames)
64c669bc 88
0b9d32af 89(defcustom minibuffer-frame-alist '((width . 80) (height . 2))
92e02072
CY
90 "Alist of parameters for the initial minibuffer frame.
91This is the minibuffer frame created if `initial-frame-alist'
92calls for a frame without a minibuffer. The parameters specified
93here supersede those given in `default-frame-alist', for the
94initial minibuffer frame.
95
dca6c418
MR
96You can set this in your init file; for example,
97
dc6d9681 98 (setq minibuffer-frame-alist
dca6c418
MR
99 '((top . 1) (left . 1) (width . 80) (height . 2)))
100
92e02072
CY
101It is not necessary to include (minibuffer . only); that is
102appended when the minibuffer frame is created."
0b9d32af
RS
103 :type '(repeat (cons :format "%v"
104 (symbol :tag "Parameter")
105 (sexp :tag "Value")))
106 :group 'frames)
64c669bc 107
924be53a 108(defun handle-delete-frame (event)
40d34803 109 "Handle delete-frame events from the X server."
924be53a
RS
110 (interactive "e")
111 (let ((frame (posn-window (event-start event)))
112 (i 0)
113 (tail (frame-list)))
114 (while tail
115 (and (frame-visible-p (car tail))
116 (not (eq (car tail) frame))
117 (setq i (1+ i)))
118 (setq tail (cdr tail)))
119 (if (> i 0)
120 (delete-frame frame t)
a9562d19
RS
121 ;; Gildea@x.org says it is ok to ask questions before terminating.
122 (save-buffers-kill-emacs))))
511fa0d3
SM
123
124(defun handle-focus-in (_event)
125 "Handle a focus-in event.
126Focus-in events are usually bound to this function.
127Focus-in events occur when a frame has focus, but a switch-frame event
128is not generated.
129This function runs the hook `focus-in-hook'."
623891e5 130 (interactive "e")
511fa0d3
SM
131 (run-hooks 'focus-in-hook))
132
133(defun handle-focus-out (_event)
134 "Handle a focus-out event.
135Focus-out events are usually bound to this function.
136Focus-out events occur when no frame has focus.
137This function runs the hook `focus-out-hook'."
623891e5 138 (interactive "e")
511fa0d3 139 (run-hooks 'focus-out-hook))
64c669bc 140\f
dc6d9681 141;;;; Arrangement of frames at startup
64c669bc 142
7e573c4a
SM
143;; 1) Load the window system startup file from the lisp library and read the
144;; high-priority arguments (-q and the like). The window system startup
145;; file should create any frames specified in the window system defaults.
146;;
147;; 2) If no frames have been opened, we open an initial text frame.
148;;
149;; 3) Once the init file is done, we apply any newly set parameters
150;; in initial-frame-alist to the frame.
64c669bc 151
85557d7e 152;; These are now called explicitly at the proper times,
fc4d4afb
RS
153;; since that is easier to understand.
154;; Actually using hooks within Emacs is bad for future maintenance. --rms.
155;; (add-hook 'before-init-hook 'frame-initialize)
156;; (add-hook 'window-setup-hook 'frame-notice-user-settings)
64c669bc 157
7e573c4a 158;; If we create the initial frame, this is it.
dc6d9681 159(defvar frame-initial-frame nil)
64c669bc 160
3f2f8c83
RS
161;; Record the parameters used in frame-initialize to make the initial frame.
162(defvar frame-initial-frame-alist)
163
791e09d8
RS
164(defvar frame-initial-geometry-arguments nil)
165
7e573c4a
SM
166;; startup.el calls this function before loading the user's init
167;; file - if there is no frame with a minibuffer open now, create
168;; one to display messages while loading the init file.
dc6d9681 169(defun frame-initialize ()
ff2a1c79 170 "Create an initial frame if necessary."
64c669bc 171 ;; Are we actually running under a window system at all?
2246281f
KL
172 (if (and initial-window-system
173 (not noninteractive)
174 (not (eq initial-window-system 'pc)))
7eadab74
JB
175 (progn
176 ;; If there is no frame with a minibuffer besides the terminal
177 ;; frame, then we need to create the opening frame. Make sure
178 ;; it has a minibuffer, but let initial-frame-alist omit the
179 ;; minibuffer spec.
180 (or (delq terminal-frame (minibuffer-frame-list))
36fc9c9f 181 (progn
3f2f8c83 182 (setq frame-initial-frame-alist
9688894d 183 (append initial-frame-alist default-frame-alist nil))
a8bb5882
RS
184 (or (assq 'horizontal-scroll-bars frame-initial-frame-alist)
185 (setq frame-initial-frame-alist
186 (cons '(horizontal-scroll-bars . t)
187 frame-initial-frame-alist)))
2246281f
KL
188 (setq frame-initial-frame-alist
189 (cons (cons 'window-system initial-window-system)
190 frame-initial-frame-alist))
36fc9c9f
RS
191 (setq default-minibuffer-frame
192 (setq frame-initial-frame
96a84970 193 (make-frame frame-initial-frame-alist)))
11281034
RS
194 ;; Delete any specifications for window geometry parameters
195 ;; so that we won't reapply them in frame-notice-user-settings.
196 ;; It would be wrong to reapply them then,
197 ;; because that would override explicit user resizing.
58bf6042 198 (setq initial-frame-alist
c2079f0a 199 (frame-remove-geometry-params initial-frame-alist))))
a13f8f50
KL
200 ;; Copy the environment of the Emacs process into the new frame.
201 (set-frame-parameter frame-initial-frame 'environment
202 (frame-parameter terminal-frame 'environment))
85557d7e 203 ;; At this point, we know that we have a frame open, so we
dc6d9681
JB
204 ;; can delete the terminal frame.
205 (delete-frame terminal-frame)
2246281f 206 (setq terminal-frame nil))))
85557d7e 207
8f2a992b
GM
208(defvar frame-notice-user-settings t
209 "Non-nil means function `frame-notice-user-settings' wasn't run yet.")
210
aa360da1
GM
211(declare-function tool-bar-mode "tool-bar" (&optional arg))
212
880e6158
MR
213(defalias 'tool-bar-lines-needed 'tool-bar-height)
214
7e573c4a
SM
215;; startup.el calls this function after loading the user's init
216;; file. Now default-frame-alist and initial-frame-alist contain
217;; information to which we must react; do what needs to be done.
dc6d9681 218(defun frame-notice-user-settings ()
40d34803 219 "Act on user's init file settings of frame parameters.
0e1bfc78
KL
220React to settings of `initial-frame-alist',
221`window-system-default-frame-alist' and `default-frame-alist'
222there (in decreasing order of priority)."
7eadab74
JB
223 ;; Creating and deleting frames may shift the selected frame around,
224 ;; and thus the current buffer. Protect against that. We don't
225 ;; want to use save-excursion here, because that may also try to set
226 ;; the buffer of the selected window, which fails when the selected
227 ;; window is the minibuffer.
0e1bfc78 228 (let ((old-buffer (current-buffer))
cb01ce3f
SM
229 (window-system-frame-alist
230 (cdr (assq initial-window-system
231 window-system-default-frame-alist))))
7eadab74 232
8f2a992b
GM
233 (when (and frame-notice-user-settings
234 (null frame-initial-frame))
42002db5
EZ
235 ;; This case happens when we don't have a window system, and
236 ;; also for MS-DOS frames.
0216b738 237 (let ((parms (frame-parameters)))
8f2a992b
GM
238 ;; Don't change the frame names.
239 (setq parms (delq (assq 'name parms) parms))
240 ;; Can't modify the minibuffer parameter, so don't try.
241 (setq parms (delq (assq 'minibuffer parms) parms))
0216b738
CY
242 (modify-frame-parameters
243 nil
244 (if initial-window-system
245 parms
246 ;; initial-frame-alist and default-frame-alist were already
247 ;; applied in pc-win.el.
248 (append initial-frame-alist window-system-frame-alist
249 default-frame-alist parms nil)))
2246281f 250 (if (null initial-window-system) ;; MS-DOS does this differently in pc-win.el
42002db5
EZ
251 (let ((newparms (frame-parameters))
252 (frame (selected-frame)))
253 (tty-handle-reverse-video frame newparms)
254 ;; If we changed the background color, we need to update
255 ;; the background-mode parameter, and maybe some faces,
256 ;; too.
257 (when (assq 'background-color newparms)
258 (unless (or (assq 'background-mode initial-frame-alist)
259 (assq 'background-mode default-frame-alist))
260 (frame-set-background-mode frame))
261 (face-set-after-frame-default frame))))))
8f2a992b 262
7eadab74
JB
263 ;; If the initial frame is still around, apply initial-frame-alist
264 ;; and default-frame-alist to it.
9688894d
GM
265 (when (frame-live-p frame-initial-frame)
266
267 ;; When tool-bar has been switched off, correct the frame size
268 ;; by the lines added in x-create-frame for the tool-bar and
269 ;; switch `tool-bar-mode' off.
085ef9b3
GM
270 (when (display-graphic-p)
271 (let ((tool-bar-lines (or (assq 'tool-bar-lines initial-frame-alist)
0e1bfc78 272 (assq 'tool-bar-lines window-system-frame-alist)
085ef9b3 273 (assq 'tool-bar-lines default-frame-alist))))
5c39a60f
JR
274 (when (and tool-bar-originally-present
275 (or (null tool-bar-lines)
276 (null (cdr tool-bar-lines))
277 (eq 0 (cdr tool-bar-lines))))
085ef9b3 278 (let* ((char-height (frame-char-height frame-initial-frame))
5c39a60f 279 (image-height tool-bar-images-pixel-height)
085ef9b3
GM
280 (margin (cond ((and (consp tool-bar-button-margin)
281 (integerp (cdr tool-bar-button-margin))
282 (> tool-bar-button-margin 0))
283 (cdr tool-bar-button-margin))
284 ((and (integerp tool-bar-button-margin)
285 (> tool-bar-button-margin 0))
286 tool-bar-button-margin)
287 (t 0)))
288 (relief (if (and (integerp tool-bar-button-relief)
289 (> tool-bar-button-relief 0))
290 tool-bar-button-relief 3))
f39784dd 291 (lines (/ (+ image-height
085ef9b3
GM
292 (* 2 margin)
293 (* 2 relief)
294 (1- char-height))
295 char-height))
296 (height (frame-parameter frame-initial-frame 'height))
297 (newparms (list (cons 'height (- height lines))))
f39784dd 298 (initial-top (cdr (assq 'top
085ef9b3
GM
299 frame-initial-geometry-arguments)))
300 (top (frame-parameter frame-initial-frame 'top)))
301 (when (and (consp initial-top) (eq '- (car initial-top)))
7f18ce22
RS
302 (let ((adjusted-top
303 (cond ((and (consp top)
304 (eq '+ (car top)))
305 (list '+
306 (+ (cadr top)
307 (* lines char-height))))
308 ((and (consp top)
309 (eq '- (car top)))
310 (list '-
311 (- (cadr top)
312 (* lines char-height))))
313 (t (+ top (* lines char-height))))))
314 (setq newparms
315 (append newparms
316 `((top . ,adjusted-top))
317 nil))))
085ef9b3
GM
318 (modify-frame-parameters frame-initial-frame newparms)
319 (tool-bar-mode -1)))))
9688894d
GM
320
321 ;; The initial frame we create above always has a minibuffer.
322 ;; If the user wants to remove it, or make it a minibuffer-only
323 ;; frame, then we'll have to delete the current frame and make a
324 ;; new one; you can't remove or add a root window to/from an
325 ;; existing frame.
326 ;;
327 ;; NOTE: default-frame-alist was nil when we created the
328 ;; existing frame. We need to explicitly include
329 ;; default-frame-alist in the parameters of the screen we
330 ;; create here, so that its new value, gleaned from the user's
865fe16f 331 ;; init file, will be applied to the existing screen.
de2f5dbe 332 (if (not (eq (cdr (or (assq 'minibuffer initial-frame-alist)
0e1bfc78 333 (assq 'minibuffer window-system-frame-alist)
de2f5dbe
GM
334 (assq 'minibuffer default-frame-alist)
335 '(minibuffer . t)))
336 t))
337 ;; Create the new frame.
338 (let (parms new)
35a89bdd
EZ
339 ;; MS-Windows needs this to avoid inflooping below.
340 (if (eq system-type 'windows-nt)
341 (sit-for 0 t))
de2f5dbe
GM
342 ;; If the frame isn't visible yet, wait till it is.
343 ;; If the user has to position the window,
344 ;; Emacs doesn't know its real position until
345 ;; the frame is seen to be visible.
346 (while (not (cdr (assq 'visibility
347 (frame-parameters frame-initial-frame))))
348 (sleep-for 1))
349 (setq parms (frame-parameters frame-initial-frame))
9688894d 350
f39784dd 351 ;; Get rid of `name' unless it was specified explicitly before.
de2f5dbe
GM
352 (or (assq 'name frame-initial-frame-alist)
353 (setq parms (delq (assq 'name parms) parms)))
2f5bb432
SM
354 ;; An explicit parent-id is a request to XEmbed the frame.
355 (or (assq 'parent-id frame-initial-frame-alist)
356 (setq parms (delq (assq 'parent-id parms) parms)))
de2f5dbe
GM
357
358 (setq parms (append initial-frame-alist
0e1bfc78 359 window-system-frame-alist
de2f5dbe
GM
360 default-frame-alist
361 parms
362 nil))
363
364 ;; Get rid of `reverse', because that was handled
365 ;; when we first made the frame.
366 (setq parms (cons '(reverse) (delq (assq 'reverse parms) parms)))
367
368 (if (assq 'height frame-initial-geometry-arguments)
369 (setq parms (assq-delete-all 'height parms)))
370 (if (assq 'width frame-initial-geometry-arguments)
371 (setq parms (assq-delete-all 'width parms)))
372 (if (assq 'left frame-initial-geometry-arguments)
373 (setq parms (assq-delete-all 'left parms)))
374 (if (assq 'top frame-initial-geometry-arguments)
375 (setq parms (assq-delete-all 'top parms)))
376 (setq new
377 (make-frame
378 ;; Use the geometry args that created the existing
379 ;; frame, rather than the parms we get for it.
380 (append frame-initial-geometry-arguments
381 '((user-size . t) (user-position . t))
382 parms)))
383 ;; The initial frame, which we are about to delete, may be
384 ;; the only frame with a minibuffer. If it is, create a
385 ;; new one.
386 (or (delq frame-initial-frame (minibuffer-frame-list))
387 (make-initial-minibuffer-frame nil))
388
389 ;; If the initial frame is serving as a surrogate
390 ;; minibuffer frame for any frames, we need to wean them
391 ;; onto a new frame. The default-minibuffer-frame
392 ;; variable must be handled similarly.
393 (let ((users-of-initial
394 (filtered-frame-list
b7de6024
SM
395 (lambda (frame)
396 (and (not (eq frame frame-initial-frame))
397 (eq (window-frame
398 (minibuffer-window frame))
399 frame-initial-frame))))))
400 (if (or users-of-initial
de2f5dbe
GM
401 (eq default-minibuffer-frame frame-initial-frame))
402
403 ;; Choose an appropriate frame. Prefer frames which
404 ;; are only minibuffers.
405 (let* ((new-surrogate
406 (car
407 (or (filtered-frame-list
b7de6024
SM
408 (lambda (frame)
409 (eq (cdr (assq 'minibuffer
410 (frame-parameters frame)))
411 'only)))
de2f5dbe
GM
412 (minibuffer-frame-list))))
413 (new-minibuffer (minibuffer-window new-surrogate)))
414
415 (if (eq default-minibuffer-frame frame-initial-frame)
416 (setq default-minibuffer-frame new-surrogate))
417
418 ;; Wean the frames using frame-initial-frame as
419 ;; their minibuffer frame.
b7de6024
SM
420 (dolist (frame users-of-initial)
421 (modify-frame-parameters
422 frame (list (cons 'minibuffer new-minibuffer)))))))
423
424 ;; Redirect events enqueued at this frame to the new frame.
de2f5dbe
GM
425 ;; Is this a good idea?
426 (redirect-frame-focus frame-initial-frame new)
427
428 ;; Finally, get rid of the old frame.
429 (delete-frame frame-initial-frame t))
9688894d 430
9858f6c3 431 ;; Otherwise, we don't need all that rigmarole; just apply
9688894d
GM
432 ;; the new parameters.
433 (let (newparms allparms tail)
434 (setq allparms (append initial-frame-alist
0e1bfc78 435 window-system-frame-alist
9688894d
GM
436 default-frame-alist nil))
437 (if (assq 'height frame-initial-geometry-arguments)
438 (setq allparms (assq-delete-all 'height allparms)))
439 (if (assq 'width frame-initial-geometry-arguments)
440 (setq allparms (assq-delete-all 'width allparms)))
441 (if (assq 'left frame-initial-geometry-arguments)
442 (setq allparms (assq-delete-all 'left allparms)))
443 (if (assq 'top frame-initial-geometry-arguments)
444 (setq allparms (assq-delete-all 'top allparms)))
445 (setq tail allparms)
446 ;; Find just the parms that have changed since we first
447 ;; made this frame. Those are the ones actually set by
f39784dd 448 ;; the init file. For those parms whose values we already knew
9688894d
GM
449 ;; (such as those spec'd by command line options)
450 ;; it is undesirable to specify the parm again
f39784dd 451 ;; once the user has seen the frame and been able to alter it
9688894d 452 ;; manually.
0216b738
CY
453 (let (newval oldval)
454 (dolist (entry tail)
455 (setq oldval (assq (car entry) frame-initial-frame-alist))
456 (setq newval (cdr (assq (car entry) allparms)))
9688894d
GM
457 (or (and oldval (eq (cdr oldval) newval))
458 (setq newparms
0216b738 459 (cons (cons (car entry) newval) newparms)))))
9688894d 460 (setq newparms (nreverse newparms))
0216b738
CY
461
462 (let ((new-bg (assq 'background-color newparms)))
463 ;; If the `background-color' parameter is changed, apply
464 ;; it first, then make sure that the `background-mode'
465 ;; parameter and other faces are updated, before applying
466 ;; the other parameters.
467 (when new-bg
468 (modify-frame-parameters frame-initial-frame
469 (list new-bg))
470 (unless (assq 'background-mode newparms)
471 (frame-set-background-mode frame-initial-frame))
472 (face-set-after-frame-default frame-initial-frame)
473 (setq newparms (delq new-bg newparms)))
474 (modify-frame-parameters frame-initial-frame newparms)))))
64c669bc 475
7eadab74
JB
476 ;; Restore the original buffer.
477 (set-buffer old-buffer)
478
479 ;; Make sure the initial frame can be GC'd if it is ever deleted.
d202f1f2 480 ;; Make sure frame-notice-user-settings does nothing if called twice.
8f2a992b 481 (setq frame-notice-user-settings nil)
d202f1f2 482 (setq frame-initial-frame nil)))
64c669bc 483
746bd265
KH
484(defun make-initial-minibuffer-frame (display)
485 (let ((parms (append minibuffer-frame-alist '((minibuffer . only)))))
486 (if display
487 (make-frame-on-display display parms)
488 (make-frame parms))))
489
7eadab74 490;;;; Creation of additional frames, and other frame miscellanea
dc6d9681 491
63019bad 492(defun modify-all-frames-parameters (alist)
d398de43 493 "Modify all current and future frames' parameters according to ALIST.
63019bad 494This changes `default-frame-alist' and possibly `initial-frame-alist'.
095fe281
KL
495Furthermore, this function removes all parameters in ALIST from
496`window-system-default-frame-alist'.
63019bad 497See help of `modify-frame-parameters' for more information."
095fe281
KL
498 (dolist (frame (frame-list))
499 (modify-frame-parameters frame alist))
500
501 (dolist (pair alist) ;; conses to add/replace
502 ;; initial-frame-alist needs setting only when
503 ;; frame-notice-user-settings is true.
504 (and frame-notice-user-settings
505 (setq initial-frame-alist
506 (assq-delete-all (car pair) initial-frame-alist)))
507 (setq default-frame-alist
508 (assq-delete-all (car pair) default-frame-alist))
509 ;; Remove any similar settings from the window-system specific
510 ;; parameters---they would override default-frame-alist.
511 (dolist (w window-system-default-frame-alist)
512 (setcdr w (assq-delete-all (car pair) (cdr w)))))
513
63019bad
JB
514 (and frame-notice-user-settings
515 (setq initial-frame-alist (append initial-frame-alist alist)))
516 (setq default-frame-alist (append default-frame-alist alist)))
517
7253d8e0 518(defun get-other-frame ()
40d34803
DL
519 "Return some frame other than the current frame.
520Create one if necessary. Note that the minibuffer frame, if separate,
521is not considered (see `next-frame')."
c8c2aca8 522 (if (equal (next-frame) (selected-frame)) (make-frame) (next-frame)))
64c669bc 523
dc6d9681
JB
524(defun next-multiframe-window ()
525 "Select the next window, regardless of which frame it is on."
64c669bc
JB
526 (interactive)
527 (select-window (next-window (selected-window)
528 (> (minibuffer-depth) 0)
bb2c34b1 529 0))
030f4537 530 (select-frame-set-input-focus (selected-frame)))
64c669bc 531
dc6d9681
JB
532(defun previous-multiframe-window ()
533 "Select the previous window, regardless of which frame it is on."
64c669bc
JB
534 (interactive)
535 (select-window (previous-window (selected-window)
536 (> (minibuffer-depth) 0)
bb2c34b1 537 0))
030f4537 538 (select-frame-set-input-focus (selected-frame)))
64c669bc 539
efc3dd3c
DC
540(defun window-system-for-display (display)
541 "Return the window system for DISPLAY.
542Return nil if we don't know how to interpret DISPLAY."
543 (cl-loop for descriptor in display-format-alist
544 for pattern = (car descriptor)
545 for system = (cdr descriptor)
546 when (string-match-p pattern display) return system))
bbf6ef44 547
6d73e337 548(defun make-frame-on-display (display &optional parameters)
c5a8bc01
CY
549 "Make a frame on display DISPLAY.
550The optional argument PARAMETERS specifies additional frame parameters."
6d73e337 551 (interactive "sMake frame on display: ")
efc3dd3c 552 (make-frame (cons (cons 'display display) parameters)))
6d73e337 553
aa360da1
GM
554(declare-function x-close-connection "xfns.c" (terminal))
555
b7de6024
SM
556(defun close-display-connection (display)
557 "Close the connection to a display, deleting all its associated frames.
558For DISPLAY, specify either a frame or a display name (a string).
559If DISPLAY is nil, that stands for the selected frame's display."
560 (interactive
561 (list
562 (let* ((default (frame-parameter nil 'display))
563 (display (completing-read
564 (format "Close display (default %s): " default)
565 (delete-dups
566 (mapcar (lambda (frame)
567 (frame-parameter frame 'display))
568 (frame-list)))
569 nil t nil nil
570 default)))
571 (if (zerop (length display)) default display))))
572 (let ((frames (delq nil
573 (mapcar (lambda (frame)
574 (if (equal display
575 (frame-parameter frame 'display))
576 frame))
577 (frame-list)))))
578 (if (and (consp frames)
579 (not (y-or-n-p (if (cdr frames)
580 (format "Delete %s frames? " (length frames))
581 (format "Delete %s ? " (car frames))))))
582 (error "Abort!")
583 (mapc 'delete-frame frames)
584 (x-close-connection display))))
585
6238bfaf 586(defun make-frame-command ()
e9e6aee8
CY
587 "Make a new frame, on the same terminal as the selected frame.
588If the terminal is a text-only terminal, this also selects the
589new frame."
6238bfaf 590 (interactive)
e9e6aee8 591 (if (display-graphic-p)
6238bfaf
RS
592 (make-frame)
593 (select-frame (make-frame))))
594
45c4fdeb
SM
595(defvar before-make-frame-hook nil
596 "Functions to run before a frame is created.")
597
598(defvar after-make-frame-functions nil
599 "Functions to run after a frame is created.
600The functions are run with one arg, the newly created frame.")
601
72bf1a8b 602(defvar after-setting-font-hook nil
81b99826
GM
603 "Functions to run after a frame's font has been changed.")
604
92e443b1 605;; Alias, kept temporarily.
84ed1560 606(define-obsolete-function-alias 'new-frame 'make-frame "22.1")
bc93c097 607
9e483377 608(defvar frame-inherited-parameters '()
ab6198b2
SM
609 ;; FIXME: Shouldn't we add `font' here as well?
610 "Parameters `make-frame' copies from the `selected-frame' to the new frame.")
611
4bd4c0af
GM
612(defvar x-display-name)
613
45c4fdeb
SM
614(defun make-frame (&optional parameters)
615 "Return a newly created frame displaying the current buffer.
c1ef4455
CY
616Optional argument PARAMETERS is an alist of frame parameters for
617the new frame. Each element of PARAMETERS should have the
618form (NAME . VALUE), for example:
a105105a 619
45c4fdeb 620 (name . STRING) The frame should be named STRING.
43a2e52c 621
45c4fdeb
SM
622 (width . NUMBER) The frame should be NUMBER characters in width.
623 (height . NUMBER) The frame should be NUMBER text lines high.
43a2e52c 624
c1ef4455
CY
625You cannot specify either `width' or `height', you must specify
626neither or both.
43a2e52c 627
45c4fdeb
SM
628 (minibuffer . t) The frame should have a minibuffer.
629 (minibuffer . nil) The frame should have no minibuffer.
630 (minibuffer . only) The frame should contain only a minibuffer.
631 (minibuffer . WINDOW) The frame should use WINDOW as its minibuffer window.
43a2e52c 632
2246281f
KL
633 (window-system . nil) The frame should be displayed on a terminal device.
634 (window-system . x) The frame should be displayed in an X window.
635
efc3dd3c
DC
636 (display . \":0\") The frame should appear on display :0.
637
d51f6378 638 (terminal . TERMINAL) The frame should use the terminal object TERMINAL.
b6660415 639
c1ef4455
CY
640In addition, any parameter specified in `default-frame-alist',
641but not present in PARAMETERS, is applied.
8de9d3f6 642
c1ef4455
CY
643Before creating the frame (via `frame-creation-function-alist'),
644this function runs the hook `before-make-frame-hook'. After
645creating the frame, it runs the hook `after-make-frame-functions'
646with one arg, the newly created frame.
647
efc3dd3c
DC
648If a display parameter is supplied and a window-system is not,
649guess the window-system from the display.
650
c1ef4455
CY
651On graphical displays, this function does not itself make the new
652frame the selected frame. However, the window system may select
653the new frame according to its own rules."
64c669bc 654 (interactive)
efc3dd3c
DC
655 (let* ((display (cdr (assq 'display parameters)))
656 (w (cond
6ed8eeff
KL
657 ((assq 'terminal parameters)
658 (let ((type (terminal-live-p (cdr (assq 'terminal parameters)))))
b6660415
KL
659 (cond
660 ((eq type t) nil)
cb01ce3f
SM
661 ((eq type nil) (error "Terminal %s does not exist"
662 (cdr (assq 'terminal parameters))))
b6660415
KL
663 (t type))))
664 ((assq 'window-system parameters)
665 (cdr (assq 'window-system parameters)))
efc3dd3c
DC
666 (display
667 (or (window-system-for-display display)
668 (error "Don't know how to interpret display \"%S\""
669 display)))
b6660415 670 (t window-system)))
2246281f 671 (frame-creation-function (cdr (assq w frame-creation-function-alist)))
da8e8fc1 672 (oldframe (selected-frame))
c1ef4455 673 (params parameters)
2246281f
KL
674 frame)
675 (unless frame-creation-function
676 (error "Don't know how to create a frame on window system %s" w))
efc3dd3c
DC
677
678 (unless (get w 'window-system-initialized)
ebb19708
DA
679 (funcall (cdr (assq w window-system-initialization-alist)) display)
680 (setq x-display-name display)
efc3dd3c
DC
681 (put w 'window-system-initialized t))
682
c1ef4455
CY
683 ;; Add parameters from `window-system-default-frame-alist'.
684 (dolist (p (cdr (assq w window-system-default-frame-alist)))
21bd02a6 685 (unless (assq (car p) params)
c1ef4455
CY
686 (push p params)))
687 ;; Add parameters from `default-frame-alist'.
688 (dolist (p default-frame-alist)
21bd02a6 689 (unless (assq (car p) params)
c1ef4455
CY
690 (push p params)))
691 ;; Now make the frame.
2246281f 692 (run-hooks 'before-make-frame-hook)
c1ef4455 693 (setq frame (funcall frame-creation-function params))
30a2fded 694 (normal-erase-is-backspace-setup-frame frame)
ab6198b2
SM
695 ;; Inherit the original frame's parameters.
696 (dolist (param frame-inherited-parameters)
697 (unless (assq param parameters) ;Overridden by explicit parameters.
698 (let ((val (frame-parameter oldframe param)))
699 (when val (set-frame-parameter frame param val)))))
45c4fdeb
SM
700 (run-hook-with-args 'after-make-frame-functions frame)
701 frame))
64c669bc 702
7eadab74
JB
703(defun filtered-frame-list (predicate)
704 "Return a list of all live frames which satisfy PREDICATE."
047bc928
GM
705 (let* ((frames (frame-list))
706 (list frames))
7eadab74 707 (while (consp frames)
047bc928
GM
708 (unless (funcall predicate (car frames))
709 (setcar frames nil))
7eadab74 710 (setq frames (cdr frames)))
047bc928 711 (delq nil list)))
7eadab74
JB
712
713(defun minibuffer-frame-list ()
714 "Return a list of all frames with their own minibuffers."
715 (filtered-frame-list
b7de6024
SM
716 (lambda (frame)
717 (eq frame (window-frame (minibuffer-window frame))))))
7eadab74 718
371fed4e
SM
719;; Used to be called `terminal-id' in termdev.el.
720(defun get-device-terminal (device)
721 "Return the terminal corresponding to DEVICE.
722DEVICE can be a terminal, a frame, nil (meaning the selected frame's terminal),
723the name of an X display device (HOST.SERVER.SCREEN) or a tty device file."
724 (cond
725 ((or (null device) (framep device))
726 (frame-terminal device))
727 ((stringp device)
728 (let ((f (car (filtered-frame-list
729 (lambda (frame)
730 (or (equal (frame-parameter frame 'display) device)
731 (equal (frame-parameter frame 'tty) device)))))))
732 (or f (error "Display %s does not exist" device))
733 (frame-terminal f)))
734 ((terminal-live-p device) device)
735 (t
736 (error "Invalid argument %s in `get-device-terminal'" device))))
737
738(defun frames-on-display-list (&optional device)
739 "Return a list of all frames on DEVICE.
740
741DEVICE should be a terminal, a frame,
742or a name of an X display or tty (a string of the form
9684e4c9 743HOST:SERVER.SCREEN).
b6660415 744
371fed4e 745If DEVICE is omitted or nil, it defaults to the selected
9684e4c9 746frame's terminal device."
371fed4e 747 (let* ((terminal (get-device-terminal device))
047bc928 748 (func #'(lambda (frame)
6ed8eeff 749 (eq (frame-terminal frame) terminal))))
9911648b
EZ
750 (filtered-frame-list func)))
751
f35ca2fe
KL
752(defun framep-on-display (&optional terminal)
753 "Return the type of frames on TERMINAL.
754TERMINAL may be a terminal id, a display name or a frame. If it
755is a frame, its type is returned. If TERMINAL is omitted or nil,
756it defaults to the selected frame's terminal device. All frames
757on a given display are of the same type."
6ed8eeff 758 (or (terminal-live-p terminal)
f35ca2fe
KL
759 (framep terminal)
760 (framep (car (frames-on-display-list terminal)))))
9911648b 761
58bf6042
JB
762(defun frame-remove-geometry-params (param-list)
763 "Return the parameter list PARAM-LIST, but with geometry specs removed.
764This deletes all bindings in PARAM-LIST for `top', `left', `width',
791e09d8 765`height', `user-size' and `user-position' parameters.
58bf6042
JB
766Emacs uses this to avoid overriding explicit moves and resizings from
767the user during startup."
768 (setq param-list (cons nil param-list))
769 (let ((tail param-list))
770 (while (consp (cdr tail))
771 (if (and (consp (car (cdr tail)))
791e09d8
RS
772 (memq (car (car (cdr tail)))
773 '(height width top left user-position user-size)))
774 (progn
775 (setq frame-initial-geometry-arguments
776 (cons (car (cdr tail)) frame-initial-geometry-arguments))
777 (setcdr tail (cdr (cdr tail))))
58bf6042 778 (setq tail (cdr tail)))))
e11c3dc2
KH
779 (setq frame-initial-geometry-arguments
780 (nreverse frame-initial-geometry-arguments))
58bf6042
JB
781 (cdr param-list))
782
fcd42c11 783(declare-function x-focus-frame "frame.c" (frame))
aa360da1 784
be39b8cc 785(defun select-frame-set-input-focus (frame &optional norecord)
bbca16d8 786 "Select FRAME, raise it, and set input focus, if possible.
e343066f 787If `mouse-autoselect-window' is non-nil, also move mouse pointer
bbca16d8 788to FRAME's selected window. Otherwise, if `focus-follows-mouse'
be39b8cc
MR
789is non-nil, move mouse cursor to FRAME.
790
791Optional argument NORECORD means to neither change the order of
792recently selected windows nor the buffer list."
793 (select-frame frame norecord)
b0c7121c 794 (raise-frame frame)
bbca16d8 795 ;; Ensure, if possible, that FRAME gets input focus.
b0c7121c
MR
796 (when (memq (window-system frame) '(x w32 ns))
797 (x-focus-frame frame))
bbca16d8
MR
798 ;; Move mouse cursor if necessary.
799 (cond
800 (mouse-autoselect-window
801 (let ((edges (window-inside-edges (frame-selected-window frame))))
802 ;; Move mouse cursor into FRAME's selected window to avoid that
803 ;; Emacs mouse-autoselects another window.
804 (set-mouse-position frame (nth 2 edges) (nth 1 edges))))
805 (focus-follows-mouse
806 ;; Move mouse cursor into FRAME to avoid that another frame gets
807 ;; selected by the window manager.
808 (set-mouse-position frame (1- (frame-width frame)) 0))))
030f4537 809
ceab6935 810(defun other-frame (arg)
c2c93894 811 "Select the ARGth different visible frame on current display, and raise it.
ceab6935
RM
812All frames are arranged in a cyclic order.
813This command selects the frame ARG steps away in that order.
bb578a72
RS
814A negative ARG moves in the opposite order.
815
816To make this command work properly, you must tell Emacs
817how the system (or the window manager) generally handles
818focus-switching between windows. If moving the mouse onto a window
819selects it (gives it focus), set `focus-follows-mouse' to t.
820Otherwise, that variable should be nil."
ceab6935
RM
821 (interactive "p")
822 (let ((frame (selected-frame)))
823 (while (> arg 0)
a569dbc3
RM
824 (setq frame (next-frame frame))
825 (while (not (eq (frame-visible-p frame) t))
826 (setq frame (next-frame frame)))
827 (setq arg (1- arg)))
ceab6935 828 (while (< arg 0)
a569dbc3
RM
829 (setq frame (previous-frame frame))
830 (while (not (eq (frame-visible-p frame) t))
831 (setq frame (previous-frame frame)))
915cfd1f 832 (setq arg (1+ arg)))
030f4537 833 (select-frame-set-input-focus frame)))
845cde06 834
3db7df06
SM
835(defun iconify-or-deiconify-frame ()
836 "Iconify the selected frame, or deiconify if it's currently an icon."
837 (interactive)
838 (if (eq (cdr (assq 'visibility (frame-parameters))) t)
839 (iconify-frame)
840 (make-frame-visible)))
841
0b0d3e0b
KL
842(defun suspend-frame ()
843 "Do whatever is right to suspend the current frame.
f35ca2fe
KL
844Calls `suspend-emacs' if invoked from the controlling tty device,
845`suspend-tty' from a secondary tty device, and
0b0d3e0b
KL
846`iconify-or-deiconify-frame' from an X frame."
847 (interactive)
848 (let ((type (framep (selected-frame))))
849 (cond
edfda783 850 ((memq type '(x ns w32)) (iconify-or-deiconify-frame))
0b0d3e0b 851 ((eq type t)
6ed8eeff 852 (if (controlling-tty-p)
4a933ef8
KL
853 (suspend-emacs)
854 (suspend-tty)))
0b0d3e0b
KL
855 (t (suspend-emacs)))))
856
845cde06 857(defun make-frame-names-alist ()
e2c3f530 858 ;; Only consider the frames on the same display.
845cde06
EZ
859 (let* ((current-frame (selected-frame))
860 (falist
861 (cons
862 (cons (frame-parameter current-frame 'name) current-frame) nil))
e2c3f530 863 (frame (next-frame nil 0)))
845cde06
EZ
864 (while (not (eq frame current-frame))
865 (progn
e2c3f530
SM
866 (push (cons (frame-parameter frame 'name) frame) falist)
867 (setq frame (next-frame frame 0))))
845cde06
EZ
868 falist))
869
870(defvar frame-name-history nil)
845cde06 871(defun select-frame-by-name (name)
563283b1 872 "Select the frame on the current terminal whose name is NAME and raise it.
845cde06
EZ
873If there is no frame by that name, signal an error."
874 (interactive
716ff1c9
RS
875 (let* ((frame-names-alist (make-frame-names-alist))
876 (default (car (car frame-names-alist)))
877 (input (completing-read
878 (format "Select Frame (default %s): " default)
879 frame-names-alist nil t nil 'frame-name-history)))
845cde06
EZ
880 (if (= (length input) 0)
881 (list default)
882 (list input))))
716ff1c9
RS
883 (let* ((frame-names-alist (make-frame-names-alist))
884 (frame (cdr (assoc name frame-names-alist))))
bbca16d8
MR
885 (if frame
886 (select-frame-set-input-focus frame)
887 (error "There is no frame named `%s'" name))))
1485f4c0
CY
888
889\f
890;;;; Background mode.
891
892(defcustom frame-background-mode nil
893 "The brightness of the background.
894Set this to the symbol `dark' if your background color is dark,
895`light' if your background is light, or nil (automatic by default)
e73c3a0d
GM
896if you want Emacs to examine the brightness for you.
897
79a15a36 898If you change this without using customize, you should use
2e4a0a90
GM
899`frame-set-background-mode' to update existing frames;
900e.g. (mapc 'frame-set-background-mode (frame-list))."
1485f4c0
CY
901 :group 'faces
902 :set #'(lambda (var value)
903 (set-default var value)
904 (mapc 'frame-set-background-mode (frame-list)))
905 :initialize 'custom-initialize-changed
906 :type '(choice (const dark)
907 (const light)
908 (const :tag "automatic" nil)))
909
910(declare-function x-get-resource "frame.c"
911 (attribute class &optional component subclass))
912
e740f9d2
GM
913;; Only used if window-system is not null.
914(declare-function x-display-grayscale-p "xfns.c" (&optional terminal))
915
1485f4c0
CY
916(defvar inhibit-frame-set-background-mode nil)
917
918(defun frame-set-background-mode (frame &optional keep-face-specs)
919 "Set up display-dependent faces on FRAME.
920Display-dependent faces are those which have different definitions
921according to the `background-mode' and `display-type' frame parameters.
922
923If optional arg KEEP-FACE-SPECS is non-nil, don't recalculate
924face specs for the new background mode."
925 (unless inhibit-frame-set-background-mode
926 (let* ((frame-default-bg-mode (frame-terminal-default-bg-mode frame))
927 (bg-color (frame-parameter frame 'background-color))
928 (tty-type (tty-type frame))
929 (default-bg-mode
930 (if (or (window-system frame)
931 (and tty-type
932 (string-match "^\\(xterm\\|\\rxvt\\|dtterm\\|eterm\\)"
933 tty-type)))
934 'light
935 'dark))
936 (non-default-bg-mode (if (eq default-bg-mode 'light) 'dark 'light))
937 (bg-mode
938 (cond (frame-default-bg-mode)
939 ((equal bg-color "unspecified-fg") ; inverted colors
940 non-default-bg-mode)
941 ((not (color-values bg-color frame))
942 default-bg-mode)
943 ((>= (apply '+ (color-values bg-color frame))
944 ;; Just looking at the screen, colors whose
945 ;; values add up to .6 of the white total
946 ;; still look dark to me.
947 (* (apply '+ (color-values "white" frame)) .6))
948 'light)
949 (t 'dark)))
950 (display-type
951 (cond ((null (window-system frame))
952 (if (tty-display-color-p frame) 'color 'mono))
953 ((display-color-p frame)
954 'color)
955 ((x-display-grayscale-p frame)
956 'grayscale)
957 (t 'mono)))
958 (old-bg-mode
959 (frame-parameter frame 'background-mode))
960 (old-display-type
961 (frame-parameter frame 'display-type)))
962
963 (unless (and (eq bg-mode old-bg-mode) (eq display-type old-display-type))
964 (let ((locally-modified-faces nil)
965 ;; Prevent face-spec-recalc from calling this function
966 ;; again, resulting in a loop (bug#911).
967 (inhibit-frame-set-background-mode t)
968 (params (list (cons 'background-mode bg-mode)
969 (cons 'display-type display-type))))
970 (if keep-face-specs
971 (modify-frame-parameters frame params)
972 ;; If we are recomputing face specs, first collect a list
973 ;; of faces that don't match their face-specs. These are
974 ;; the faces modified on FRAME, and we avoid changing them
975 ;; below. Use a negative list to avoid consing (we assume
976 ;; most faces are unmodified).
977 (dolist (face (face-list))
978 (and (not (get face 'face-override-spec))
979 (not (face-spec-match-p face
980 (face-user-default-spec face)
981 (selected-frame)))
982 (push face locally-modified-faces)))
983 ;; Now change to the new frame parameters
984 (modify-frame-parameters frame params)
985 ;; For all unmodified named faces, choose face specs
986 ;; matching the new frame parameters.
987 (dolist (face (face-list))
988 (unless (memq face locally-modified-faces)
989 (face-spec-recalc face frame)))))))))
990
991(defun frame-terminal-default-bg-mode (frame)
992 "Return the default background mode of FRAME.
993This checks the `frame-background-mode' variable, the X resource
994named \"backgroundMode\" (if FRAME is an X frame), and finally
995the `background-mode' terminal parameter."
996 (or frame-background-mode
997 (let ((bg-resource
998 (and (window-system frame)
999 (x-get-resource "backgroundMode" "BackgroundMode"))))
1000 (if bg-resource
1001 (intern (downcase bg-resource))))
1002 (terminal-parameter frame 'background-mode)))
1003
64c669bc 1004\f
dc6d9681
JB
1005;;;; Frame configurations
1006
1007(defun current-frame-configuration ()
1008 "Return a list describing the positions and states of all frames.
376a7584
JB
1009Its car is `frame-configuration'.
1010Each element of the cdr is a list of the form (FRAME ALIST WINDOW-CONFIG),
1011where
1012 FRAME is a frame object,
1013 ALIST is an association list specifying some of FRAME's parameters, and
1014 WINDOW-CONFIG is a window configuration object for FRAME."
1015 (cons 'frame-configuration
b7de6024
SM
1016 (mapcar (lambda (frame)
1017 (list frame
1018 (frame-parameters frame)
1019 (current-window-configuration frame)))
376a7584 1020 (frame-list))))
dc6d9681 1021
68cd265f 1022(defun set-frame-configuration (configuration &optional nodelete)
dc6d9681
JB
1023 "Restore the frames to the state described by CONFIGURATION.
1024Each frame listed in CONFIGURATION has its position, size, window
68cd265f 1025configuration, and other parameters set as specified in CONFIGURATION.
d398de43
LT
1026However, this function does not restore deleted frames.
1027
a78db71c
RS
1028Ordinarily, this function deletes all existing frames not
1029listed in CONFIGURATION. But if optional second argument NODELETE
5da841d2 1030is given and non-nil, the unwanted frames are iconified instead."
376a7584
JB
1031 (or (frame-configuration-p configuration)
1032 (signal 'wrong-type-argument
1033 (list 'frame-configuration-p configuration)))
1034 (let ((config-alist (cdr configuration))
1035 frames-to-delete)
b7de6024
SM
1036 (dolist (frame (frame-list))
1037 (let ((parameters (assq frame config-alist)))
1038 (if parameters
1039 (progn
1040 (modify-frame-parameters
1041 frame
1042 ;; Since we can't set a frame's minibuffer status,
1043 ;; we might as well omit the parameter altogether.
1044 (let* ((parms (nth 1 parameters))
b2529d56
MB
1045 (mini (assq 'minibuffer parms))
1046 (name (assq 'name parms))
1047 (explicit-name (cdr (assq 'explicit-name parms))))
1048 (when mini (setq parms (delq mini parms)))
1049 ;; Leave name in iff it was set explicitly.
1050 ;; This should fix the behavior reported in
1051 ;; http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg01632.html
1052 (when (and name (not explicit-name))
1053 (setq parms (delq name parms)))
b7de6024
SM
1054 parms))
1055 (set-window-configuration (nth 2 parameters)))
1056 (setq frames-to-delete (cons frame frames-to-delete)))))
1057 (mapc (if nodelete
1058 ;; Note: making frames invisible here was tried
1059 ;; but led to some strange behavior--each time the frame
1060 ;; was made visible again, the window manager asked afresh
1061 ;; for where to put it.
1062 'iconify-frame
1063 'delete-frame)
1064 frames-to-delete)))
64c669bc 1065\f
dc6d9681
JB
1066;;;; Convenience functions for accessing and interactively changing
1067;;;; frame parameters.
64c669bc 1068
151bdc83 1069(defun frame-height (&optional frame)
dc6d9681 1070 "Return number of lines available for display on FRAME.
4619ff5e
GM
1071If FRAME is omitted, describe the currently selected frame.
1072Exactly what is included in the return value depends on the
1073window-system and toolkit in use - see `frame-pixel-height' for
1074more details. The lines are in units of the default font height.
1075
1076The result is roughly related to the frame pixel height via
1077height in pixels = height in lines * `frame-char-height'.
1078However, this is only approximate, and is complicated e.g. by the
1079fact that individual window lines and menu bar lines can have
1080differing font heights."
151bdc83 1081 (cdr (assq 'height (frame-parameters frame))))
dc6d9681
JB
1082
1083(defun frame-width (&optional frame)
1084 "Return number of columns available for display on FRAME.
1085If FRAME is omitted, describe the currently selected frame."
151bdc83 1086 (cdr (assq 'width (frame-parameters frame))))
dc6d9681 1087
aa360da1
GM
1088(declare-function x-list-fonts "xfaces.c"
1089 (pattern &optional face frame maximum width))
1090
52ef9375 1091(define-obsolete-function-alias 'set-default-font 'set-frame-font "23.1")
fce3fdeb 1092
f2045622
CY
1093(defun set-frame-font (font &optional keep-size frames)
1094 "Set the default font to FONT.
fce3fdeb 1095When called interactively, prompt for the name of a font, and use
f2045622
CY
1096that font on the selected frame. When called from Lisp, FONT
1097should be a font name (a string), a font object, font entity, or
1098font spec.
fce3fdeb
CY
1099
1100If KEEP-SIZE is nil, keep the number of frame lines and columns
1101fixed. If KEEP-SIZE is non-nil (or with a prefix argument), try
1102to keep the current frame size fixed (in pixels) by adjusting the
1103number of lines and columns.
1104
9f562668
CY
1105If FRAMES is nil, apply the font to the selected frame only.
1106If FRAMES is non-nil, it should be a list of frames to act upon,
1107or t meaning all graphical frames. Also, if FRAME is non-nil,
1108alter the user's Customization settings as though the
fce3fdeb
CY
1109font-related attributes of the `default' face had been \"set in
1110this session\", so that the font is applied to future frames."
f39784dd 1111 (interactive
1cef6541
JB
1112 (let* ((completion-ignore-case t)
1113 (font (completing-read "Font name: "
1cef6541
JB
1114 ;; x-list-fonts will fail with an error
1115 ;; if this frame doesn't support fonts.
b7de6024
SM
1116 (x-list-fonts "*" nil (selected-frame))
1117 nil nil nil nil
1118 (frame-parameter nil 'font))))
fce3fdeb 1119 (list font current-prefix-arg nil)))
f2045622 1120 (when (or (stringp font) (fontp font))
fce3fdeb 1121 (let* ((this-frame (selected-frame))
9f562668
CY
1122 ;; FRAMES nil means affect the selected frame.
1123 (frame-list (cond ((null frames)
1124 (list this-frame))
1125 ((eq frames t)
1126 (frame-list))
1127 (t frames)))
fce3fdeb 1128 height width)
9f562668 1129 (dolist (f frame-list)
fce3fdeb
CY
1130 (when (display-multi-font-p f)
1131 (if keep-size
1132 (setq height (* (frame-parameter f 'height)
1133 (frame-char-height f))
1134 width (* (frame-parameter f 'width)
1135 (frame-char-width f))))
1136 ;; When set-face-attribute is called for :font, Emacs
1137 ;; guesses the best font according to other face attributes
1138 ;; (:width, :weight, etc.) so reset them too (Bug#2476).
1139 (set-face-attribute 'default f
1140 :width 'normal :weight 'normal
f2045622 1141 :slant 'normal :font font)
fce3fdeb
CY
1142 (if keep-size
1143 (modify-frame-parameters
1144 f
1145 (list (cons 'height (round height (frame-char-height f)))
1146 (cons 'width (round width (frame-char-width f))))))))
9f562668 1147 (when frames
fce3fdeb
CY
1148 ;; Alter the user's Custom setting of the `default' face, but
1149 ;; only for font-related attributes.
1150 (let ((specs (cadr (assq 'user (get 'default 'theme-face))))
1151 (attrs '(:family :foundry :slant :weight :height :width))
1152 (new-specs nil))
1153 (if (null specs) (setq specs '((t nil))))
1154 (dolist (spec specs)
1155 ;; Each SPEC has the form (DISPLAY ATTRIBUTE-PLIST)
1156 (let ((display (nth 0 spec))
1157 (plist (copy-tree (nth 1 spec))))
1158 ;; Alter only DISPLAY conditions matching this frame.
1159 (when (or (memq display '(t default))
1160 (face-spec-set-match-display display this-frame))
1161 (dolist (attr attrs)
1162 (setq plist (plist-put plist attr
1163 (face-attribute 'default attr)))))
1164 (push (list display plist) new-specs)))
1165 (setq new-specs (nreverse new-specs))
1166 (put 'default 'customized-face new-specs)
1167 (custom-push-theme 'theme-face 'default 'user 'set new-specs)
1168 (put 'default 'face-modified nil))))
1169 (run-hooks 'after-setting-font-hook 'after-setting-font-hooks)))
64c669bc 1170
7e573c4a 1171(defun set-frame-parameter (frame parameter value)
0dac35b8
KL
1172 "Set frame parameter PARAMETER to VALUE on FRAME.
1173If FRAME is nil, it defaults to the selected frame.
c2c93894 1174See `modify-frame-parameters'."
7e573c4a
SM
1175 (modify-frame-parameters frame (list (cons parameter value))))
1176
8290babd 1177(defun set-background-color (color-name)
40d34803 1178 "Set the background color of the selected frame to COLOR-NAME.
61298010
RS
1179When called interactively, prompt for the name of the color to use.
1180To get the frame's current background color, use `frame-parameters'."
9317e499 1181 (interactive (list (read-color "Background color: ")))
dc6d9681 1182 (modify-frame-parameters (selected-frame)
528e1416
EZ
1183 (list (cons 'background-color color-name)))
1184 (or window-system
1185 (face-set-after-frame-default (selected-frame))))
64c669bc 1186
8290babd 1187(defun set-foreground-color (color-name)
40d34803 1188 "Set the foreground color of the selected frame to COLOR-NAME.
61298010
RS
1189When called interactively, prompt for the name of the color to use.
1190To get the frame's current foreground color, use `frame-parameters'."
9317e499 1191 (interactive (list (read-color "Foreground color: ")))
dc6d9681 1192 (modify-frame-parameters (selected-frame)
528e1416
EZ
1193 (list (cons 'foreground-color color-name)))
1194 (or window-system
1195 (face-set-after-frame-default (selected-frame))))
64c669bc
JB
1196
1197(defun set-cursor-color (color-name)
40d34803 1198 "Set the text cursor color of the selected frame to COLOR-NAME.
61298010 1199When called interactively, prompt for the name of the color to use.
2680c309
CY
1200This works by setting the `cursor-color' frame parameter on the
1201selected frame.
1202
1203You can also set the text cursor color, for all frames, by
1204customizing the `cursor' face."
9317e499 1205 (interactive (list (read-color "Cursor color: ")))
dc6d9681 1206 (modify-frame-parameters (selected-frame)
7eadab74 1207 (list (cons 'cursor-color color-name))))
64c669bc 1208
eaa974e1 1209(defun set-mouse-color (color-name)
40d34803 1210 "Set the color of the mouse pointer of the selected frame to COLOR-NAME.
61298010
RS
1211When called interactively, prompt for the name of the color to use.
1212To get the frame's current mouse color, use `frame-parameters'."
9317e499 1213 (interactive (list (read-color "Mouse color: ")))
dc6d9681 1214 (modify-frame-parameters (selected-frame)
ec6d4463
KH
1215 (list (cons 'mouse-color
1216 (or color-name
1217 (cdr (assq 'mouse-color
1218 (frame-parameters))))))))
7eadab74 1219
eaa974e1 1220(defun set-border-color (color-name)
40d34803 1221 "Set the color of the border of the selected frame to COLOR-NAME.
61298010
RS
1222When called interactively, prompt for the name of the color to use.
1223To get the frame's current border color, use `frame-parameters'."
9317e499 1224 (interactive (list (read-color "Border color: ")))
eaa974e1
JB
1225 (modify-frame-parameters (selected-frame)
1226 (list (cons 'border-color color-name))))
1227
f44379e7 1228(define-minor-mode auto-raise-mode
ed472be9 1229 "Toggle whether or not selected frames should auto-raise.
06e21633
CY
1230With a prefix argument ARG, enable Auto Raise mode if ARG is
1231positive, and disable it otherwise. If called from Lisp, enable
1232the mode if ARG is omitted or nil.
1233
ed472be9
CY
1234Auto Raise mode does nothing under most window managers, which
1235switch focus on mouse clicks. It only has an effect if your
1236window manager switches focus on mouse movement (in which case
1237you should also change `focus-follows-mouse' to t). Then,
1238enabling Auto Raise mode causes any graphical Emacs frame which
1239acquires focus to be automatically raised.
1240
1241Note that this minor mode controls Emacs's own auto-raise
1242feature. Window managers that switch focus on mouse movement
1243often have their own auto-raise feature."
f44379e7
SM
1244 :variable (frame-parameter nil 'auto-raise)
1245 (if (frame-parameter nil 'auto-raise)
1246 (raise-frame)))
7eadab74 1247
f44379e7 1248(define-minor-mode auto-lower-mode
7eadab74 1249 "Toggle whether or not the selected frame should auto-lower.
06e21633
CY
1250With a prefix argument ARG, enable Auto Lower mode if ARG is
1251positive, and disable it otherwise. If called from Lisp, enable
1252the mode if ARG is omitted or nil.
1253
ed472be9
CY
1254Auto Lower mode does nothing under most window managers, which
1255switch focus on mouse clicks. It only has an effect if your
1256window manager switches focus on mouse movement (in which case
1257you should also change `focus-follows-mouse' to t). Then,
1258enabling Auto Lower Mode causes any graphical Emacs frame which
1259loses focus to be automatically lowered.
1260
1261Note that this minor mode controls Emacs's own auto-lower
1262feature. Window managers that switch focus on mouse movement
1263often have their own features for raising or lowering frames."
f44379e7
SM
1264 :variable (frame-parameter nil 'auto-lower))
1265
7777d03b
EZ
1266(defun set-frame-name (name)
1267 "Set the name of the selected frame to NAME.
1268When called interactively, prompt for the name of the frame.
37269466
CY
1269On text terminals, the frame name is displayed on the mode line.
1270On graphical displays, it is displayed on the frame's title bar."
7777d03b
EZ
1271 (interactive "sFrame name: ")
1272 (modify-frame-parameters (selected-frame)
1273 (list (cons 'name name))))
56cfea72
KS
1274
1275(defun frame-current-scroll-bars (&optional frame)
1276 "Return the current scroll-bar settings in frame FRAME.
1cecf04d 1277Value is a cons (VERTICAL . HORIZ0NTAL) where VERTICAL specifies the
56cfea72 1278current location of the vertical scroll-bars (left, right, or nil),
1cecf04d 1279and HORIZONTAL specifies the current location of the horizontal scroll
56cfea72
KS
1280bars (top, bottom, or nil)."
1281 (let ((vert (frame-parameter frame 'vertical-scroll-bars))
1282 (hor nil))
1283 (unless (memq vert '(left right nil))
1284 (setq vert default-frame-scroll-bars))
1285 (cons vert hor)))
4e3f9230
YM
1286
1287(defun frame-monitor-attributes (&optional frame)
1288 "Return the attributes of the physical monitor dominating FRAME.
1289If FRAME is omitted, describe the currently selected frame.
1290
1291A frame is dominated by a physical monitor when either the
1292largest area of the frame resides in the monitor, or the monitor
1293is the closest to the frame if the frame does not intersect any
1294physical monitors.
1295
1296See `display-monitor-attributes-list' for the list of attribute
1297keys and their meanings."
1298 (or frame (setq frame (selected-frame)))
1299 (cl-loop for attributes in (display-monitor-attributes-list frame)
1300 for frames = (cdr (assq 'frames attributes))
1301 if (memq frame frames) return attributes))
1302
64c669bc 1303\f
9911648b 1304;;;; Frame/display capabilities.
b6660415 1305
73e6adaa
DN
1306(declare-function msdos-mouse-p "dosfns.c")
1307
9911648b
EZ
1308(defun display-mouse-p (&optional display)
1309 "Return non-nil if DISPLAY has a mouse available.
1310DISPLAY can be a display name, a frame, or nil (meaning the selected
1311frame's display)."
1312 (let ((frame-type (framep-on-display display)))
1313 (cond
1314 ((eq frame-type 'pc)
1315 (msdos-mouse-p))
0fda9b75 1316 ((eq frame-type 'w32)
9fa5bb32
RS
1317 (with-no-warnings
1318 (> w32-num-mouse-buttons 0)))
9e2a2647
DN
1319 ((memq frame-type '(x ns))
1320 t) ;; We assume X and NeXTstep *always* have a pointing device
9911648b 1321 (t
7565ee93
DL
1322 (or (and (featurep 'xt-mouse)
1323 xterm-mouse-mode)
1324 ;; t-mouse is distributed with the GPM package. It doesn't have
1325 ;; a toggle.
ffe759eb
EZ
1326 (featurep 't-mouse)
1327 ;; No way to check whether a w32 console has a mouse, assume
1328 ;; it always does.
1329 (boundp 'w32-use-full-screen-buffer))))))
9911648b
EZ
1330
1331(defun display-popup-menus-p (&optional display)
1332 "Return non-nil if popup menus are supported on DISPLAY.
1333DISPLAY can be a display name, a frame, or nil (meaning the selected
1334frame's display).
1335Support for popup menus requires that the mouse be available."
ffe759eb 1336 (display-mouse-p display))
9911648b
EZ
1337
1338(defun display-graphic-p (&optional display)
1339 "Return non-nil if DISPLAY is a graphic display.
1340Graphical displays are those which are capable of displaying several
1341frames and several different fonts at once. This is true for displays
1342that use a window system such as X, and false for text-only terminals.
1343DISPLAY can be a display name, a frame, or nil (meaning the selected
1344frame's display)."
9e2a2647 1345 (not (null (memq (framep-on-display display) '(x w32 ns)))))
9911648b 1346
ddc456e4
EZ
1347(defun display-images-p (&optional display)
1348 "Return non-nil if DISPLAY can display images.
1349
1350DISPLAY can be a display name, a frame, or nil (meaning the selected
1351frame's display)."
1352 (and (display-graphic-p display)
1353 (fboundp 'image-mask-p)
fcc6f5cc 1354 (fboundp 'image-size)))
ddc456e4 1355
6693b279
EZ
1356(defalias 'display-multi-frame-p 'display-graphic-p)
1357(defalias 'display-multi-font-p 'display-graphic-p)
1358
9911648b
EZ
1359(defun display-selections-p (&optional display)
1360 "Return non-nil if DISPLAY supports selections.
1361A selection is a way to transfer text or other data between programs
45240125 1362via special system buffers called `selection' or `clipboard'.
9911648b
EZ
1363DISPLAY can be a display name, a frame, or nil (meaning the selected
1364frame's display)."
1365 (let ((frame-type (framep-on-display display)))
1366 (cond
1367 ((eq frame-type 'pc)
1368 ;; MS-DOG frames support selections when Emacs runs inside
1369 ;; the Windows' DOS Box.
9fa5bb32
RS
1370 (with-no-warnings
1371 (not (null dos-windows-version))))
9e2a2647 1372 ((memq frame-type '(x w32 ns))
9911648b
EZ
1373 t) ;; FIXME?
1374 (t
1375 nil))))
1376
aa360da1
GM
1377(declare-function x-display-screens "xfns.c" (&optional terminal))
1378
9911648b 1379(defun display-screens (&optional display)
d40a46d7
XF
1380 "Return the number of screens associated with DISPLAY.
1381If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1382 (let ((frame-type (framep-on-display display)))
1383 (cond
9e2a2647 1384 ((memq frame-type '(x w32 ns))
9911648b 1385 (x-display-screens display))
bb9404d6 1386 (t
9911648b
EZ
1387 1))))
1388
aa360da1
GM
1389(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
1390
9911648b
EZ
1391(defun display-pixel-height (&optional display)
1392 "Return the height of DISPLAY's screen in pixels.
cf13177e
YM
1393For character terminals, each character counts as a single pixel.
1394For graphical terminals, note that on \"multi-monitor\" setups this
1395refers to the pixel height for all physical monitors associated
1396with DISPLAY. To get information for each physical monitor, use
d40a46d7
XF
1397`display-monitor-attributes-list'.
1398If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1399 (let ((frame-type (framep-on-display display)))
1400 (cond
9e2a2647 1401 ((memq frame-type '(x w32 ns))
9911648b
EZ
1402 (x-display-pixel-height display))
1403 (t
1404 (frame-height (if (framep display) display (selected-frame)))))))
1405
aa360da1
GM
1406(declare-function x-display-pixel-width "xfns.c" (&optional terminal))
1407
9911648b
EZ
1408(defun display-pixel-width (&optional display)
1409 "Return the width of DISPLAY's screen in pixels.
cf13177e
YM
1410For character terminals, each character counts as a single pixel.
1411For graphical terminals, note that on \"multi-monitor\" setups this
1412refers to the pixel width for all physical monitors associated
1413with DISPLAY. To get information for each physical monitor, use
d40a46d7
XF
1414`display-monitor-attributes-list'.
1415If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1416 (let ((frame-type (framep-on-display display)))
1417 (cond
9e2a2647 1418 ((memq frame-type '(x w32 ns))
9911648b
EZ
1419 (x-display-pixel-width display))
1420 (t
1421 (frame-width (if (framep display) display (selected-frame)))))))
1422
51e39dfc
KS
1423(defcustom display-mm-dimensions-alist nil
1424 "Alist for specifying screen dimensions in millimeters.
1425The dimensions will be used for `display-mm-height' and
1426`display-mm-width' if defined for the respective display.
1427
1428Each element of the alist has the form (display . (width . height)),
1429e.g. (\":0.0\" . (287 . 215)).
1430
1431If `display' equals t, it specifies dimensions for all graphical
c7015153 1432displays not explicitly specified."
51e39dfc
KS
1433 :version "22.1"
1434 :type '(alist :key-type (choice (string :tag "Display name")
1435 (const :tag "Default" t))
1436 :value-type (cons :tag "Dimensions"
1437 (integer :tag "Width")
1438 (integer :tag "Height")))
1439 :group 'frames)
1440
aa360da1
GM
1441(declare-function x-display-mm-height "xfns.c" (&optional terminal))
1442
9911648b
EZ
1443(defun display-mm-height (&optional display)
1444 "Return the height of DISPLAY's screen in millimeters.
d7cd2d8b 1445System values can be overridden by `display-mm-dimensions-alist'.
cf13177e
YM
1446If the information is unavailable, value is nil.
1447For graphical terminals, note that on \"multi-monitor\" setups this
1448refers to the height in millimeters for all physical monitors
1449associated with DISPLAY. To get information for each physical
d40a46d7
XF
1450monitor, use `display-monitor-attributes-list'.
1451If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9e2a2647 1452 (and (memq (framep-on-display display) '(x w32 ns))
51e39dfc
KS
1453 (or (cddr (assoc (or display (frame-parameter nil 'display))
1454 display-mm-dimensions-alist))
1455 (cddr (assoc t display-mm-dimensions-alist))
1456 (x-display-mm-height display))))
9911648b 1457
aa360da1
GM
1458(declare-function x-display-mm-width "xfns.c" (&optional terminal))
1459
9911648b
EZ
1460(defun display-mm-width (&optional display)
1461 "Return the width of DISPLAY's screen in millimeters.
d7cd2d8b 1462System values can be overridden by `display-mm-dimensions-alist'.
cf13177e
YM
1463If the information is unavailable, value is nil.
1464For graphical terminals, note that on \"multi-monitor\" setups this
1465refers to the width in millimeters for all physical monitors
1466associated with DISPLAY. To get information for each physical
d40a46d7
XF
1467monitor, use `display-monitor-attributes-list'.
1468If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9e2a2647 1469 (and (memq (framep-on-display display) '(x w32 ns))
51e39dfc
KS
1470 (or (cadr (assoc (or display (frame-parameter nil 'display))
1471 display-mm-dimensions-alist))
1472 (cadr (assoc t display-mm-dimensions-alist))
1473 (x-display-mm-width display))))
9911648b 1474
aa360da1
GM
1475(declare-function x-display-backing-store "xfns.c" (&optional terminal))
1476
916119ec
XF
1477;; In NS port, the return value may be `buffered', `retained', or
1478;; `non-retained'. See src/nsfns.m.
9911648b
EZ
1479(defun display-backing-store (&optional display)
1480 "Return the backing store capability of DISPLAY's screen.
1481The value may be `always', `when-mapped', `not-useful', or nil if
d40a46d7
XF
1482the question is inapplicable to a certain kind of display.
1483If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1484 (let ((frame-type (framep-on-display display)))
1485 (cond
9e2a2647 1486 ((memq frame-type '(x w32 ns))
9911648b
EZ
1487 (x-display-backing-store display))
1488 (t
1489 'not-useful))))
1490
aa360da1
GM
1491(declare-function x-display-save-under "xfns.c" (&optional terminal))
1492
9911648b 1493(defun display-save-under (&optional display)
d40a46d7
XF
1494 "Return non-nil if DISPLAY's screen supports the SaveUnder feature.
1495If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1496 (let ((frame-type (framep-on-display display)))
1497 (cond
9e2a2647 1498 ((memq frame-type '(x w32 ns))
9911648b
EZ
1499 (x-display-save-under display))
1500 (t
1501 'not-useful))))
1502
aa360da1
GM
1503(declare-function x-display-planes "xfns.c" (&optional terminal))
1504
9911648b 1505(defun display-planes (&optional display)
d40a46d7
XF
1506 "Return the number of planes supported by DISPLAY.
1507If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1508 (let ((frame-type (framep-on-display display)))
1509 (cond
9e2a2647 1510 ((memq frame-type '(x w32 ns))
9911648b
EZ
1511 (x-display-planes display))
1512 ((eq frame-type 'pc)
1513 4)
1514 (t
1515 (truncate (log (length (tty-color-alist)) 2))))))
1516
aa360da1
GM
1517(declare-function x-display-color-cells "xfns.c" (&optional terminal))
1518
9911648b 1519(defun display-color-cells (&optional display)
d40a46d7
XF
1520 "Return the number of color cells supported by DISPLAY.
1521If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1522 (let ((frame-type (framep-on-display display)))
1523 (cond
9e2a2647 1524 ((memq frame-type '(x w32 ns))
9911648b
EZ
1525 (x-display-color-cells display))
1526 ((eq frame-type 'pc)
1527 16)
1528 (t
3224dac1 1529 (tty-display-color-cells display)))))
9911648b 1530
aa360da1
GM
1531(declare-function x-display-visual-class "xfns.c" (&optional terminal))
1532
9911648b 1533(defun display-visual-class (&optional display)
6cda144f 1534 "Return the visual class of DISPLAY.
9911648b 1535The value is one of the symbols `static-gray', `gray-scale',
d40a46d7
XF
1536`static-color', `pseudo-color', `true-color', or `direct-color'.
1537If DISPLAY is omitted or nil, it defaults to the selected frame's display."
9911648b
EZ
1538 (let ((frame-type (framep-on-display display)))
1539 (cond
9e2a2647 1540 ((memq frame-type '(x w32 ns))
9911648b
EZ
1541 (x-display-visual-class display))
1542 ((and (memq frame-type '(pc t))
1543 (tty-display-color-p display))
1544 'static-color)
1545 (t
1546 'static-gray))))
1547
4e3f9230
YM
1548(declare-function x-display-monitor-attributes-list "xfns.c"
1549 (&optional terminal))
cf13177e
YM
1550(declare-function w32-display-monitor-attributes-list "w32fns.c"
1551 (&optional display))
f20def1f 1552(declare-function ns-display-monitor-attributes-list "nsfns.m"
4465bfb4 1553 (&optional terminal))
4e3f9230
YM
1554
1555(defun display-monitor-attributes-list (&optional display)
1556 "Return a list of physical monitor attributes on DISPLAY.
1557Each element of the list represents the attributes of each
1558physical monitor. The first element corresponds to the primary
1559monitor.
1560
1561Attributes for a physical monitor is represented as an alist of
1562attribute keys and values as follows:
1563
1564 geometry -- Position and size in pixels in the form of
1565 (X Y WIDTH HEIGHT)
1566 workarea -- Position and size of the workarea in pixels in the
1567 form of (X Y WIDTH HEIGHT)
1568 mm-size -- Width and height in millimeters in the form of
1569 (WIDTH HEIGHT)
1570 frames -- List of frames dominated by the physical monitor
1571 name (*) -- Name of the physical monitor as a string
1572
1573where X, Y, WIDTH, and HEIGHT are integers. Keys labeled
1574with (*) are optional.
1575
1576A frame is dominated by a physical monitor when either the
1577largest area of the frame resides in the monitor, or the monitor
1578is the closest to the frame if the frame does not intersect any
1579physical monitors. Every non-tip frame (including invisible one)
1580in a graphical display is dominated by exactly one physical
1581monitor at a time, though it can span multiple (or no) physical
d40a46d7
XF
1582monitors.
1583If DISPLAY is omitted or nil, it defaults to the selected frame's display."
4e3f9230
YM
1584 (let ((frame-type (framep-on-display display)))
1585 (cond
1586 ((eq frame-type 'x)
1587 (x-display-monitor-attributes-list display))
cf13177e
YM
1588 ((eq frame-type 'w32)
1589 (w32-display-monitor-attributes-list display))
4465bfb4
JD
1590 ((eq frame-type 'ns)
1591 (ns-display-monitor-attributes-list display))
4e3f9230
YM
1592 (t
1593 (let ((geometry (list 0 0 (display-pixel-width display)
1594 (display-pixel-height display))))
1595 `(((geometry . ,geometry)
1596 (workarea . ,geometry)
1597 (mm-size . (,(display-mm-width display)
1598 ,(display-mm-height display)))
1599 (frames . ,(frames-on-display-list display)))))))))
1600
9911648b 1601\f
a32c1804
RS
1602;;;; Frame geometry values
1603
1604(defun frame-geom-value-cons (type value &optional frame)
1605 "Return equivalent geometry value for FRAME as a cons with car `+'.
1606A geometry value equivalent to VALUE for FRAME is returned,
1607where the value is a cons with car `+', not numeric.
1608TYPE is the car of the original geometry spec (TYPE . VALUE).
1609 It is `top' or `left', depending on which edge VALUE is related to.
1610VALUE is the cdr of a frame geometry spec: (left/top . VALUE).
1611If VALUE is a number, then it is converted to a cons value, perhaps
1612 relative to the opposite frame edge from that in the original spec.
1613FRAME defaults to the selected frame.
1614
1615Examples (measures in pixels) -
1616 Assuming display height/width=1024, frame height/width=600:
1617 300 inside display edge: 300 => (+ 300)
1618 (+ 300) => (+ 300)
1619 300 inside opposite display edge: (- 300) => (+ 124)
1620 -300 => (+ 124)
1621 300 beyond display edge
1622 (= 724 inside opposite display edge): (+ -300) => (+ -300)
1623 300 beyond display edge
1624 (= 724 inside opposite display edge): (- -300) => (+ 724)
1625
1626In the 3rd, 4th, and 6th examples, the returned value is relative to
1627the opposite frame edge from the edge indicated in the input spec."
1628 (cond ((and (consp value) (eq '+ (car value))) ; e.g. (+ 300), (+ -300)
1629 value)
1630 ((natnump value) (list '+ value)) ; e.g. 300 => (+ 300)
1631 (t ; e.g. -300, (- 300), (- -300)
1632 (list '+ (- (if (eq 'left type) ; => (+ 124), (+ 124), (+ 724)
1633 (x-display-pixel-width)
1634 (x-display-pixel-height))
1635 (if (integerp value) (- value) (cadr value))
1636 (if (eq 'left type)
1637 (frame-pixel-width frame)
1638 (frame-pixel-height frame)))))))
1639
1640(defun frame-geom-spec-cons (spec &optional frame)
1641 "Return equivalent geometry spec for FRAME as a cons with car `+'.
1642A geometry specification equivalent to SPEC for FRAME is returned,
1643where the value is a cons with car `+', not numeric.
1644SPEC is a frame geometry spec: (left . VALUE) or (top . VALUE).
1645If VALUE is a number, then it is converted to a cons value, perhaps
1646 relative to the opposite frame edge from that in the original spec.
1647FRAME defaults to the selected frame.
1648
1649Examples (measures in pixels) -
1650 Assuming display height=1024, frame height=600:
1651 top 300 below display top: (top . 300) => (top + 300)
1652 (top + 300) => (top + 300)
1653 bottom 300 above display bottom: (top - 300) => (top + 124)
1654 (top . -300) => (top + 124)
1655 top 300 above display top
1656 (= bottom 724 above display bottom): (top + -300) => (top + -300)
1657 bottom 300 below display bottom
1658 (= top 724 below display top): (top - -300) => (top + 724)
1659
1660In the 3rd, 4th, and 6th examples, the returned value is relative to
1661the opposite frame edge from the edge indicated in the input spec."
06b60517 1662 (cons (car spec) (frame-geom-value-cons (car spec) (cdr spec) frame)))
a32c1804 1663\f
9e2b097b 1664
154a757e 1665(defun delete-other-frames (&optional frame)
4a592f66 1666 "Delete all frames on the current terminal, except FRAME.
a2125918
GM
1667If FRAME uses another frame's minibuffer, the minibuffer frame is
1668left untouched. FRAME nil or omitted means use the selected frame."
154a757e
GM
1669 (interactive)
1670 (unless frame
1671 (setq frame (selected-frame)))
a2125918
GM
1672 (let* ((mini-frame (window-frame (minibuffer-window frame)))
1673 (frames (delq mini-frame (delq frame (frame-list)))))
5e5ae184
SM
1674 ;; Only consider frames on the same terminal.
1675 (dolist (frame (prog1 frames (setq frames nil)))
1676 (if (eq (frame-terminal) (frame-terminal frame))
1677 (push frame frames)))
a2125918
GM
1678 ;; Delete mon-minibuffer-only frames first, because `delete-frame'
1679 ;; signals an error when trying to delete a mini-frame that's
1680 ;; still in use by another frame.
1681 (dolist (frame frames)
1682 (unless (eq (frame-parameter frame 'minibuffer) 'only)
1683 (delete-frame frame)))
1684 ;; Delete minibuffer-only frames.
1685 (dolist (frame frames)
1686 (when (eq (frame-parameter frame 'minibuffer) 'only)
1687 (delete-frame frame)))))
154a757e 1688
da7829a3 1689;; miscellaneous obsolescence declarations
84ed1560
JB
1690(define-obsolete-variable-alias 'delete-frame-hook
1691 'delete-frame-functions "22.1")
da7829a3 1692
dc6d9681 1693\f
7e573c4a 1694;; Blinking cursor
81b99826
GM
1695
1696(defgroup cursor nil
ca693be8 1697 "Displaying text cursors."
40d34803 1698 :version "21.1"
81b99826
GM
1699 :group 'frames)
1700
1701(defcustom blink-cursor-delay 0.5
6cda144f 1702 "Seconds of idle time after which cursor starts to blink."
81b99826
GM
1703 :type 'number
1704 :group 'cursor)
1705
1706(defcustom blink-cursor-interval 0.5
6cda144f 1707 "Length of cursor blink interval in seconds."
81b99826
GM
1708 :type 'number
1709 :group 'cursor)
1710
18c26d81
JD
1711(defcustom blink-cursor-blinks 10
1712 "How many times to blink before using a solid cursor on NS and X.
1713Use 0 or negative value to blink forever."
1714 :version "24.4"
1715 :type 'integer
1716 :group 'cursor)
1717
1718(defvar blink-cursor-blinks-done 1
1719 "Number of blinks done since we started blinking on NS and X")
1720
81b99826 1721(defvar blink-cursor-idle-timer nil
ca693be8
GM
1722 "Timer started after `blink-cursor-delay' seconds of Emacs idle time.
1723The function `blink-cursor-start' is called when the timer fires.")
81b99826
GM
1724
1725(defvar blink-cursor-timer nil
ca693be8 1726 "Timer started from `blink-cursor-start'.
a795e09a
LT
1727This timer calls `blink-cursor-timer-function' every
1728`blink-cursor-interval' seconds.")
1729
81b99826 1730(defun blink-cursor-start ()
ca693be8
GM
1731 "Timer function called from the timer `blink-cursor-idle-timer'.
1732This starts the timer `blink-cursor-timer', which makes the cursor blink
1733if appropriate. It also arranges to cancel that timer when the next
1734command starts, by installing a pre-command hook."
81b99826 1735 (when (null blink-cursor-timer)
f9ac92c5
CY
1736 ;; Set up the timer first, so that if this signals an error,
1737 ;; blink-cursor-end is not added to pre-command-hook.
18c26d81 1738 (setq blink-cursor-blinks-done 1)
81b99826
GM
1739 (setq blink-cursor-timer
1740 (run-with-timer blink-cursor-interval blink-cursor-interval
f9ac92c5
CY
1741 'blink-cursor-timer-function))
1742 (add-hook 'pre-command-hook 'blink-cursor-end)
1743 (internal-show-cursor nil nil)))
0a5ebe4b
GM
1744
1745(defun blink-cursor-timer-function ()
1746 "Timer function of timer `blink-cursor-timer'."
18c26d81
JD
1747 (internal-show-cursor nil (not (internal-show-cursor-p)))
1748 ;; Each blink is two calls to this function.
511fa0d3
SM
1749 (setq blink-cursor-blinks-done (1+ blink-cursor-blinks-done))
1750 (when (and (> blink-cursor-blinks 0)
1751 (<= (* 2 blink-cursor-blinks) blink-cursor-blinks-done))
1752 (blink-cursor-suspend)
1753 (add-hook 'post-command-hook 'blink-cursor-check)))
18c26d81 1754
81b99826
GM
1755
1756(defun blink-cursor-end ()
1757 "Stop cursor blinking.
ca693be8 1758This is installed as a pre-command hook by `blink-cursor-start'.
f39784dd 1759When run, it cancels the timer `blink-cursor-timer' and removes
ca693be8 1760itself as a pre-command hook."
81b99826 1761 (remove-hook 'pre-command-hook 'blink-cursor-end)
0a5ebe4b 1762 (internal-show-cursor nil t)
8ec94c16
SM
1763 (when blink-cursor-timer
1764 (cancel-timer blink-cursor-timer)
1765 (setq blink-cursor-timer nil)))
81b99826 1766
18c26d81 1767(defun blink-cursor-suspend ()
511fa0d3 1768 "Suspend cursor blinking.
18c26d81
JD
1769This is called when no frame has focus and timers can be suspended.
1770Timers are restarted by `blink-cursor-check', which is called when a
1771frame receives focus."
511fa0d3
SM
1772 (blink-cursor-end)
1773 (when blink-cursor-idle-timer
1774 (cancel-timer blink-cursor-idle-timer)
1775 (setq blink-cursor-idle-timer nil)))
18c26d81
JD
1776
1777(defun blink-cursor-check ()
02c66599 1778 "Check if cursor blinking shall be restarted.
18c26d81
JD
1779This is done when a frame gets focus. Blink timers may be stopped by
1780`blink-cursor-suspend'."
1781 (when (and blink-cursor-mode
1782 (not blink-cursor-idle-timer))
1783 (remove-hook 'post-command-hook 'blink-cursor-check)
1784 (setq blink-cursor-idle-timer
1785 (run-with-idle-timer blink-cursor-delay
1786 blink-cursor-delay
1787 'blink-cursor-start))))
1788
e5bd0a28
SM
1789(define-obsolete-variable-alias 'blink-cursor 'blink-cursor-mode "22.1")
1790
8ec94c16 1791(define-minor-mode blink-cursor-mode
06e21633
CY
1792 "Toggle cursor blinking (Blink Cursor mode).
1793With a prefix argument ARG, enable Blink Cursor mode if ARG is
1794positive, and disable it otherwise. If called from Lisp, enable
1795the mode if ARG is omitted or nil.
1796
1797This command is effective only on graphical frames. On text-only
1798terminals, cursor blinking is controlled by the terminal."
8ec94c16
SM
1799 :init-value (not (or noninteractive
1800 no-blinking-cursor
1801 (eq system-type 'ms-dos)
0afb6242 1802 (not (memq window-system '(x w32 ns)))))
adba8116 1803 :initialize 'custom-initialize-delay
8ec94c16
SM
1804 :group 'cursor
1805 :global t
1806 (if blink-cursor-idle-timer (cancel-timer blink-cursor-idle-timer))
1807 (setq blink-cursor-idle-timer nil)
1808 (blink-cursor-end)
511fa0d3
SM
1809 (remove-hook 'focus-in-hook #'blink-cursor-check)
1810 (remove-hook 'focus-out-hook #'blink-cursor-suspend)
8ec94c16 1811 (when blink-cursor-mode
511fa0d3
SM
1812 (add-hook 'focus-in-hook #'blink-cursor-check)
1813 (add-hook 'focus-out-hook #'blink-cursor-suspend)
8ec94c16
SM
1814 (setq blink-cursor-idle-timer
1815 (run-with-idle-timer blink-cursor-delay
1816 blink-cursor-delay
511fa0d3 1817 #'blink-cursor-start))))
81b99826 1818
81b99826 1819\f
a45b7647 1820;; Frame maximization/fullscreen
37f38bca
SS
1821
1822(defun toggle-frame-maximized ()
a45b7647
JL
1823 "Toggle maximization state of the selected frame.
1824Maximize the selected frame or un-maximize if it is already maximized.
1825Respect window manager screen decorations.
1826If the frame is in fullscreen mode, don't change its mode,
1827just toggle the temporary frame parameter `maximized',
1828so the frame will go to the right maximization state
1829after disabling fullscreen mode.
1830See also `toggle-frame-fullscreen'."
37f38bca 1831 (interactive)
64ced394 1832 (if (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
a45b7647
JL
1833 (modify-frame-parameters
1834 nil
1835 `((maximized
1836 . ,(unless (eq (frame-parameter nil 'maximized) 'maximized)
1837 'maximized))))
1838 (modify-frame-parameters
1839 nil
1840 `((fullscreen
1841 . ,(unless (eq (frame-parameter nil 'fullscreen) 'maximized)
1842 'maximized))))))
1843
1844(defun toggle-frame-fullscreen ()
1845 "Toggle fullscreen mode of the selected frame.
1846Enable fullscreen mode of the selected frame or disable if it is
1847already fullscreen. Ignore window manager screen decorations.
1848When turning on fullscreen mode, remember the previous value of the
1849maximization state in the temporary frame parameter `maximized'.
1850Restore the maximization state when turning off fullscreen mode.
37f38bca
SS
1851See also `toggle-frame-maximized'."
1852 (interactive)
1853 (modify-frame-parameters
a45b7647
JL
1854 nil
1855 `((maximized
64ced394 1856 . ,(unless (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
a45b7647
JL
1857 (frame-parameter nil 'fullscreen)))
1858 (fullscreen
64ced394 1859 . ,(if (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
a45b7647
JL
1860 (if (eq (frame-parameter nil 'maximized) 'maximized)
1861 'maximized)
1862 'fullscreen)))))
37f38bca
SS
1863
1864\f
64c669bc 1865;;;; Key bindings
64c669bc 1866
6238bfaf 1867(define-key ctl-x-5-map "2" 'make-frame-command)
154a757e 1868(define-key ctl-x-5-map "1" 'delete-other-frames)
dc6d9681 1869(define-key ctl-x-5-map "0" 'delete-frame)
ceab6935 1870(define-key ctl-x-5-map "o" 'other-frame)
a45b7647
JL
1871(define-key global-map [f11] 'toggle-frame-fullscreen)
1872(define-key global-map [(meta f10)] 'toggle-frame-maximized)
c84b0881 1873(define-key esc-map [f10] 'toggle-frame-maximized)
49116ac0 1874
7a76850c
CY
1875\f
1876;; Misc.
1877
2a1e2476 1878;; Only marked as obsolete in 24.3.
e5bd0a28
SM
1879(define-obsolete-variable-alias 'automatic-hscrolling
1880 'auto-hscroll-mode "22.1")
7a76850c
CY
1881
1882(make-variable-buffer-local 'show-trailing-whitespace)
1883
3424a4f6
CY
1884;; Defined in dispnew.c.
1885(make-obsolete-variable
1886 'window-system-version "it does not give useful information." "24.3")
1887
dc6d9681 1888(provide 'frame)
c88ab9ce 1889
dc6d9681 1890;;; frame.el ends here