Commit | Line | Data |
---|---|---|
c88ab9ce ER |
1 | ;;; screen.el --- multi-screen management independent of window systems. |
2 | ||
49116ac0 | 3 | ;;;; Copyright (C) 1990, 1992 Free Software Foundation, Inc. |
64c669bc JB |
4 | |
5 | ;;; This file is part of GNU Emacs. | |
6 | ;;; | |
7 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | |
8 | ;;; it under the terms of the GNU General Public License as published by | |
9 | ;;; the Free Software Foundation; either version 1, or (at your option) | |
10 | ;;; any later version. | |
11 | ;;; | |
12 | ;;; GNU Emacs is distributed in the hope that it will be useful, | |
13 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ;;; GNU General Public License for more details. | |
16 | ;;; | |
17 | ;;; You should have received a copy of the GNU General Public License | |
18 | ;;; along with GNU Emacs; see the file COPYING. If not, write to | |
19 | ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | ||
64c669bc JB |
21 | (defvar screen-creation-function nil |
22 | "Window-system dependent function to call to create a new screen. | |
23 | The window system startup file should set this to its screen creation | |
24 | function, which should take an alist of parameters as its argument.") | |
25 | ||
26 | ;;; The default value for this must ask for a minibuffer. There must | |
27 | ;;; always exist a screen with a minibuffer, and after we delete the | |
28 | ;;; terminal screen, this will be the only screen. | |
29 | (defvar initial-screen-alist '((minibuffer . nil)) | |
30 | "Alist of values used when creating the initial emacs text screen. | |
31 | These may be set in your init file, like this: | |
32 | (setq initial-screen-alist '((top . 1) (left . 1) (width . 80) (height . 55))) | |
33 | These supercede the values given in screen-default-alist.") | |
34 | ||
35 | (defvar minibuffer-screen-alist nil | |
36 | "Alist of values to apply to a minibuffer screen. | |
37 | These may be set in your init file, like this: | |
38 | (setq minibuffer-screen-alist | |
39 | '((top . 1) (left . 1) (width . 80) (height . 1))) | |
40 | These supercede the values given in default-screen-alist.") | |
41 | ||
42 | (defvar pop-up-screen-alist nil | |
43 | "Alist of values used when creating pop-up screens. | |
44 | Pop-up screens are used for completions, help, and the like. | |
45 | This variable can be set in your init file, like this: | |
46 | (setq pop-up-screen-alist '((width . 80) (height . 20))) | |
47 | These supercede the values given in default-screen-alist.") | |
48 | ||
49 | (setq pop-up-screen-function | |
50 | (function (lambda () | |
51 | (new-screen pop-up-screen-alist)))) | |
52 | ||
53 | \f | |
54 | ;;;; Arrangement of screens at startup | |
55 | ||
56 | ;;; 1) Load the window system startup file from the lisp library and read the | |
57 | ;;; high-priority arguments (-q and the like). The window system startup | |
58 | ;;; file should create any screens specified in the window system defaults. | |
59 | ;;; | |
60 | ;;; 2) If no screens have been opened, we open an initial text screen. | |
61 | ;;; | |
62 | ;;; 3) Once the init file is done, we apply any newly set parameters | |
63 | ;;; in initial-screen-alist to the screen. | |
64 | ||
e3bd99f5 | 65 | (add-hook 'before-init-hook 'screen-initialize) |
64c669bc JB |
66 | (add-hook 'window-setup-hook 'screen-notice-user-settings) |
67 | ||
68 | ;;; If we create the initial screen, this is it. | |
69 | (defvar screen-initial-screen nil) | |
70 | ||
71 | ;;; startup.el calls this function before loading the user's init | |
72 | ;;; file - if there is no screen with a minibuffer open now, create | |
73 | ;;; one to display messages while loading the init file. | |
74 | (defun screen-initialize () | |
75 | ||
76 | ;; Are we actually running under a window system at all? | |
77 | (if (and window-system (not noninteractive)) | |
78 | (let ((screens (screen-list))) | |
79 | ||
80 | ;; Look for a screen that has a minibuffer. | |
81 | (while (and screens | |
82 | (or (eq (car screens) terminal-screen) | |
83 | (not (cdr (assq 'minibuffer | |
84 | (screen-parameters | |
85 | (car screens))))))) | |
86 | (setq screens (cdr screens))) | |
87 | ||
88 | ;; If there was none, then we need to create the opening screen. | |
89 | (or screens | |
df11cb7f | 90 | (setq default-minibuffer-screen |
64c669bc JB |
91 | (setq screen-initial-screen |
92 | (new-screen initial-screen-alist)))) | |
93 | ||
94 | ;; At this point, we know that we have a screen open, so we | |
95 | ;; can delete the terminal screen. | |
96 | (delete-screen terminal-screen) | |
97 | (setq terminal-screen nil)) | |
98 | ||
99 | ;; No, we're not running a window system. Arrange to cause errors. | |
100 | (setq screen-creation-function | |
9198945a MB |
101 | (function |
102 | (lambda (parameters) | |
103 | (error | |
104 | "Can't create multiple screens without a window system.")))))) | |
64c669bc JB |
105 | |
106 | ;;; startup.el calls this function after loading the user's init file. | |
107 | ;;; If we created a minibuffer before knowing if we had permission, we | |
108 | ;;; need to see if it should go away or change. Create a text screen | |
109 | ;;; here. | |
110 | (defun screen-notice-user-settings () | |
111 | (if screen-initial-screen | |
112 | (progn | |
113 | ||
114 | ;; If the user wants a minibuffer-only screen, we'll have to | |
115 | ;; make a new one; you can't remove or add a root window to/from | |
116 | ;; an existing screen. | |
117 | (if (eq (cdr (or (assq 'minibuffer initial-screen-alist) | |
118 | '(minibuffer . t))) | |
119 | 'only) | |
120 | (progn | |
df11cb7f JB |
121 | (setq default-minibuffer-screen |
122 | (new-screen | |
123 | (append initial-screen-alist | |
124 | (screen-parameters screen-initial-screen)))) | |
64c669bc JB |
125 | (delete-screen screen-initial-screen)) |
126 | (modify-screen-parameters screen-initial-screen | |
127 | initial-screen-alist)))) | |
128 | ||
129 | ;; Make sure the initial screen can be GC'd if it is ever deleted. | |
130 | (makunbound 'screen-initial-screen)) | |
131 | ||
132 | \f | |
133 | ;;;; Creation of additional screens | |
134 | ||
135 | ;;; Return some screen other than the current screen, | |
136 | ;;; creating one if neccessary. Note that the minibuffer screen, if | |
137 | ;;; separate, is not considered (see next-screen). | |
138 | (defun get-screen () | |
139 | (let ((s (if (equal (next-screen (selected-screen)) (selected-screen)) | |
140 | (new-screen) | |
141 | (next-screen (selected-screen))))) | |
142 | s)) | |
143 | ||
144 | (defun next-multiscreen-window () | |
145 | "Select the next window, regardless of which screen it is on." | |
146 | (interactive) | |
147 | (select-window (next-window (selected-window) | |
148 | (> (minibuffer-depth) 0) | |
149 | t))) | |
150 | ||
151 | (defun previous-multiscreen-window () | |
152 | "Select the previous window, regardless of which screen it is on." | |
153 | (interactive) | |
154 | (select-window (previous-window (selected-window) | |
155 | (> (minibuffer-depth) 0) | |
156 | t))) | |
157 | ||
158 | (defun new-screen (&optional parameters) | |
bc93c097 JB |
159 | "Create a new screen, displaying the current buffer. |
160 | ||
43a2e52c JB |
161 | Optional argument PARAMETERS is an alist of parameters for the new |
162 | screen. Specifically, PARAMETERS is a list of pairs, each having one | |
163 | of the following forms: | |
164 | ||
165 | (name . STRING) - The screen should be named STRING. | |
166 | ||
167 | (height . NUMBER) - The screen should be NUMBER text lines high. If | |
168 | this parameter is present, the width parameter must also be | |
169 | given. | |
170 | ||
171 | (width . NUMBER) - The screen should be NUMBER characters in width. | |
172 | If this parameter is present, the height parameter must also | |
173 | be given. | |
174 | ||
175 | (minibuffer . t) - the screen should have a minibuffer | |
176 | (minibuffer . none) - the screen should have no minibuffer | |
177 | (minibuffer . only) - the screen should contain only a minibuffer | |
178 | (minibuffer . WINDOW) - the screen should use WINDOW as its minibuffer window. | |
179 | ||
180 | (NAME . VALUE), specifying the parameter and the value it should have. | |
181 | NAME should be one of the following symbols: | |
182 | name VALUE | |
183 | ||
184 | The documentation for the function x-create-screen describes | |
185 | additional screen parameters that Emacs will recognize when running | |
186 | under the X Window System." | |
64c669bc JB |
187 | (interactive) |
188 | (funcall screen-creation-function parameters)) | |
189 | ||
190 | \f | |
191 | ;;;; Iconification | |
192 | ||
193 | ;;; A possible enhancement for the below: if you iconify a surrogate | |
194 | ;;; minibuffer screen, iconify all of its minibuffer's users too; | |
195 | ;;; de-iconify them as a group. This will need to wait until screens | |
196 | ;;; have mapping and unmapping hooks. | |
197 | ||
198 | (defun iconify () | |
199 | "Iconify or deiconify the selected screen." | |
200 | (interactive) | |
201 | (let ((screen (selected-screen))) | |
202 | (if (eq (screen-visible-p screen) t) | |
203 | (iconify-screen screen) | |
06b1a5ef JB |
204 | (make-screen-visible screen)))) |
205 | ||
206 | \f | |
207 | ;;;; Screen configurations | |
208 | ||
209 | (defun current-screen-configuration () | |
210 | "Return a list describing the positions and states of all screens. | |
211 | Each element is a list of the form (SCREEN ALIST WINDOW-CONFIG), where | |
212 | SCREEN is a screen object, ALIST is an association list specifying | |
213 | some of SCREEN's parameters, and WINDOW-CONFIG is a window | |
214 | configuration object for SCREEN." | |
215 | (mapcar (function | |
216 | (lambda (screen) | |
217 | (list screen | |
218 | (screen-parameters screen) | |
219 | (current-window-configuration screen)))) | |
220 | (screen-list))) | |
221 | ||
222 | (defun set-screen-configuration (configuration) | |
223 | "Restore the screens to the state described by CONFIGURATION. | |
224 | Each screen listed in CONFIGURATION has its position, size, window | |
225 | configuration, and other parameters set as specified in CONFIGURATION." | |
226 | (let (screens-to-delete) | |
227 | (mapcar (function | |
228 | (lambda (screen) | |
229 | (let ((parameters (assq screen configuration))) | |
230 | (if parameters | |
231 | (progn | |
232 | (modify-screen-parameters screen (nth 1 parameters)) | |
233 | (set-window-configuration (nth 2 parameters))) | |
234 | (setq screens-to-delete (cons screen screens-to-delete)))))) | |
235 | (screen-list)) | |
236 | (mapcar 'delete-screen screens-to-delete))) | |
64c669bc JB |
237 | |
238 | \f | |
239 | ;;;; Convenience functions for dynamically changing screen parameters | |
240 | ||
241 | (defun set-screen-height (h) | |
242 | (interactive "NHeight: ") | |
243 | (let* ((screen (selected-screen)) | |
244 | (width (cdr (assoc 'width (screen-parameters (selected-screen)))))) | |
245 | (set-screen-size (selected-screen) width h))) | |
246 | ||
247 | (defun set-screen-width (w) | |
248 | (interactive "NWidth: ") | |
249 | (let* ((screen (selected-screen)) | |
250 | (height (cdr (assoc 'height (screen-parameters (selected-screen)))))) | |
251 | (set-screen-size (selected-screen) w height))) | |
252 | ||
253 | (defun set-default-font (font-name) | |
254 | (interactive "sFont name: ") | |
255 | (modify-screen-parameters (selected-screen) | |
256 | (list (cons 'font font-name)))) | |
257 | ||
258 | (defun set-screen-background (color-name) | |
259 | (interactive "sColor: ") | |
260 | (modify-screen-parameters (selected-screen) | |
261 | (list (cons 'background-color color-name)))) | |
262 | ||
263 | (defun set-screen-foreground (color-name) | |
264 | (interactive "sColor: ") | |
265 | (modify-screen-parameters (selected-screen) | |
266 | (list (cons 'foreground-color color-name)))) | |
267 | ||
268 | (defun set-cursor-color (color-name) | |
269 | (interactive "sColor: ") | |
270 | (modify-screen-parameters (selected-screen) | |
271 | (list (cons 'cursor-color color-name)))) | |
272 | ||
273 | (defun set-pointer-color (color-name) | |
274 | (interactive "sColor: ") | |
275 | (modify-screen-parameters (selected-screen) | |
276 | (list (cons 'mouse-color color-name)))) | |
277 | ||
278 | (defun set-auto-raise (toggle) | |
279 | (interactive "xt or nil? ") | |
280 | (modify-screen-parameters (selected-screen) | |
281 | (list (cons 'auto-raise toggle)))) | |
282 | ||
283 | (defun set-auto-lower (toggle) | |
284 | (interactive "xt or nil? ") | |
285 | (modify-screen-parameters (selected-screen) | |
286 | (list (cons 'auto-lower toggle)))) | |
287 | ||
288 | (defun set-vertical-bar (toggle) | |
289 | (interactive "xt or nil? ") | |
290 | (modify-screen-parameters (selected-screen) | |
291 | (list (cons 'vertical-scroll-bar toggle)))) | |
292 | ||
293 | (defun set-horizontal-bar (toggle) | |
294 | (interactive "xt or nil? ") | |
295 | (modify-screen-parameters (selected-screen) | |
296 | (list (cons 'horizontal-scroll-bar toggle)))) | |
297 | \f | |
298 | ;;;; Key bindings | |
daa37602 JB |
299 | (defvar ctl-x-5-map (make-sparse-keymap) |
300 | "Keymap for screen commands.") | |
301 | (fset 'ctl-x-5-prefix ctl-x-5-map) | |
302 | (define-key ctl-x-map "5" 'ctl-x-5-prefix) | |
64c669bc | 303 | |
87ef29fd JB |
304 | (define-key ctl-x-5-map "2" 'new-screen) |
305 | (define-key ctl-x-5-map "0" 'delete-screen) | |
49116ac0 JB |
306 | |
307 | (provide 'screen) | |
c88ab9ce ER |
308 | |
309 | ;;; screen.el ends here |