These are in preparation for a more thorough renaming to occur soon.
[bpt/emacs.git] / lisp / frame.el
CommitLineData
dc6d9681 1;;; frame.el --- multi-frame management independent of window systems.
c88ab9ce 2
faa3b11d 3;;;; Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
3a801d0c 4
fc68affa 5;; Maintainer: FSF
fd7fa35a 6;; Keywords: internal
fc68affa 7
64c669bc
JB
8;;; This file is part of GNU Emacs.
9;;;
10;;; GNU Emacs is free software; you can redistribute it and/or modify
11;;; it under the terms of the GNU General Public License as published by
de49a6d3 12;;; the Free Software Foundation; either version 2, or (at your option)
64c669bc
JB
13;;; any later version.
14;;;
15;;; GNU Emacs is distributed in the hope that it will be useful,
16;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;;; GNU General Public License for more details.
19;;;
20;;; You should have received a copy of the GNU General Public License
21;;; along with GNU Emacs; see the file COPYING. If not, write to
22;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
fc68affa
ER
24;;; Code:
25
dc6d9681
JB
26(defvar frame-creation-function nil
27 "Window-system dependent function to call to create a new frame.
28The window system startup file should set this to its frame creation
64c669bc
JB
29function, which should take an alist of parameters as its argument.")
30
7eadab74
JB
31;;; The initial value given here for this must ask for a minibuffer.
32;;; There must always exist a frame with a minibuffer, and after we
33;;; delete the terminal frame, this will be the only frame.
9e2b097b 34(defvar initial-frame-alist '((minibuffer . t))
dc6d9681 35 "Alist of values used when creating the initial emacs text frame.
64c669bc 36These may be set in your init file, like this:
dc6d9681 37 (setq initial-frame-alist '((top . 1) (left . 1) (width . 80) (height . 55)))
7eadab74
JB
38If this requests a frame without a minibuffer, and you do not create a
39minibuffer frame on your own, one will be created, according to
40`minibuffer-frame-alist'.
dc6d9681 41These supercede the values given in frame-default-alist.")
64c669bc 42
7eadab74 43(defvar minibuffer-frame-alist '((width . 80) (height . 2))
dc6d9681 44 "Alist of values to apply to a minibuffer frame.
64c669bc 45These may be set in your init file, like this:
dc6d9681 46 (setq minibuffer-frame-alist
7eadab74 47 '((top . 1) (left . 1) (width . 80) (height . 2)))
dc6d9681 48These supercede the values given in default-frame-alist.")
64c669bc 49
dc6d9681
JB
50(defvar pop-up-frame-alist nil
51 "Alist of values used when creating pop-up frames.
52Pop-up frames are used for completions, help, and the like.
64c669bc 53This variable can be set in your init file, like this:
dc6d9681
JB
54 (setq pop-up-frame-alist '((width . 80) (height . 20)))
55These supercede the values given in default-frame-alist.")
64c669bc 56
dc6d9681 57(setq pop-up-frame-function
64c669bc 58 (function (lambda ()
dc6d9681 59 (new-frame pop-up-frame-alist))))
64c669bc
JB
60
61\f
dc6d9681 62;;;; Arrangement of frames at startup
64c669bc
JB
63
64;;; 1) Load the window system startup file from the lisp library and read the
65;;; high-priority arguments (-q and the like). The window system startup
dc6d9681 66;;; file should create any frames specified in the window system defaults.
64c669bc 67;;;
dc6d9681 68;;; 2) If no frames have been opened, we open an initial text frame.
64c669bc
JB
69;;;
70;;; 3) Once the init file is done, we apply any newly set parameters
dc6d9681 71;;; in initial-frame-alist to the frame.
64c669bc 72
dc6d9681
JB
73(add-hook 'before-init-hook 'frame-initialize)
74(add-hook 'window-setup-hook 'frame-notice-user-settings)
64c669bc 75
dc6d9681
JB
76;;; If we create the initial frame, this is it.
77(defvar frame-initial-frame nil)
64c669bc
JB
78
79;;; startup.el calls this function before loading the user's init
dc6d9681 80;;; file - if there is no frame with a minibuffer open now, create
64c669bc 81;;; one to display messages while loading the init file.
dc6d9681 82(defun frame-initialize ()
64c669bc
JB
83
84 ;; Are we actually running under a window system at all?
85 (if (and window-system (not noninteractive))
7eadab74
JB
86 (progn
87 ;; If there is no frame with a minibuffer besides the terminal
88 ;; frame, then we need to create the opening frame. Make sure
89 ;; it has a minibuffer, but let initial-frame-alist omit the
90 ;; minibuffer spec.
91 (or (delq terminal-frame (minibuffer-frame-list))
dc6d9681
JB
92 (setq default-minibuffer-frame
93 (setq frame-initial-frame
94 (new-frame initial-frame-alist))))
7eadab74 95
dc6d9681
JB
96 ;; At this point, we know that we have a frame open, so we
97 ;; can delete the terminal frame.
98 (delete-frame terminal-frame)
99 (setq terminal-frame nil))
64c669bc
JB
100
101 ;; No, we're not running a window system. Arrange to cause errors.
dc6d9681 102 (setq frame-creation-function
9198945a
MB
103 (function
104 (lambda (parameters)
105 (error
8290babd 106 "Can't create multiple frames without a window system"))))))
64c669bc 107
7eadab74
JB
108;;; startup.el calls this function after loading the user's init
109;;; file. Now default-frame-alist and initial-frame-alist contain
110;;; information to which we must react; do what needs to be done.
dc6d9681 111(defun frame-notice-user-settings ()
7eadab74
JB
112
113 ;; Creating and deleting frames may shift the selected frame around,
114 ;; and thus the current buffer. Protect against that. We don't
115 ;; want to use save-excursion here, because that may also try to set
116 ;; the buffer of the selected window, which fails when the selected
117 ;; window is the minibuffer.
118 (let ((old-buffer (current-buffer)))
119
120 ;; If the initial frame is still around, apply initial-frame-alist
121 ;; and default-frame-alist to it.
122 (if (frame-live-p frame-initial-frame)
123
124 ;; The initial frame we create above always has a minibuffer.
125 ;; If the user wants to remove it, or make it a minibuffer-only
126 ;; frame, then we'll have to delete the current frame and make a
127 ;; new one; you can't remove or add a root window to/from an
128 ;; existing frame.
129 ;;
ec558adc
JB
130 ;; NOTE: default-frame-alist was nil when we created the
131 ;; existing frame. We need to explicitly include
132 ;; default-frame-alist in the parameters of the screen we
133 ;; create here, so that its new value, gleaned from the user's
134 ;; .emacs file, will be applied to the existing screen.
7eadab74
JB
135 (if (not (eq (cdr (or (assq 'minibuffer initial-frame-alist)
136 (assq 'minibuffer default-frame-alist)
137 '(minibuffer . t)))
138 t))
139 ;; Create the new frame.
140 (let ((new
141 (new-frame
142 (append initial-frame-alist
143 default-frame-alist
144 (frame-parameters frame-initial-frame)))))
145
146 ;; The initial frame, which we are about to delete, may be
147 ;; the only frame with a minibuffer. If it is, create a
148 ;; new one.
149 (or (delq frame-initial-frame (minibuffer-frame-list))
150 (new-frame (append minibuffer-frame-alist
151 '((minibuffer . only)))))
152
153 ;; If the initial frame is serving as a surrogate
154 ;; minibuffer frame for any frames, we need to wean them
155 ;; onto a new frame. The default-minibuffer-frame
156 ;; variable must be handled similarly.
157 (let ((users-of-initial
158 (filtered-frame-list
159 (function (lambda (frame)
160 (and (not (eq frame frame-initial-frame))
161 (eq (window-frame
162 (minibuffer-window frame))
163 frame-initial-frame)))))))
164 (if (or users-of-initial
165 (eq default-minibuffer-frame frame-initial-frame))
166
167 ;; Choose an appropriate frame. Prefer frames which
168 ;; are only minibuffers.
169 (let* ((new-surrogate
170 (car
171 (or (filtered-frame-list
172 (function
173 (lambda (frame)
174 (eq (cdr (assq 'minibuffer
175 (frame-parameters frame)))
176 'only))))
177 (minibuffer-frame-list))))
178 (new-minibuffer (minibuffer-window new-surrogate)))
179
180 (if (eq default-minibuffer-frame frame-initial-frame)
181 (setq default-minibuffer-frame new-surrogate))
182
183 ;; Wean the frames using frame-initial-frame as
184 ;; their minibuffer frame.
185 (mapcar
186 (function
187 (lambda (frame)
188 (modify-frame-parameters
189 frame (list (cons 'minibuffer new-minibuffer)))))
190 users-of-initial))))
ec558adc
JB
191
192 ;; Redirect events enqueued at this frame to the new frame.
193 ;; Is this a good idea?
7eadab74 194 (redirect-frame-focus frame-initial-frame new)
ec558adc 195
7eadab74 196 ;; Finally, get rid of the old frame.
dc6d9681 197 (delete-frame frame-initial-frame))
7eadab74
JB
198
199 ;; Otherwise, we don't need all that rigamarole; just apply
200 ;; the new parameters.
dc6d9681 201 (modify-frame-parameters frame-initial-frame
ec558adc 202 (append initial-frame-alist
7eadab74 203 default-frame-alist))))
64c669bc 204
7eadab74
JB
205 ;; Restore the original buffer.
206 (set-buffer old-buffer)
207
208 ;; Make sure the initial frame can be GC'd if it is ever deleted.
209 (makunbound 'frame-initial-frame)))
64c669bc
JB
210
211\f
7eadab74 212;;;; Creation of additional frames, and other frame miscellanea
dc6d9681 213
7eadab74
JB
214;;; Return some frame other than the current frame, creating one if
215;;; neccessary. Note that the minibuffer frame, if separate, is not
216;;; considered (see next-frame).
7253d8e0 217(defun get-other-frame ()
dc6d9681
JB
218 (let ((s (if (equal (next-frame (selected-frame)) (selected-frame))
219 (new-frame)
220 (next-frame (selected-frame)))))
64c669bc
JB
221 s))
222
dc6d9681
JB
223(defun next-multiframe-window ()
224 "Select the next window, regardless of which frame it is on."
64c669bc
JB
225 (interactive)
226 (select-window (next-window (selected-window)
227 (> (minibuffer-depth) 0)
228 t)))
229
dc6d9681
JB
230(defun previous-multiframe-window ()
231 "Select the previous window, regardless of which frame it is on."
64c669bc
JB
232 (interactive)
233 (select-window (previous-window (selected-window)
234 (> (minibuffer-depth) 0)
235 t)))
236
dc6d9681
JB
237(defun new-frame (&optional parameters)
238 "Create a new frame, displaying the current buffer.
bc93c097 239
43a2e52c 240Optional argument PARAMETERS is an alist of parameters for the new
dc6d9681 241frame. Specifically, PARAMETERS is a list of pairs, each having one
43a2e52c
JB
242of the following forms:
243
dc6d9681 244(name . STRING) - The frame should be named STRING.
43a2e52c 245
dc6d9681 246(height . NUMBER) - The frame should be NUMBER text lines high. If
43a2e52c
JB
247 this parameter is present, the width parameter must also be
248 given.
249
dc6d9681 250(width . NUMBER) - The frame should be NUMBER characters in width.
43a2e52c
JB
251 If this parameter is present, the height parameter must also
252 be given.
253
dc6d9681
JB
254(minibuffer . t) - the frame should have a minibuffer
255(minibuffer . none) - the frame should have no minibuffer
256(minibuffer . only) - the frame should contain only a minibuffer
257(minibuffer . WINDOW) - the frame should use WINDOW as its minibuffer window.
43a2e52c
JB
258
259(NAME . VALUE), specifying the parameter and the value it should have.
260NAME should be one of the following symbols:
261 name VALUE
262
dc6d9681
JB
263The documentation for the function x-create-frame describes
264additional frame parameters that Emacs will recognize when running
43a2e52c 265under the X Window System."
64c669bc 266 (interactive)
dc6d9681 267 (funcall frame-creation-function parameters))
64c669bc 268
7eadab74
JB
269(defun filtered-frame-list (predicate)
270 "Return a list of all live frames which satisfy PREDICATE."
271 (let ((frames (frame-list))
272 good-frames)
273 (while (consp frames)
274 (if (funcall predicate (car frames))
275 (setq good-frames (cons (car frames) good-frames)))
276 (setq frames (cdr frames)))
277 good-frames))
278
279(defun minibuffer-frame-list ()
280 "Return a list of all frames with their own minibuffers."
281 (filtered-frame-list
282 (function (lambda (frame)
283 (eq frame (window-frame (minibuffer-window frame)))))))
284
64c669bc 285\f
dc6d9681
JB
286;;;; Frame configurations
287
288(defun current-frame-configuration ()
289 "Return a list describing the positions and states of all frames.
290Each element is a list of the form (FRAME ALIST WINDOW-CONFIG), where
291FRAME is a frame object, ALIST is an association list specifying
292some of FRAME's parameters, and WINDOW-CONFIG is a window
293configuration object for FRAME."
06b1a5ef 294 (mapcar (function
dc6d9681
JB
295 (lambda (frame)
296 (list frame
297 (frame-parameters frame)
298 (current-window-configuration frame))))
299 (frame-list)))
300
301(defun set-frame-configuration (configuration)
302 "Restore the frames to the state described by CONFIGURATION.
303Each frame listed in CONFIGURATION has its position, size, window
06b1a5ef 304configuration, and other parameters set as specified in CONFIGURATION."
dc6d9681 305 (let (frames-to-delete)
06b1a5ef 306 (mapcar (function
dc6d9681
JB
307 (lambda (frame)
308 (let ((parameters (assq frame configuration)))
06b1a5ef
JB
309 (if parameters
310 (progn
dc6d9681 311 (modify-frame-parameters frame (nth 1 parameters))
06b1a5ef 312 (set-window-configuration (nth 2 parameters)))
dc6d9681
JB
313 (setq frames-to-delete (cons frame frames-to-delete))))))
314 (frame-list))
315 (mapcar 'delete-frame frames-to-delete)))
64c669bc
JB
316
317\f
dc6d9681
JB
318;;;; Convenience functions for accessing and interactively changing
319;;;; frame parameters.
64c669bc 320
151bdc83 321(defun frame-height (&optional frame)
dc6d9681
JB
322 "Return number of lines available for display on FRAME.
323If FRAME is omitted, describe the currently selected frame."
151bdc83 324 (cdr (assq 'height (frame-parameters frame))))
dc6d9681
JB
325
326(defun frame-width (&optional frame)
327 "Return number of columns available for display on FRAME.
328If FRAME is omitted, describe the currently selected frame."
151bdc83 329 (cdr (assq 'width (frame-parameters frame))))
dc6d9681 330
64c669bc 331(defun set-default-font (font-name)
7eadab74
JB
332 "Set the font of the selected frame to FONT.
333When called interactively, prompt for the name of the font to use."
64c669bc 334 (interactive "sFont name: ")
dc6d9681 335 (modify-frame-parameters (selected-frame)
7eadab74 336 (list (cons 'font font-name))))
64c669bc 337
8290babd 338(defun set-background-color (color-name)
7eadab74
JB
339 "Set the background color of the selected frame to COLOR.
340When called interactively, prompt for the name of the color to use."
64c669bc 341 (interactive "sColor: ")
dc6d9681 342 (modify-frame-parameters (selected-frame)
7eadab74 343 (list (cons 'background-color color-name))))
64c669bc 344
8290babd 345(defun set-foreground-color (color-name)
7eadab74
JB
346 "Set the foreground color of the selected frame to COLOR.
347When called interactively, prompt for the name of the color to use."
64c669bc 348 (interactive "sColor: ")
dc6d9681 349 (modify-frame-parameters (selected-frame)
7eadab74 350 (list (cons 'foreground-color color-name))))
64c669bc
JB
351
352(defun set-cursor-color (color-name)
7eadab74
JB
353 "Set the text cursor color of the selected frame to COLOR.
354When called interactively, prompt for the name of the color to use."
64c669bc 355 (interactive "sColor: ")
dc6d9681 356 (modify-frame-parameters (selected-frame)
7eadab74 357 (list (cons 'cursor-color color-name))))
64c669bc
JB
358
359(defun set-pointer-color (color-name)
7eadab74
JB
360 "Set the color of the mouse pointer of the selected frame to COLOR.
361When called interactively, prompt for the name of the color to use."
64c669bc 362 (interactive "sColor: ")
dc6d9681 363 (modify-frame-parameters (selected-frame)
7eadab74
JB
364 (list (cons 'mouse-color color-name))))
365
8290babd 366(defun toggle-auto-raise (arg)
7eadab74
JB
367 "Toggle whether or not the selected frame should auto-raise.
368With arg, turn auto-raise mode on if and only if arg is positive."
369 (interactive "P")
370 (if (null arg)
371 (setq arg
372 (if (cdr (assq 'auto-raise (frame-parameters (selected-frame))))
373 -1 1)))
dc6d9681 374 (modify-frame-parameters (selected-frame)
7eadab74
JB
375 (list (cons 'auto-raise (> arg 0)))))
376
8290babd 377(defun toggle-auto-lower (arg)
7eadab74
JB
378 "Toggle whether or not the selected frame should auto-lower.
379With arg, turn auto-lower mode on if and only if arg is positive."
380 (interactive "P")
381 (if (null arg)
382 (setq arg
383 (if (cdr (assq 'auto-lower (frame-parameters (selected-frame))))
384 -1 1)))
dc6d9681 385 (modify-frame-parameters (selected-frame)
7eadab74
JB
386 (list (cons 'auto-lower (> arg 0)))))
387
8290babd 388(defun toggle-vertical-scroll-bar (arg)
7eadab74
JB
389 "Toggle whether or not the selected frame has vertical scrollbars.
390With arg, turn vertical scrollbars on if and only if arg is positive."
391 (interactive "P")
392 (if (null arg)
393 (setq arg
394 (if (cdr (assq 'vertical-scrollbars
395 (frame-parameters (selected-frame))))
396 -1 1)))
dc6d9681 397 (modify-frame-parameters (selected-frame)
7eadab74
JB
398 (list (cons 'vertical-scrollbars (> arg 0)))))
399
8290babd 400(defun toggle-horizontal-scroll-bar (arg)
7eadab74
JB
401 "Toggle whether or not the selected frame has horizontal scrollbars.
402With arg, turn horizontal scrollbars on if and only if arg is positive.
403Horizontal scrollbars aren't implemented yet."
404 (interactive "P")
8290babd 405 (error "Horizontal scroll bars aren't implemented yet"))
64c669bc 406
64c669bc 407\f
dc6d9681
JB
408;;;; Aliases for backward compatibility with Emacs 18.
409(fset 'screen-height 'frame-height)
410(fset 'screen-width 'frame-width)
9e2b097b
JB
411
412(defun set-screen-width (cols &optional pretend)
413 "Obsolete function to change the size of the screen to COLS columns.\n\
414Optional second arg non-nil means that redisplay should use COLS columns\n\
415but that the idea of the actual width of the frame should not be changed.\n\
416This function is provided only for compatibility with Emacs 18; new code\n\
fe668515 417should use `set-frame-width instead'."
9e2b097b
JB
418 (set-frame-width (selected-frame) cols pretend))
419
420(defun set-screen-height (lines &optional pretend)
421 "Obsolete function to change the height of the screen to LINES lines.\n\
422Optional second arg non-nil means that redisplay should use LINES lines\n\
423but that the idea of the actual height of the screen should not be changed.\n\
424This function is provided only for compatibility with Emacs 18; new code\n\
fe668515 425should use `set-frame-width' instead."
9e2b097b
JB
426 (set-frame-height (selected-frame) lines pretend))
427
428(make-obsolete 'screen-height 'frame-height)
429(make-obsolete 'screen-width 'frame-width)
430(make-obsolete 'set-screen-width 'set-frame-width)
431(make-obsolete 'set-screen-height 'set-frame-height)
dc6d9681
JB
432
433\f
64c669bc 434;;;; Key bindings
daa37602 435(defvar ctl-x-5-map (make-sparse-keymap)
dc6d9681 436 "Keymap for frame commands.")
daa37602
JB
437(fset 'ctl-x-5-prefix ctl-x-5-map)
438(define-key ctl-x-map "5" 'ctl-x-5-prefix)
64c669bc 439
dc6d9681
JB
440(define-key ctl-x-5-map "2" 'new-frame)
441(define-key ctl-x-5-map "0" 'delete-frame)
49116ac0 442
dc6d9681 443(provide 'frame)
c88ab9ce 444
dc6d9681 445;;; frame.el ends here