(xmenu_show): Enable asynchronous events.
[bpt/emacs.git] / src / frame.c
CommitLineData
ff11dfa1 1/* Generic frame functions.
c6c5df7f 2 Copyright (C) 1993 Free Software Foundation.
dc6f92b8
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
1113d9db 8the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
d5e7c279
JB
20#include <stdio.h>
21
18160b98 22#include <config.h>
cc38027b
JB
23#include "lisp.h"
24#include "frame.h"
bc1ed486 25#include "termhooks.h"
e5d77022 26
ff11dfa1 27#ifdef MULTI_FRAME
e5d77022 28
bff19c8d 29#include "buffer.h"
dc6f92b8
JB
30#include "window.h"
31
2f0b07e0
JB
32/* These help us bind and responding to switch-frame events. */
33#include "commands.h"
34#include "keyboard.h"
35
dc6f92b8 36Lisp_Object Vemacs_iconified;
ff11dfa1
JB
37Lisp_Object Vframe_list;
38Lisp_Object Vterminal_frame;
39Lisp_Object Vdefault_minibuffer_frame;
40Lisp_Object Vdefault_frame_alist;
fd0c2bd1
JB
41
42/* Evaluate this expression to rebuild the section of syms_of_frame
43 that initializes and staticpros the symbols declared below. Note
44 that Emacs 18 has a bug that keeps C-x C-e from being able to
45 evaluate this expression.
46
47(progn
48 ;; Accumulate a list of the symbols we want to initialize from the
49 ;; declarations at the top of the file.
50 (goto-char (point-min))
51 (search-forward "/\*&&& symbols declared here &&&*\/\n")
52 (let (symbol-list)
53 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
54 (setq symbol-list
55 (cons (buffer-substring (match-beginning 1) (match-end 1))
56 symbol-list))
57 (forward-line 1))
58 (setq symbol-list (nreverse symbol-list))
59 ;; Delete the section of syms_of_... where we initialize the symbols.
60 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
61 (let ((start (point)))
62 (while (looking-at "^ Q")
63 (forward-line 2))
64 (kill-region start (point)))
65 ;; Write a new symbol initialization section.
66 (while symbol-list
67 (insert (format " %s = intern (\"" (car symbol-list)))
68 (let ((start (point)))
69 (insert (substring (car symbol-list) 1))
70 (subst-char-in-region start (point) ?_ ?-))
71 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
72 (setq symbol-list (cdr symbol-list)))))
73 */
74
75/*&&& symbols declared here &&&*/
76Lisp_Object Qframep;
dbc4e1c1 77Lisp_Object Qframe_live_p;
fd0c2bd1
JB
78Lisp_Object Qheight;
79Lisp_Object Qicon;
bc93c097 80Lisp_Object Qminibuffer;
fd0c2bd1
JB
81Lisp_Object Qmodeline;
82Lisp_Object Qname;
fd0c2bd1
JB
83Lisp_Object Qonly;
84Lisp_Object Qunsplittable;
fa8fdbf9 85Lisp_Object Qmenu_bar_lines;
fd0c2bd1
JB
86Lisp_Object Qwidth;
87Lisp_Object Qx;
f7af3f7b 88Lisp_Object Qvisible;
dc6f92b8
JB
89
90extern Lisp_Object Vminibuffer_list;
91extern Lisp_Object get_minibuffer ();
84386599
RS
92extern Lisp_Object Fhandle_switch_frame ();
93extern Lisp_Object Fredirect_frame_focus ();
dc6f92b8 94\f
ff11dfa1
JB
95DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
96 "Return non-nil if OBJECT is a frame.\n\
97Value is t for a termcap frame (a character-only terminal),\n\
98`x' for an Emacs frame that is really an X window.\n\
99Also see `live-frame-p'.")
f9898cc6
JB
100 (object)
101 Lisp_Object object;
dc6f92b8 102{
ff11dfa1 103 if (XTYPE (object) != Lisp_Frame)
dc6f92b8 104 return Qnil;
ff11dfa1 105 switch (XFRAME (object)->output_method)
dc6f92b8
JB
106 {
107 case output_termcap:
108 return Qt;
109 case output_x_window:
fd0c2bd1 110 return Qx;
dc6f92b8
JB
111 default:
112 abort ();
113 }
114}
115
dbc4e1c1 116DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
ff11dfa1
JB
117 "Return non-nil if OBJECT is a frame which has not been deleted.\n\
118Value is nil if OBJECT is not a live frame. If object is a live\n\
119frame, the return value indicates what sort of output device it is\n\
120displayed on. Value is t for a termcap frame (a character-only\n\
121terminal), `x' for an Emacs frame being displayed in an X window.")
f9898cc6
JB
122 (object)
123 Lisp_Object object;
124{
ff11dfa1
JB
125 return ((FRAMEP (object)
126 && FRAME_LIVE_P (XFRAME (object)))
127 ? Fframep (object)
f9898cc6
JB
128 : Qnil);
129}
130
ff11dfa1
JB
131struct frame *
132make_frame (mini_p)
dc6f92b8
JB
133 int mini_p;
134{
ff11dfa1
JB
135 Lisp_Object frame;
136 register struct frame *f;
dc6f92b8
JB
137 register Lisp_Object root_window;
138 register Lisp_Object mini_window;
139
ff11dfa1 140 frame = Fmake_vector (((sizeof (struct frame) - (sizeof (Lisp_Vector)
d5e7c279
JB
141 - sizeof (Lisp_Object)))
142 / sizeof (Lisp_Object)),
dc6f92b8 143 make_number (0));
ff11dfa1
JB
144 XSETTYPE (frame, Lisp_Frame);
145 f = XFRAME (frame);
146
147 f->cursor_x = 0;
148 f->cursor_y = 0;
149 f->current_glyphs = 0;
150 f->desired_glyphs = 0;
151 f->visible = 0;
323405de 152 f->async_visible = 0;
ff11dfa1
JB
153 f->display.nothing = 0;
154 f->iconified = 0;
323405de 155 f->async_iconified = 0;
ff11dfa1
JB
156 f->wants_modeline = 1;
157 f->auto_raise = 0;
158 f->auto_lower = 0;
159 f->no_split = 0;
160 f->garbaged = 0;
161 f->has_minibuffer = mini_p;
a42e9724 162 f->focus_frame = Qnil;
804518aa 163 f->explicit_name = 0;
fd2777e0
JB
164 f->can_have_scroll_bars = 0;
165 f->has_vertical_scroll_bars = 0;
ff11dfa1 166 f->param_alist = Qnil;
fd2777e0
JB
167 f->scroll_bars = Qnil;
168 f->condemned_scroll_bars = Qnil;
306cc902 169 f->face_alist = Qnil;
9dd935ee 170 f->menu_bar_items = Qnil;
dc6f92b8 171
cc38027b 172 root_window = make_window ();
dc6f92b8
JB
173 if (mini_p)
174 {
cc38027b 175 mini_window = make_window ();
dc6f92b8
JB
176 XWINDOW (root_window)->next = mini_window;
177 XWINDOW (mini_window)->prev = root_window;
178 XWINDOW (mini_window)->mini_p = Qt;
ff11dfa1
JB
179 XWINDOW (mini_window)->frame = frame;
180 f->minibuffer_window = mini_window;
dc6f92b8
JB
181 }
182 else
183 {
184 mini_window = Qnil;
185 XWINDOW (root_window)->next = Qnil;
ff11dfa1 186 f->minibuffer_window = Qnil;
dc6f92b8
JB
187 }
188
ff11dfa1 189 XWINDOW (root_window)->frame = frame;
dc6f92b8
JB
190
191 /* 10 is arbitrary,
192 just so that there is "something there."
ff11dfa1 193 Correct size will be set up later with change_frame_size. */
dc6f92b8 194
ff11dfa1
JB
195 f->width = 10;
196 f->height = 10;
dc6f92b8
JB
197
198 XFASTINT (XWINDOW (root_window)->width) = 10;
199 XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
200
201 if (mini_p)
202 {
203 XFASTINT (XWINDOW (mini_window)->width) = 10;
204 XFASTINT (XWINDOW (mini_window)->top) = 9;
205 XFASTINT (XWINDOW (mini_window)->height) = 1;
206 }
207
ff11dfa1 208 /* Choose a buffer for the frame's root window. */
5bce042c
JB
209 {
210 Lisp_Object buf;
211
212 XWINDOW (root_window)->buffer = Qt;
213 buf = Fcurrent_buffer ();
214 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
215 a space), try to find another one. */
216 if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
c3c73481 217 buf = Fother_buffer (buf, Qnil);
5bce042c
JB
218 Fset_window_buffer (root_window, buf);
219 }
220
dc6f92b8
JB
221 if (mini_p)
222 {
223 XWINDOW (mini_window)->buffer = Qt;
224 Fset_window_buffer (mini_window,
265a9e55 225 (NILP (Vminibuffer_list)
dc6f92b8
JB
226 ? get_minibuffer (0)
227 : Fcar (Vminibuffer_list)));
228 }
229
ff11dfa1
JB
230 f->root_window = root_window;
231 f->selected_window = root_window;
d5e7c279
JB
232 /* Make sure this window seems more recently used than
233 a newly-created, never-selected window. */
ff11dfa1 234 XFASTINT (XWINDOW (f->selected_window)->use_time) = ++window_select_count;
dc6f92b8 235
ff11dfa1 236 return f;
dc6f92b8
JB
237}
238\f
ff11dfa1 239/* Make a frame using a separate minibuffer window on another frame.
dc6f92b8
JB
240 MINI_WINDOW is the minibuffer window to use. nil means use the
241 default (the global minibuffer). */
242
ff11dfa1
JB
243struct frame *
244make_frame_without_minibuffer (mini_window)
dc6f92b8
JB
245 register Lisp_Object mini_window;
246{
ff11dfa1 247 register struct frame *f;
dc6f92b8
JB
248
249 /* Choose the minibuffer window to use. */
265a9e55 250 if (NILP (mini_window))
dc6f92b8 251 {
ff11dfa1
JB
252 if (XTYPE (Vdefault_minibuffer_frame) != Lisp_Frame)
253 error ("default-minibuffer-frame must be set when creating minibufferless frames");
254 if (! FRAME_LIVE_P (XFRAME (Vdefault_minibuffer_frame)))
255 error ("default-minibuffer-frame must be a live frame");
256 mini_window = XFRAME (Vdefault_minibuffer_frame)->minibuffer_window;
dc6f92b8
JB
257 }
258 else
259 {
774910eb 260 CHECK_LIVE_WINDOW (mini_window, 0);
dc6f92b8
JB
261 }
262
ff11dfa1
JB
263 /* Make a frame containing just a root window. */
264 f = make_frame (0);
dc6f92b8
JB
265
266 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 267 f->minibuffer_window = mini_window;
dc6f92b8 268 Fset_window_buffer (mini_window,
265a9e55 269 (NILP (Vminibuffer_list)
dc6f92b8
JB
270 ? get_minibuffer (0)
271 : Fcar (Vminibuffer_list)));
ff11dfa1 272 return f;
dc6f92b8
JB
273}
274
ff11dfa1 275/* Make a frame containing only a minibuffer window. */
dc6f92b8 276
ff11dfa1
JB
277struct frame *
278make_minibuffer_frame ()
dc6f92b8 279{
ff11dfa1 280 /* First make a frame containing just a root window, no minibuffer. */
dc6f92b8 281
ff11dfa1 282 register struct frame *f = make_frame (0);
dc6f92b8 283 register Lisp_Object mini_window;
ff11dfa1 284 register Lisp_Object frame;
dc6f92b8 285
ff11dfa1 286 XSET (frame, Lisp_Frame, f);
dc6f92b8 287
804518aa 288 f->auto_raise = 0;
ff11dfa1
JB
289 f->auto_lower = 0;
290 f->no_split = 1;
291 f->wants_modeline = 0;
292 f->has_minibuffer = 1;
dc6f92b8
JB
293
294 /* Now label the root window as also being the minibuffer.
295 Avoid infinite looping on the window chain by marking next pointer
296 as nil. */
297
ff11dfa1 298 mini_window = f->minibuffer_window = f->root_window;
dc6f92b8
JB
299 XWINDOW (mini_window)->mini_p = Qt;
300 XWINDOW (mini_window)->next = Qnil;
804518aa 301 XWINDOW (mini_window)->prev = Qnil;
ff11dfa1 302 XWINDOW (mini_window)->frame = frame;
dc6f92b8
JB
303
304 /* Put the proper buffer in that window. */
305
306 Fset_window_buffer (mini_window,
265a9e55 307 (NILP (Vminibuffer_list)
dc6f92b8
JB
308 ? get_minibuffer (0)
309 : Fcar (Vminibuffer_list)));
ff11dfa1 310 return f;
dc6f92b8
JB
311}
312\f
ff11dfa1 313/* Construct a frame that refers to the terminal (stdin and stdout). */
dc6f92b8 314
ff11dfa1
JB
315struct frame *
316make_terminal_frame ()
dc6f92b8 317{
ff11dfa1 318 register struct frame *f;
d063751a 319 Lisp_Object frame;
ff11dfa1
JB
320
321 Vframe_list = Qnil;
322 f = make_frame (1);
d063751a
RS
323
324 XSET (frame, Lisp_Frame, f);
325 Vframe_list = Fcons (frame, Vframe_list);
326
ff11dfa1 327 f->name = build_string ("terminal");
a42e9724 328 FRAME_SET_VISIBLE (f, 1);
ff11dfa1
JB
329 f->display.nothing = 1; /* Nonzero means frame isn't deleted. */
330 XSET (Vterminal_frame, Lisp_Frame, f);
331 return f;
dc6f92b8
JB
332}
333\f
0aed85f4
KH
334static Lisp_Object
335do_switch_frame (frame, no_enter, track)
ff11dfa1 336 Lisp_Object frame, no_enter;
0aed85f4 337 int track;
dc6f92b8 338{
2f0b07e0
JB
339 /* If FRAME is a switch-frame event, extract the frame we should
340 switch to. */
341 if (CONSP (frame)
342 && EQ (XCONS (frame)->car, Qswitch_frame)
343 && CONSP (XCONS (frame)->cdr))
344 frame = XCONS (XCONS (frame)->cdr)->car;
345
09907c3a
KH
346 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
347 a switch-frame event to arrive after a frame is no longer live,
348 especially when deleting the initial frame during startup. */
349 CHECK_FRAME (frame, 0);
350 if (! FRAME_LIVE_P (XFRAME (frame)))
351 return Qnil;
dc6f92b8 352
ff11dfa1
JB
353 if (selected_frame == XFRAME (frame))
354 return frame;
dc6f92b8 355
0aed85f4
KH
356 /* This is too greedy; it causes inappropriate focus redirection
357 that's hard to get rid of. */
358#if 0
a42e9724
JB
359 /* If a frame's focus has been redirected toward the currently
360 selected frame, we should change the redirection to point to the
361 newly selected frame. This means that if the focus is redirected
362 from a minibufferless frame to a surrogate minibuffer frame, we
363 can use `other-window' to switch between all the frames using
364 that minibuffer frame, and the focus redirection will follow us
365 around. */
0aed85f4
KH
366 if (track)
367 {
368 Lisp_Object tail;
a42e9724 369
0aed85f4
KH
370 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
371 {
372 Lisp_Object focus;
a42e9724 373
0aed85f4
KH
374 if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
375 abort ();
a42e9724 376
0aed85f4 377 focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
a42e9724 378
0aed85f4
KH
379 if (XTYPE (focus) == Lisp_Frame
380 && XFRAME (focus) == selected_frame)
381 Fredirect_frame_focus (XCONS (tail)->car, frame);
382 }
383 }
384#else /* ! 0 */
385 /* Instead, apply it only to the frame we're pointing to. */
386#ifdef HAVE_X_WINDOWS
387 if (track)
388 {
389 Lisp_Object focus, xfocus;
390
391 xfocus = x_get_focus_frame ();
392 if (FRAMEP (xfocus))
393 {
394 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
395 if (FRAMEP (focus) && XFRAME (focus) == selected_frame)
396 Fredirect_frame_focus (xfocus, frame);
397 }
398 }
399#endif /* HAVE_X_WINDOWS */
400#endif /* ! 0 */
a42e9724 401
ff11dfa1
JB
402 selected_frame = XFRAME (frame);
403 if (! FRAME_MINIBUF_ONLY_P (selected_frame))
404 last_nonminibuf_frame = selected_frame;
d5e7c279 405
ff11dfa1 406 Fselect_window (XFRAME (frame)->selected_window);
ff11dfa1 407 choose_minibuf_frame ();
dc6f92b8 408
074577b8 409 /* We want to make sure that the next event generates a frame-switch
eb8c3be9 410 event to the appropriate frame. This seems kludgy to me, but
074577b8
JB
411 before you take it out, make sure that evaluating something like
412 (select-window (frame-root-window (new-frame))) doesn't end up
413 with your typing being interpreted in the new frame instead of
414 the one you're actually typing in. */
fd2777e0 415 internal_last_event_frame = Qnil;
074577b8 416
ff11dfa1 417 return frame;
dc6f92b8
JB
418}
419
0aed85f4
KH
420DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
421 "Select the frame FRAME.\n\
422Subsequent editing commands apply to its selected window.\n\
423The selection of FRAME lasts until the next time the user does\n\
424something to select a different frame, or until the next time this\n\
425function is called.")
426 (frame, no_enter)
427 Lisp_Object frame, no_enter;
428{
429 return do_switch_frame (frame, no_enter, 1);
430}
431
432
433DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
434 "Handle a switch-frame event EVENT.\n\
435Switch-frame events are usually bound to this function.\n\
436A switch-frame event tells Emacs that the window manager has requested\n\
437that the user's events be directed to the frame mentioned in the event.\n\
438This function selects the selected window of the frame of EVENT.\n\
439\n\
440If EVENT is frame object, handle it as if it were a switch-frame event\n\
441to that frame.")
442 (frame, no_enter)
443 Lisp_Object frame, no_enter;
444{
445 return do_switch_frame (frame, no_enter, 0);
446}
447
448
ff11dfa1
JB
449DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
450 "Return the frame that is now selected.")
dc6f92b8
JB
451 ()
452{
453 Lisp_Object tem;
ff11dfa1 454 XSET (tem, Lisp_Frame, selected_frame);
dc6f92b8
JB
455 return tem;
456}
457
ff11dfa1
JB
458DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
459 "Return the frame object that window WINDOW is on.")
dc6f92b8
JB
460 (window)
461 Lisp_Object window;
462{
774910eb 463 CHECK_LIVE_WINDOW (window, 0);
ff11dfa1 464 return XWINDOW (window)->frame;
dc6f92b8
JB
465}
466
ff11dfa1 467DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
8693ca83
JB
468 "Returns the root-window of FRAME.\n\
469If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
470 (frame)
471 Lisp_Object frame;
dc6f92b8 472{
ff11dfa1
JB
473 if (NILP (frame))
474 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 475 else
ff11dfa1 476 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 477
ff11dfa1 478 return XFRAME (frame)->root_window;
dc6f92b8
JB
479}
480
ff11dfa1
JB
481DEFUN ("frame-selected-window", Fframe_selected_window,
482 Sframe_selected_window, 0, 1, 0,
8693ca83
JB
483 "Return the selected window of frame object FRAME.\n\
484If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
485 (frame)
486 Lisp_Object frame;
dc6f92b8 487{
ff11dfa1
JB
488 if (NILP (frame))
489 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 490 else
ff11dfa1 491 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 492
ff11dfa1 493 return XFRAME (frame)->selected_window;
dc6f92b8
JB
494}
495
ff11dfa1 496DEFUN ("frame-list", Fframe_list, Sframe_list,
dc6f92b8 497 0, 0, 0,
ff11dfa1 498 "Return a list of all frames.")
dc6f92b8
JB
499 ()
500{
ff11dfa1 501 return Fcopy_sequence (Vframe_list);
dc6f92b8
JB
502}
503
ff11dfa1 504/* Return the next frame in the frame list after FRAME.
ff11dfa1
JB
505 If MINIBUF is nil, exclude minibuffer-only frames.
506 If MINIBUF is a window, include only frames using that window for
d06a8a56 507 their minibuffer.
f7af3f7b
RS
508 If MINIBUF is `visible', include all visible frames.
509 Otherwise, include all frames. */
510
dc6f92b8 511Lisp_Object
ff11dfa1
JB
512next_frame (frame, minibuf)
513 Lisp_Object frame;
f9898cc6 514 Lisp_Object minibuf;
dc6f92b8
JB
515{
516 Lisp_Object tail;
517 int passed = 0;
518
ff11dfa1
JB
519 /* There must always be at least one frame in Vframe_list. */
520 if (! CONSP (Vframe_list))
f9898cc6
JB
521 abort ();
522
dbc4e1c1
JB
523 /* If this frame is dead, it won't be in Vframe_list, and we'll loop
524 forever. Forestall that. */
525 CHECK_LIVE_FRAME (frame, 0);
526
dc6f92b8 527 while (1)
ff11dfa1 528 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8 529 {
ab9f008d 530 Lisp_Object f;
d06a8a56 531
ab9f008d 532 f = XCONS (tail)->car;
dc6f92b8 533 if (passed)
d5e7c279 534 {
d06a8a56
JB
535 /* Decide whether this frame is eligible to be returned. */
536
537 /* If we've looped all the way around without finding any
538 eligible frames, return the original frame. */
539 if (EQ (f, frame))
540 return f;
541
542 /* Let minibuf decide if this frame is acceptable. */
543 if (NILP (minibuf))
544 {
545 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
546 return f;
547 }
f7af3f7b
RS
548 else if (EQ (minibuf, Qvisible))
549 {
550 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
551 if (FRAME_VISIBLE_P (XFRAME (f)))
552 return f;
553 }
554 else if (WINDOWP (minibuf))
d06a8a56
JB
555 {
556 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
557 return f;
558 }
559 else
ff11dfa1 560 return f;
d5e7c279 561 }
dc6f92b8 562
d06a8a56 563 if (EQ (frame, f))
dc6f92b8
JB
564 passed++;
565 }
566}
567
ff11dfa1 568/* Return the previous frame in the frame list before FRAME.
ff11dfa1
JB
569 If MINIBUF is nil, exclude minibuffer-only frames.
570 If MINIBUF is a window, include only frames using that window for
d06a8a56 571 their minibuffer.
f7af3f7b
RS
572 If MINIBUF is `visible', include all visible frames.
573 Otherwise, include all frames. */
574
dc6f92b8 575Lisp_Object
ff11dfa1
JB
576prev_frame (frame, minibuf)
577 Lisp_Object frame;
f9898cc6 578 Lisp_Object minibuf;
dc6f92b8
JB
579{
580 Lisp_Object tail;
581 Lisp_Object prev;
582
ff11dfa1
JB
583 /* There must always be at least one frame in Vframe_list. */
584 if (! CONSP (Vframe_list))
f9898cc6
JB
585 abort ();
586
dc6f92b8 587 prev = Qnil;
d06a8a56 588 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
f9898cc6 589 {
ab9f008d 590 Lisp_Object f;
f9898cc6 591
ab9f008d 592 f = XCONS (tail)->car;
d06a8a56
JB
593 if (XTYPE (f) != Lisp_Frame)
594 abort ();
f9898cc6 595
d06a8a56
JB
596 if (EQ (frame, f) && !NILP (prev))
597 return prev;
f9898cc6 598
d06a8a56
JB
599 /* Decide whether this frame is eligible to be returned,
600 according to minibuf. */
601 if (NILP (minibuf))
602 {
603 if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
604 prev = f;
f9898cc6 605 }
d06a8a56
JB
606 else if (XTYPE (minibuf) == Lisp_Window)
607 {
608 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
609 prev = f;
610 }
f7af3f7b
RS
611 else if (EQ (minibuf, Qvisible))
612 {
613 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
614 if (FRAME_VISIBLE_P (XFRAME (f)))
615 prev = f;
616 }
d06a8a56
JB
617 else
618 prev = f;
f9898cc6 619 }
d06a8a56
JB
620
621 /* We've scanned the entire list. */
622 if (NILP (prev))
623 /* We went through the whole frame list without finding a single
624 acceptable frame. Return the original frame. */
625 return frame;
626 else
627 /* There were no acceptable frames in the list before FRAME; otherwise,
628 we would have returned directly from the loop. Since PREV is the last
629 acceptable frame in the list, return it. */
630 return prev;
dc6f92b8
JB
631}
632
ef2c57ac 633
ff11dfa1
JB
634DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
635 "Return the next frame in the frame list after FRAME.\n\
a42e9724 636By default, skip minibuffer-only frames.\n\
d06a8a56 637If omitted, FRAME defaults to the selected frame.\n\
c08c95c7 638If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
8693ca83 639If MINIFRAME is a window, include only frames using that window for their\n\
d06a8a56 640minibuffer.\n\
f7af3f7b
RS
641If MINIFRAME is `visible', include all visible frames.\n\
642Otherwise, include all frames.")
ff11dfa1 643 (frame, miniframe)
8693ca83 644 Lisp_Object frame, miniframe;
dc6f92b8
JB
645{
646 Lisp_Object tail;
647
ff11dfa1
JB
648 if (NILP (frame))
649 XSET (frame, Lisp_Frame, selected_frame);
f9898cc6 650 else
ff11dfa1 651 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 652
ff11dfa1 653 return next_frame (frame, miniframe);
dc6f92b8 654}
dbc4e1c1 655
ef2c57ac
RM
656DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
657 "Return the previous frame in the frame list before FRAME.\n\
658By default, skip minibuffer-only frames.\n\
659If omitted, FRAME defaults to the selected frame.\n\
660If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
661If MINIFRAME is a window, include only frames using that window for their\n\
662minibuffer.\n\
f7af3f7b
RS
663If MINIFRAME is `visible', include all visible frames.\n\
664Otherwise, include all frames.")
ef2c57ac
RM
665 (frame, miniframe)
666 Lisp_Object frame, miniframe;
667{
668 Lisp_Object tail;
669
670 if (NILP (frame))
671 XSET (frame, Lisp_Frame, selected_frame);
672 else
673 CHECK_LIVE_FRAME (frame, 0);
674
675 return prev_frame (frame, miniframe);
676}
dc6f92b8 677\f
808c0f20
RS
678/* Return 1 if it is ok to delete frame F;
679 0 if all frames aside from F are invisible.
680 (Exception: if F is the terminal frame, and we are using X, return 1.) */
dc6f92b8 681
808c0f20
RS
682static int
683other_visible_frames (f)
684 FRAME_PTR f;
685{
686 /* We know the selected frame is visible,
687 so if F is some other frame, it can't be the sole visible one. */
688 if (f == selected_frame)
c08c95c7
RS
689 {
690 Lisp_Object frames;
691 int count = 0;
692
693 for (frames = Vframe_list;
694 CONSP (frames);
695 frames = XCONS (frames)->cdr)
696 {
ab9f008d 697 Lisp_Object this;
c08c95c7 698
ab9f008d 699 this = XCONS (frames)->car;
808c0f20
RS
700 /* Verify that the frame's window still exists
701 and we can still talk to it. And note any recent change
702 in visibility. */
5e7b7c5b
RS
703#ifdef HAVE_X_WINDOWS
704 if (FRAME_X_P (XFRAME (this)))
705 {
706 x_sync (this);
707 FRAME_SAMPLE_VISIBILITY (XFRAME (this));
708 }
709#endif
710
c08c95c7
RS
711 if (FRAME_VISIBLE_P (XFRAME (this))
712 || FRAME_ICONIFIED_P (XFRAME (this))
713 /* Allow deleting the terminal frame when at least
714 one X frame exists! */
9fbb139c 715 || (FRAME_X_P (XFRAME (this)) && !FRAME_X_P (f)))
c08c95c7
RS
716 count++;
717 }
808c0f20 718 return count > 1;
c08c95c7 719 }
808c0f20
RS
720 return 1;
721}
722
723DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
724 "Delete FRAME, permanently eliminating it from use.\n\
725If omitted, FRAME defaults to the selected frame.\n\
726A frame may not be deleted if its minibuffer is used by other frames.\n\
727Normally, you may not delete a frame if all other frames are invisible,\n\
728but if the second optional argument FORCE is non-nil, you may do so.")
729 (frame, force)
730 Lisp_Object frame, force;
731{
732 struct frame *f;
733
734 if (EQ (frame, Qnil))
735 {
736 f = selected_frame;
737 XSET (frame, Lisp_Frame, f);
738 }
739 else
740 {
741 CHECK_FRAME (frame, 0);
742 f = XFRAME (frame);
743 }
744
745 if (! FRAME_LIVE_P (f))
746 return Qnil;
747
748 if (NILP (force) && !other_visible_frames (f))
749 error ("Attempt to delete the sole visible or iconified frame");
d5e7c279 750
ff11dfa1
JB
751 /* Does this frame have a minibuffer, and is it the surrogate
752 minibuffer for any other frame? */
fd0c2bd1 753 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
dc6f92b8 754 {
ff11dfa1 755 Lisp_Object frames;
1113d9db 756
ff11dfa1
JB
757 for (frames = Vframe_list;
758 CONSP (frames);
759 frames = XCONS (frames)->cdr)
1113d9db 760 {
7a8cc307
RS
761 Lisp_Object this;
762 this = XCONS (frames)->car;
1113d9db 763
ff11dfa1
JB
764 if (! EQ (this, frame)
765 && EQ (frame,
7a8cc307
RS
766 WINDOW_FRAME (XWINDOW
767 (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
ff11dfa1 768 error ("Attempt to delete a surrogate minibuffer frame");
1113d9db 769 }
dc6f92b8
JB
770 }
771
ff11dfa1
JB
772 /* Don't let the frame remain selected. */
773 if (f == selected_frame)
0f85737c 774 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
dc6f92b8 775
ff11dfa1
JB
776 /* Don't allow minibuf_window to remain on a deleted frame. */
777 if (EQ (f->minibuffer_window, minibuf_window))
dc6f92b8 778 {
ff11dfa1 779 Fset_window_buffer (selected_frame->minibuffer_window,
dc6f92b8 780 XWINDOW (minibuf_window)->buffer);
ff11dfa1 781 minibuf_window = selected_frame->minibuffer_window;
dc6f92b8
JB
782 }
783
4a88b3b0
JB
784 /* Mark all the windows that used to be on FRAME as deleted, and then
785 remove the reference to them. */
786 delete_all_subwindows (XWINDOW (f->root_window));
787 f->root_window = Qnil;
788
ff11dfa1 789 Vframe_list = Fdelq (frame, Vframe_list);
a42e9724 790 FRAME_SET_VISIBLE (f, 0);
dc6f92b8 791
8678b9cc
JB
792 /* Since some events are handled at the interrupt level, we may get
793 an event for f at any time; if we zero out the frame's display
794 now, then we may trip up the event-handling code. Instead, we'll
795 promise that the display of the frame must be valid until we have
796 called the window-system-dependent frame destruction routine. */
dbc4e1c1
JB
797
798 /* I think this should be done with a hook. */
d5e7c279 799#ifdef HAVE_X_WINDOWS
fd0c2bd1 800 if (FRAME_X_P (f))
8678b9cc 801 x_destroy_window (f);
d5e7c279
JB
802#endif
803
8678b9cc
JB
804 f->display.nothing = 0;
805
ff11dfa1 806 /* If we've deleted the last_nonminibuf_frame, then try to find
d5e7c279 807 another one. */
ff11dfa1 808 if (f == last_nonminibuf_frame)
d5e7c279 809 {
ff11dfa1 810 Lisp_Object frames;
1113d9db 811
ff11dfa1 812 last_nonminibuf_frame = 0;
d5e7c279 813
ff11dfa1
JB
814 for (frames = Vframe_list;
815 CONSP (frames);
816 frames = XCONS (frames)->cdr)
d5e7c279 817 {
ff11dfa1
JB
818 f = XFRAME (XCONS (frames)->car);
819 if (!FRAME_MINIBUF_ONLY_P (f))
d5e7c279 820 {
ff11dfa1 821 last_nonminibuf_frame = f;
d5e7c279
JB
822 break;
823 }
824 }
825 }
dc6f92b8 826
ff11dfa1
JB
827 /* If we've deleted Vdefault_minibuffer_frame, try to find another
828 one. Prefer minibuffer-only frames, but also notice frames
1113d9db 829 with other windows. */
ff11dfa1 830 if (EQ (frame, Vdefault_minibuffer_frame))
1113d9db 831 {
ff11dfa1 832 Lisp_Object frames;
1113d9db 833
ff11dfa1 834 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
ab9f008d 835 Lisp_Object frame_with_minibuf;
1113d9db 836
ab9f008d 837 frame_with_minibuf = Qnil;
ff11dfa1
JB
838 for (frames = Vframe_list;
839 CONSP (frames);
840 frames = XCONS (frames)->cdr)
1113d9db 841 {
ab9f008d 842 Lisp_Object this;
1113d9db 843
ab9f008d 844 this = XCONS (frames)->car;
ff11dfa1 845 if (XTYPE (this) != Lisp_Frame)
1113d9db 846 abort ();
ff11dfa1 847 f = XFRAME (this);
1113d9db 848
fd0c2bd1 849 if (FRAME_HAS_MINIBUF_P (f))
1113d9db 850 {
ff11dfa1
JB
851 frame_with_minibuf = this;
852 if (FRAME_MINIBUF_ONLY_P (f))
1113d9db
JB
853 break;
854 }
855 }
856
ff11dfa1
JB
857 /* We know that there must be some frame with a minibuffer out
858 there. If this were not true, all of the frames present
1113d9db 859 would have to be minibufferless, which implies that at some
ff11dfa1 860 point their minibuffer frames must have been deleted, but
1113d9db 861 that is prohibited at the top; you can't delete surrogate
ff11dfa1
JB
862 minibuffer frames. */
863 if (NILP (frame_with_minibuf))
1113d9db
JB
864 abort ();
865
ff11dfa1 866 Vdefault_minibuffer_frame = frame_with_minibuf;
1113d9db
JB
867 }
868
dc6f92b8
JB
869 return Qnil;
870}
871\f
872/* Return mouse position in character cell units. */
873
f9898cc6 874DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
ff11dfa1 875 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
4f90516b
JB
876The position is given in character cells, where (0, 0) is the\n\
877upper-left corner.\n\
f9898cc6 878If Emacs is running on a mouseless terminal or hasn't been programmed\n\
ff11dfa1 879to read the mouse position, it returns the selected frame for FRAME\n\
f9898cc6
JB
880and nil for X and Y.")
881 ()
dc6f92b8 882{
ff11dfa1 883 FRAME_PTR f;
dbc4e1c1 884 Lisp_Object lispy_dummy;
fd2777e0 885 enum scroll_bar_part party_dummy;
dbc4e1c1 886 Lisp_Object x, y;
5384466a 887 int col, row;
dbc4e1c1 888 unsigned long long_dummy;
dc6f92b8 889
c5074d8c
RS
890 f = selected_frame;
891 x = y = Qnil;
892
893 /* It's okay for the hook to refrain from storing anything. */
f9898cc6 894 if (mouse_position_hook)
dbc4e1c1
JB
895 (*mouse_position_hook) (&f,
896 &lispy_dummy, &party_dummy,
897 &x, &y,
898 &long_dummy);
5384466a
RS
899 col = XINT (x);
900 row = XINT (y);
901 glyph_to_pixel_coords (f, col, row, &col, &row);
902 XSETINT (x, col);
903 XSETINT (y, row);
dbc4e1c1 904 XSET (lispy_dummy, Lisp_Frame, f);
c5074d8c 905 return Fcons (lispy_dummy, Fcons (x, y));
dc6f92b8
JB
906}
907
908DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
1d7cc616 909 "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
ff11dfa1
JB
910WARNING: If you use this under X, you should do `unfocus-frame' afterwards.")
911 (frame, x, y)
912 Lisp_Object frame, x, y;
dc6f92b8 913{
ff11dfa1 914 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
915 CHECK_NUMBER (x, 2);
916 CHECK_NUMBER (y, 1);
917
dbc4e1c1 918 /* I think this should be done with a hook. */
dc6f92b8 919#ifdef HAVE_X_WINDOWS
fd0c2bd1 920 if (FRAME_X_P (XFRAME (frame)))
dc6f92b8 921 /* Warping the mouse will cause enternotify and focus events. */
ff11dfa1 922 x_set_mouse_position (XFRAME (frame), x, y);
dc6f92b8
JB
923#endif
924
925 return Qnil;
926}
927\f
ff11dfa1 928DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
fc25d15d 929 0, 1, "",
ff11dfa1 930 "Make the frame FRAME visible (assuming it is an X-window).\n\
8693ca83 931If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
932 (frame)
933 Lisp_Object frame;
dc6f92b8 934{
1aa66088 935 if (NILP (frame))
7500877e 936 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 937
ff11dfa1 938 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 939
dbc4e1c1 940 /* I think this should be done with a hook. */
fd0c2bd1
JB
941#ifdef HAVE_X_WINDOWS
942 if (FRAME_X_P (XFRAME (frame)))
02ff9dd5
RS
943 {
944 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
945 x_make_frame_visible (XFRAME (frame));
946 }
fd0c2bd1 947#endif
dc6f92b8 948
ff11dfa1 949 return frame;
dc6f92b8
JB
950}
951
ff11dfa1 952DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
808c0f20 953 0, 2, "",
8693ca83 954 "Make the frame FRAME invisible (assuming it is an X-window).\n\
808c0f20
RS
955If omitted, FRAME defaults to the currently selected frame.\n\
956Normally you may not make FRAME invisible if all other frames are invisible,\n\
957but if the second optional argument FORCE is non-nil, you may do so.")
958 (frame, force)
959 Lisp_Object frame, force;
dc6f92b8 960{
1aa66088 961 if (NILP (frame))
7500877e 962 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 963
ff11dfa1 964 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 965
808c0f20
RS
966 if (NILP (force) && !other_visible_frames (XFRAME (frame)))
967 error ("Attempt to make invisible the sole visible or iconified frame");
968
9c394f17
RS
969 /* Don't let the frame remain selected. */
970 if (XFRAME (frame) == selected_frame)
971 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
972
973 /* Don't allow minibuf_window to remain on a deleted frame. */
974 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
975 {
976 Fset_window_buffer (selected_frame->minibuffer_window,
977 XWINDOW (minibuf_window)->buffer);
978 minibuf_window = selected_frame->minibuffer_window;
979 }
980
dbc4e1c1 981 /* I think this should be done with a hook. */
fd0c2bd1
JB
982#ifdef HAVE_X_WINDOWS
983 if (FRAME_X_P (XFRAME (frame)))
ff11dfa1 984 x_make_frame_invisible (XFRAME (frame));
fd0c2bd1 985#endif
dc6f92b8
JB
986
987 return Qnil;
988}
989
ff11dfa1 990DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
1aa66088 991 0, 1, "",
8693ca83
JB
992 "Make the frame FRAME into an icon.\n\
993If omitted, FRAME defaults to the currently selected frame.")
ff11dfa1
JB
994 (frame)
995 Lisp_Object frame;
dc6f92b8 996{
1aa66088 997 if (NILP (frame))
7500877e 998 XSET (frame, Lisp_Frame, selected_frame);
1aa66088 999
ff11dfa1 1000 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 1001
9c394f17
RS
1002 /* Don't let the frame remain selected. */
1003 if (XFRAME (frame) == selected_frame)
1004 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
1005
1006 /* Don't allow minibuf_window to remain on a deleted frame. */
1007 if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
1008 {
1009 Fset_window_buffer (selected_frame->minibuffer_window,
1010 XWINDOW (minibuf_window)->buffer);
1011 minibuf_window = selected_frame->minibuffer_window;
1012 }
1013
dbc4e1c1 1014 /* I think this should be done with a hook. */
fd0c2bd1
JB
1015#ifdef HAVE_X_WINDOWS
1016 if (FRAME_X_P (XFRAME (frame)))
ff11dfa1 1017 x_iconify_frame (XFRAME (frame));
fd0c2bd1 1018#endif
dc6f92b8
JB
1019
1020 return Qnil;
1021}
1022
ff11dfa1 1023DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
dc6f92b8 1024 1, 1, 0,
ff11dfa1
JB
1025 "Return t if FRAME is now \"visible\" (actually in use for display).\n\
1026A frame that is not \"visible\" is not updated and, if it works through\n\
dc6f92b8 1027a window system, it may not show at all.\n\
fd0c2bd1 1028Return the symbol `icon' if frame is visible only as an icon.")
ff11dfa1
JB
1029 (frame)
1030 Lisp_Object frame;
dc6f92b8 1031{
ff11dfa1 1032 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8 1033
5c044f55
RS
1034 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1035
a42e9724 1036 if (FRAME_VISIBLE_P (XFRAME (frame)))
dc6f92b8 1037 return Qt;
a42e9724 1038 if (FRAME_ICONIFIED_P (XFRAME (frame)))
fd0c2bd1 1039 return Qicon;
dc6f92b8
JB
1040 return Qnil;
1041}
1042
ff11dfa1 1043DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
dc6f92b8 1044 0, 0, 0,
ff11dfa1 1045 "Return a list of all frames now \"visible\" (being updated).")
dc6f92b8
JB
1046 ()
1047{
ff11dfa1
JB
1048 Lisp_Object tail, frame;
1049 struct frame *f;
dc6f92b8
JB
1050 Lisp_Object value;
1051
1052 value = Qnil;
ff11dfa1 1053 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8 1054 {
ff11dfa1
JB
1055 frame = XCONS (tail)->car;
1056 if (XTYPE (frame) != Lisp_Frame)
dc6f92b8 1057 continue;
ff11dfa1 1058 f = XFRAME (frame);
a42e9724 1059 if (FRAME_VISIBLE_P (f))
ff11dfa1 1060 value = Fcons (frame, value);
dc6f92b8
JB
1061 }
1062 return value;
1063}
d5e7c279
JB
1064
1065
b49f5578 1066DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 1, 1, 0,
dbc4e1c1
JB
1067 "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
1068If FRAME is invisible, make it visible.\n\
1069If Emacs is displaying on an ordinary terminal or some other device which\n\
1070doesn't support multiple overlapping frames, this function does nothing.")
1071 (frame)
1072 Lisp_Object frame;
1073{
1074 CHECK_LIVE_FRAME (frame, 0);
8a981af5
RS
1075
1076 /* Do like the documentation says. */
1077 Fmake_frame_visible (frame);
1078
dbc4e1c1
JB
1079 if (frame_raise_lower_hook)
1080 (*frame_raise_lower_hook) (XFRAME (frame), 1);
1081
1082 return Qnil;
1083}
1084
b49f5578
JB
1085/* Should we have a corresponding function called Flower_Power? */
1086DEFUN ("lower-frame", Flower_frame, Slower_frame, 1, 1, 0,
dbc4e1c1
JB
1087 "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
1088If Emacs is displaying on an ordinary terminal or some other device which\n\
1089doesn't support multiple overlapping frames, this function does nothing.")
1090 (frame)
1091 Lisp_Object frame;
1092{
1093 CHECK_LIVE_FRAME (frame, 0);
1094
1095 if (frame_raise_lower_hook)
1096 (*frame_raise_lower_hook) (XFRAME (frame), 0);
1097
1098 return Qnil;
1099}
1100
d5e7c279 1101\f
ff11dfa1 1102DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
d5e7c279 1103 1, 2, 0,
ff11dfa1 1104 "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
a42e9724
JB
1105In other words, switch-frame events caused by events in FRAME will\n\
1106request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
1107FOCUS-FRAME after reading an event typed at FRAME.\n\
d5e7c279 1108\n\
a42e9724 1109If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
ff11dfa1 1110cancelled, and the frame again receives its own keystrokes.\n\
d5e7c279 1111\n\
a42e9724
JB
1112Focus redirection is useful for temporarily redirecting keystrokes to\n\
1113a surrogate minibuffer frame when a frame doesn't have its own\n\
1114minibuffer window.\n\
d5e7c279 1115\n\
a42e9724
JB
1116A frame's focus redirection can be changed by select-frame. If frame\n\
1117FOO is selected, and then a different frame BAR is selected, any\n\
1118frames redirecting their focus to FOO are shifted to redirect their\n\
1119focus to BAR. This allows focus redirection to work properly when the\n\
1120user switches from one frame to another using `select-window'.\n\
1121\n\
1122This means that a frame whose focus is redirected to itself is treated\n\
1123differently from a frame whose focus is redirected to nil; the former\n\
1124is affected by select-frame, while the latter is not.\n\
1125\n\
1126The redirection lasts until `redirect-frame-focus' is called to change it.")
ff11dfa1
JB
1127 (frame, focus_frame)
1128 Lisp_Object frame, focus_frame;
d5e7c279 1129{
13144095
JB
1130 /* Note that we don't check for a live frame here. It's reasonable
1131 to redirect the focus of a frame you're about to delete, if you
1132 know what other frame should receive those keystrokes. */
1133 CHECK_FRAME (frame, 0);
f9898cc6 1134
a42e9724 1135 if (! NILP (focus_frame))
ff11dfa1 1136 CHECK_LIVE_FRAME (focus_frame, 1);
d5e7c279 1137
ff11dfa1 1138 XFRAME (frame)->focus_frame = focus_frame;
d5e7c279 1139
9c394f17
RS
1140 /* I think this should be done with a hook. */
1141#ifdef HAVE_X_WINDOWS
1142 if (!NILP (focus_frame) && ! EQ (focus_frame, frame)
1143 && FRAME_X_P (XFRAME (focus_frame)))
1144 Ffocus_frame (focus_frame);
1145#endif
1146
ff11dfa1
JB
1147 if (frame_rehighlight_hook)
1148 (*frame_rehighlight_hook) ();
d5e7c279
JB
1149
1150 return Qnil;
1151}
1152
1153
ff11dfa1
JB
1154DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
1155 "Return the frame to which FRAME's keystrokes are currently being sent.\n\
a42e9724 1156This returns nil if FRAME's focus is not redirected.\n\
ff11dfa1
JB
1157See `redirect-frame-focus'.")
1158 (frame)
1159 Lisp_Object frame;
d5e7c279 1160{
ff11dfa1 1161 CHECK_LIVE_FRAME (frame, 0);
a42e9724 1162
ff11dfa1 1163 return FRAME_FOCUS_FRAME (XFRAME (frame));
d5e7c279
JB
1164}
1165
1166
dc6f92b8
JB
1167\f
1168Lisp_Object
ff11dfa1
JB
1169get_frame_param (frame, prop)
1170 register struct frame *frame;
dc6f92b8
JB
1171 Lisp_Object prop;
1172{
1173 register Lisp_Object tem;
1174
ff11dfa1 1175 tem = Fassq (prop, frame->param_alist);
dc6f92b8
JB
1176 if (EQ (tem, Qnil))
1177 return tem;
1178 return Fcdr (tem);
1179}
1180
1181void
fd0c2bd1 1182store_in_alist (alistptr, prop, val)
dc6f92b8 1183 Lisp_Object *alistptr, val;
fd0c2bd1 1184 Lisp_Object prop;
dc6f92b8
JB
1185{
1186 register Lisp_Object tem;
dc6f92b8 1187
dc6f92b8
JB
1188 tem = Fassq (prop, *alistptr);
1189 if (EQ (tem, Qnil))
1190 *alistptr = Fcons (Fcons (prop, val), *alistptr);
1191 else
1192 Fsetcdr (tem, val);
1193}
1194
1195void
ff11dfa1
JB
1196store_frame_param (f, prop, val)
1197 struct frame *f;
dc6f92b8
JB
1198 Lisp_Object prop, val;
1199{
1200 register Lisp_Object tem;
1201
ff11dfa1 1202 tem = Fassq (prop, f->param_alist);
dc6f92b8 1203 if (EQ (tem, Qnil))
ff11dfa1 1204 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
dc6f92b8
JB
1205 else
1206 Fsetcdr (tem, val);
bc93c097
JB
1207
1208 if (EQ (prop, Qminibuffer)
1209 && XTYPE (val) == Lisp_Window)
1210 {
1211 if (! MINI_WINDOW_P (XWINDOW (val)))
1212 error ("Surrogate minibuffer windows must be minibuffer windows.");
1213
fd0c2bd1 1214 if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
1fb2d074 1215 error ("can't change the surrogate minibuffer of a frame with its own minibuffer");
bc93c097
JB
1216
1217 /* Install the chosen minibuffer window, with proper buffer. */
ff11dfa1 1218 f->minibuffer_window = val;
bc93c097 1219 }
dc6f92b8
JB
1220}
1221
ff11dfa1
JB
1222DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
1223 "Return the parameters-alist of frame FRAME.\n\
dc6f92b8 1224It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
dc6d9681
JB
1225The meaningful PARMs depend on the kind of frame.\n\
1226If FRAME is omitted, return information on the currently selected frame.")
ff11dfa1
JB
1227 (frame)
1228 Lisp_Object frame;
dc6f92b8
JB
1229{
1230 Lisp_Object alist;
ff11dfa1 1231 struct frame *f;
dc6f92b8 1232
ff11dfa1
JB
1233 if (EQ (frame, Qnil))
1234 f = selected_frame;
dc6f92b8
JB
1235 else
1236 {
ff11dfa1
JB
1237 CHECK_FRAME (frame, 0);
1238 f = XFRAME (frame);
dc6f92b8
JB
1239 }
1240
ff11dfa1 1241 if (f->display.nothing == 0)
dc6f92b8
JB
1242 return Qnil;
1243
ff11dfa1 1244 alist = Fcopy_alist (f->param_alist);
fd0c2bd1
JB
1245 store_in_alist (&alist, Qname, f->name);
1246 store_in_alist (&alist, Qheight, make_number (f->height));
1247 store_in_alist (&alist, Qwidth, make_number (f->width));
1248 store_in_alist (&alist, Qmodeline, (f->wants_modeline ? Qt : Qnil));
1249 store_in_alist (&alist, Qminibuffer,
39acc701 1250 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
fd0c2bd1
JB
1251 : (FRAME_MINIBUF_ONLY_P (f) ? Qonly
1252 : FRAME_MINIBUF_WINDOW (f))));
1253 store_in_alist (&alist, Qunsplittable, (f->no_split ? Qt : Qnil));
fa8fdbf9 1254 store_in_alist (&alist, Qmenu_bar_lines, (FRAME_MENU_BAR_LINES (f)));
fd0c2bd1 1255
dbc4e1c1 1256 /* I think this should be done with a hook. */
fd0c2bd1
JB
1257#ifdef HAVE_X_WINDOWS
1258 if (FRAME_X_P (f))
ff11dfa1 1259 x_report_frame_params (f, &alist);
fd0c2bd1 1260#endif
dc6f92b8
JB
1261 return alist;
1262}
1263
ff11dfa1
JB
1264DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
1265 Smodify_frame_parameters, 2, 2, 0,
1266 "Modify the parameters of frame FRAME according to ALIST.\n\
dc6f92b8
JB
1267ALIST is an alist of parameters to change and their new values.\n\
1268Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
ff11dfa1
JB
1269The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
1270 (frame, alist)
1271 Lisp_Object frame, alist;
dc6f92b8 1272{
fd0c2bd1 1273 FRAME_PTR f;
dc6f92b8
JB
1274 register Lisp_Object tail, elt, prop, val;
1275
ff11dfa1
JB
1276 if (EQ (frame, Qnil))
1277 f = selected_frame;
dc6f92b8
JB
1278 else
1279 {
ff11dfa1
JB
1280 CHECK_LIVE_FRAME (frame, 0);
1281 f = XFRAME (frame);
dc6f92b8
JB
1282 }
1283
dbc4e1c1 1284 /* I think this should be done with a hook. */
fd0c2bd1
JB
1285#ifdef HAVE_X_WINDOWS
1286 if (FRAME_X_P (f))
1287#if 1
1288 x_set_frame_parameters (f, alist);
1289#else
dc6f92b8
JB
1290 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
1291 {
1292 elt = Fcar (tail);
1293 prop = Fcar (elt);
1294 val = Fcdr (elt);
fd0c2bd1 1295 x_set_frame_param (f, prop, val, get_frame_param (f, prop));
ff11dfa1 1296 store_frame_param (f, prop, val);
dc6f92b8 1297 }
fd0c2bd1
JB
1298#endif
1299#endif
dc6f92b8
JB
1300
1301 return Qnil;
1302}
1303\f
a26a1f95
RS
1304DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
1305 0, 1, 0,
1306 "Height in pixels of a line in the font in frame FRAME.\n\
1307If FRAME is omitted, the selected frame is used.\n\
1308For a terminal frame, the value is always 1.")
ff11dfa1
JB
1309 (frame)
1310 Lisp_Object frame;
dc6f92b8 1311{
a26a1f95 1312 struct frame *f;
dc6f92b8 1313
a26a1f95
RS
1314 if (NILP (frame))
1315 f = selected_frame;
1316 else
1317 {
1318 CHECK_FRAME (frame, 0);
1319 f = XFRAME (frame);
1320 }
1321
1322#ifdef HAVE_X_WINDOWS
1323 if (FRAME_X_P (f))
1324 return make_number (x_char_height (f));
1325 else
dc6d9681 1326#endif
a26a1f95
RS
1327 return make_number (1);
1328}
dc6d9681 1329
dc6f92b8 1330
a26a1f95
RS
1331DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
1332 0, 1, 0,
1333 "Width in pixels of characters in the font in frame FRAME.\n\
1334If FRAME is omitted, the selected frame is used.\n\
1335The width is the same for all characters, because\n\
1336currently Emacs supports only fixed-width fonts.\n\
1337For a terminal screen, the value is always 1.")
1338 (frame)
1339 Lisp_Object frame;
dc6f92b8 1340{
a26a1f95
RS
1341 struct frame *f;
1342
1343 if (NILP (frame))
1344 f = selected_frame;
1345 else
1346 {
1347 CHECK_FRAME (frame, 0);
1348 f = XFRAME (frame);
1349 }
1350
1351#ifdef HAVE_X_WINDOWS
1352 if (FRAME_X_P (f))
1353 return make_number (x_char_width (f));
1354 else
1355#endif
1356 return make_number (1);
dc6f92b8
JB
1357}
1358
a26a1f95
RS
1359DEFUN ("frame-pixel-height", Fframe_pixel_height,
1360 Sframe_pixel_height, 0, 1, 0,
164a14ef
RS
1361 "Return a FRAME's height in pixels.\n\
1362For a terminal frame, the result really gives the height in characters.\n\
a26a1f95
RS
1363If FRAME is omitted, the selected frame is used.")
1364 (frame)
1365 Lisp_Object frame;
dc6f92b8 1366{
a26a1f95
RS
1367 struct frame *f;
1368
1369 if (NILP (frame))
1370 f = selected_frame;
1371 else
1372 {
1373 CHECK_FRAME (frame, 0);
1374 f = XFRAME (frame);
1375 }
1376
1377#ifdef HAVE_X_WINDOWS
1378 if (FRAME_X_P (f))
1379 return make_number (x_pixel_height (f));
1380 else
dc6d9681 1381#endif
a26a1f95
RS
1382 return make_number (FRAME_HEIGHT (f));
1383}
1384
1385DEFUN ("frame-pixel-width", Fframe_pixel_width,
1386 Sframe_pixel_width, 0, 1, 0,
1387 "Return FRAME's width in pixels.\n\
164a14ef 1388For a terminal frame, the result really gives the width in characters.\n\
a26a1f95
RS
1389If FRAME is omitted, the selected frame is used.")
1390 (frame)
1391 Lisp_Object frame;
1392{
1393 struct frame *f;
1394
1395 if (NILP (frame))
1396 f = selected_frame;
1397 else
1398 {
1399 CHECK_FRAME (frame, 0);
1400 f = XFRAME (frame);
1401 }
dc6f92b8 1402
a26a1f95
RS
1403#ifdef HAVE_X_WINDOWS
1404 if (FRAME_X_P (f))
1405 return make_number (x_pixel_width (f));
1406 else
1407#endif
1408 return make_number (FRAME_WIDTH (f));
1409}
1410\f
ff11dfa1
JB
1411DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1412 "Specify that the frame FRAME has LINES lines.\n\
dc6f92b8 1413Optional third arg non-nil means that redisplay should use LINES lines\n\
ff11dfa1
JB
1414but that the idea of the actual height of the frame should not be changed.")
1415 (frame, rows, pretend)
fd0c2bd1 1416 Lisp_Object frame, rows, pretend;
dc6f92b8 1417{
ff11dfa1 1418 register struct frame *f;
dc6f92b8
JB
1419
1420 CHECK_NUMBER (rows, 0);
ff11dfa1
JB
1421 if (NILP (frame))
1422 f = selected_frame;
dc6f92b8
JB
1423 else
1424 {
ff11dfa1
JB
1425 CHECK_LIVE_FRAME (frame, 0);
1426 f = XFRAME (frame);
dc6f92b8
JB
1427 }
1428
dbc4e1c1 1429 /* I think this should be done with a hook. */
fd0c2bd1
JB
1430#ifdef HAVE_X_WINDOWS
1431 if (FRAME_X_P (f))
dc6f92b8 1432 {
ff11dfa1 1433 if (XINT (rows) != f->width)
808c0f20 1434 x_set_window_size (f, 1, f->width, XINT (rows));
dc6f92b8
JB
1435 }
1436 else
fd0c2bd1
JB
1437#endif
1438 change_frame_size (f, XINT (rows), 0, !NILP (pretend), 0);
dc6f92b8
JB
1439 return Qnil;
1440}
1441
ff11dfa1
JB
1442DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1443 "Specify that the frame FRAME has COLS columns.\n\
dc6f92b8 1444Optional third arg non-nil means that redisplay should use COLS columns\n\
ff11dfa1
JB
1445but that the idea of the actual width of the frame should not be changed.")
1446 (frame, cols, pretend)
fd0c2bd1 1447 Lisp_Object frame, cols, pretend;
dc6f92b8 1448{
ff11dfa1 1449 register struct frame *f;
dc6f92b8 1450 CHECK_NUMBER (cols, 0);
ff11dfa1
JB
1451 if (NILP (frame))
1452 f = selected_frame;
dc6f92b8
JB
1453 else
1454 {
ff11dfa1
JB
1455 CHECK_LIVE_FRAME (frame, 0);
1456 f = XFRAME (frame);
dc6f92b8
JB
1457 }
1458
dbc4e1c1 1459 /* I think this should be done with a hook. */
fd0c2bd1
JB
1460#ifdef HAVE_X_WINDOWS
1461 if (FRAME_X_P (f))
dc6f92b8 1462 {
ff11dfa1 1463 if (XINT (cols) != f->width)
808c0f20 1464 x_set_window_size (f, 1, XINT (cols), f->height);
dc6f92b8
JB
1465 }
1466 else
fd0c2bd1
JB
1467#endif
1468 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0);
dc6f92b8
JB
1469 return Qnil;
1470}
1471
ff11dfa1
JB
1472DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
1473 "Sets size of FRAME to COLS by ROWS, measured in characters.")
1474 (frame, cols, rows)
1475 Lisp_Object frame, cols, rows;
dc6f92b8 1476{
ff11dfa1 1477 register struct frame *f;
dc6f92b8
JB
1478 int mask;
1479
ff11dfa1 1480 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1481 CHECK_NUMBER (cols, 2);
1482 CHECK_NUMBER (rows, 1);
ff11dfa1 1483 f = XFRAME (frame);
dc6f92b8 1484
dbc4e1c1 1485 /* I think this should be done with a hook. */
fd0c2bd1
JB
1486#ifdef HAVE_X_WINDOWS
1487 if (FRAME_X_P (f))
dc6f92b8 1488 {
ff11dfa1 1489 if (XINT (rows) != f->height || XINT (cols) != f->width)
808c0f20 1490 x_set_window_size (f, 1, XINT (cols), XINT (rows));
dc6f92b8
JB
1491 }
1492 else
fd0c2bd1
JB
1493#endif
1494 change_frame_size (f, XINT (rows), XINT (cols), 0, 0);
dc6f92b8
JB
1495
1496 return Qnil;
1497}
1498
ff11dfa1
JB
1499DEFUN ("set-frame-position", Fset_frame_position,
1500 Sset_frame_position, 3, 3, 0,
1501 "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
60bf8ee4
RS
1502This is actually the position of the upper left corner of the frame.\n\
1503Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
4524cb1c 1504the rightmost or bottommost possible position (that stays within the screen).")
ff11dfa1
JB
1505 (frame, xoffset, yoffset)
1506 Lisp_Object frame, xoffset, yoffset;
dc6f92b8 1507{
ff11dfa1 1508 register struct frame *f;
dc6f92b8
JB
1509 int mask;
1510
ff11dfa1 1511 CHECK_LIVE_FRAME (frame, 0);
dc6f92b8
JB
1512 CHECK_NUMBER (xoffset, 1);
1513 CHECK_NUMBER (yoffset, 2);
ff11dfa1 1514 f = XFRAME (frame);
dc6f92b8 1515
dbc4e1c1 1516 /* I think this should be done with a hook. */
fd0c2bd1
JB
1517#ifdef HAVE_X_WINDOWS
1518 if (FRAME_X_P (f))
ff11dfa1 1519 x_set_offset (f, XINT (xoffset), XINT (yoffset));
fd0c2bd1 1520#endif
dc6f92b8
JB
1521
1522 return Qt;
1523}
dc6d9681 1524
dc6f92b8 1525\f
ff11dfa1 1526choose_minibuf_frame ()
dc6f92b8 1527{
ff11dfa1
JB
1528 /* For lowest-level minibuf, put it on currently selected frame
1529 if frame has a minibuffer. */
d06a8a56 1530
dc6f92b8 1531 if (minibuf_level == 0
ff11dfa1 1532 && selected_frame != 0
d06a8a56 1533 && !EQ (minibuf_window, selected_frame->minibuffer_window))
dc6f92b8 1534 {
d06a8a56
JB
1535 /* I don't think that any frames may validly have a null minibuffer
1536 window anymore. */
1537 if (NILP (selected_frame->minibuffer_window))
1538 abort ();
1539
ff11dfa1 1540 Fset_window_buffer (selected_frame->minibuffer_window,
dc6f92b8 1541 XWINDOW (minibuf_window)->buffer);
ff11dfa1 1542 minibuf_window = selected_frame->minibuffer_window;
dc6f92b8
JB
1543 }
1544}
1545\f
ff11dfa1 1546syms_of_frame ()
dc6f92b8 1547{
fd0c2bd1 1548 /*&&& init symbols here &&&*/
ff11dfa1 1549 Qframep = intern ("framep");
ff11dfa1 1550 staticpro (&Qframep);
dbc4e1c1
JB
1551 Qframe_live_p = intern ("frame-live-p");
1552 staticpro (&Qframe_live_p);
fd0c2bd1
JB
1553 Qheight = intern ("height");
1554 staticpro (&Qheight);
1555 Qicon = intern ("icon");
1556 staticpro (&Qicon);
1557 Qminibuffer = intern ("minibuffer");
bc93c097 1558 staticpro (&Qminibuffer);
fd0c2bd1
JB
1559 Qmodeline = intern ("modeline");
1560 staticpro (&Qmodeline);
1561 Qname = intern ("name");
1562 staticpro (&Qname);
fd0c2bd1
JB
1563 Qonly = intern ("only");
1564 staticpro (&Qonly);
1565 Qunsplittable = intern ("unsplittable");
1566 staticpro (&Qunsplittable);
f7af3f7b
RS
1567 Qmenu_bar_lines = intern ("menu-bar-lines");
1568 staticpro (&Qmenu_bar_lines);
fd0c2bd1
JB
1569 Qwidth = intern ("width");
1570 staticpro (&Qwidth);
1571 Qx = intern ("x");
1572 staticpro (&Qx);
f7af3f7b
RS
1573 Qvisible = intern ("visible");
1574 staticpro (&Qvisible);
dc6f92b8 1575
ff11dfa1 1576 staticpro (&Vframe_list);
dc6f92b8 1577
ff11dfa1
JB
1578 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
1579 "The initial frame-object, which represents Emacs's stdout.");
dc6f92b8
JB
1580
1581 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
ff11dfa1 1582 "Non-nil if all of emacs is iconified and frame updates are not needed.");
dc6f92b8
JB
1583 Vemacs_iconified = Qnil;
1584
ff11dfa1
JB
1585 DEFVAR_LISP ("default-minibuffer-frame", &Vdefault_minibuffer_frame,
1586 "Minibufferless frames use this frame's minibuffer.\n\
f9898cc6 1587\n\
ff11dfa1 1588Emacs cannot create minibufferless frames unless this is set to an\n\
f9898cc6
JB
1589appropriate surrogate.\n\
1590\n\
1591Emacs consults this variable only when creating minibufferless\n\
ff11dfa1 1592frames; once the frame is created, it sticks with its assigned\n\
f9898cc6
JB
1593minibuffer, no matter what this variable is set to. This means that\n\
1594this variable doesn't necessarily say anything meaningful about the\n\
ff11dfa1 1595current set of frames, or where the minibuffer is currently being\n\
f9898cc6 1596displayed.");
ff11dfa1 1597 Vdefault_minibuffer_frame = Qnil;
dc6f92b8 1598
ff11dfa1
JB
1599 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
1600 "Alist of default values for frame creation.\n\
5bce042c 1601These may be set in your init file, like this:\n\
ff11dfa1 1602 (setq default-frame-alist '((width . 80) (height . 55)))\n\
5bce042c
JB
1603These override values given in window system configuration data, like\n\
1604X Windows' defaults database.\n\
ff11dfa1
JB
1605For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
1606For values specific to the separate minibuffer frame, see\n\
1607`minibuffer-frame-alist'.");
1608 Vdefault_frame_alist = Qnil;
1609
1610 defsubr (&Sframep);
dbc4e1c1 1611 defsubr (&Sframe_live_p);
0f85737c 1612 defsubr (&Shandle_switch_frame);
ff11dfa1
JB
1613 defsubr (&Sselect_frame);
1614 defsubr (&Sselected_frame);
1615 defsubr (&Swindow_frame);
1616 defsubr (&Sframe_root_window);
1617 defsubr (&Sframe_selected_window);
1618 defsubr (&Sframe_list);
1619 defsubr (&Snext_frame);
ef2c57ac 1620 defsubr (&Sprevious_frame);
ff11dfa1 1621 defsubr (&Sdelete_frame);
f9898cc6 1622 defsubr (&Smouse_position);
dc6f92b8
JB
1623 defsubr (&Sset_mouse_position);
1624#if 0
ff11dfa1
JB
1625 defsubr (&Sframe_configuration);
1626 defsubr (&Srestore_frame_configuration);
dc6f92b8 1627#endif
ff11dfa1
JB
1628 defsubr (&Smake_frame_visible);
1629 defsubr (&Smake_frame_invisible);
1630 defsubr (&Siconify_frame);
1631 defsubr (&Sframe_visible_p);
1632 defsubr (&Svisible_frame_list);
b49f5578
JB
1633 defsubr (&Sraise_frame);
1634 defsubr (&Slower_frame);
ff11dfa1
JB
1635 defsubr (&Sredirect_frame_focus);
1636 defsubr (&Sframe_focus);
1637 defsubr (&Sframe_parameters);
1638 defsubr (&Smodify_frame_parameters);
a26a1f95
RS
1639 defsubr (&Sframe_char_height);
1640 defsubr (&Sframe_char_width);
1641 defsubr (&Sframe_pixel_height);
1642 defsubr (&Sframe_pixel_width);
ff11dfa1
JB
1643 defsubr (&Sset_frame_height);
1644 defsubr (&Sset_frame_width);
1645 defsubr (&Sset_frame_size);
1646 defsubr (&Sset_frame_position);
dc6f92b8 1647}
e5d77022 1648
2f0b07e0
JB
1649keys_of_frame ()
1650{
0f85737c 1651 initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
2f0b07e0 1652}
a26a1f95 1653\f
d06a8a56 1654#else /* not MULTI_FRAME */
fd0c2bd1 1655
cc38027b
JB
1656/* If we're not using multi-frame stuff, we still need to provide some
1657 support functions. */
1658
91f5a8d7
KH
1659Lisp_Object Vterminal_frame;
1660
cc38027b
JB
1661/* Unless this function is defined, providing set-frame-height and
1662 set-frame-width doesn't help compatibility any, since they both
1663 want this as their first argument. */
1664DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
9597f4b8
KH
1665 /* Don't confuse make-docfile by having two doc strings for this function.
1666 make-docfile does not pay attention to #if, for good reason! */
1667 0)
cc38027b
JB
1668 ()
1669{
1670 Lisp_Object tem;
1671 XFASTINT (tem) = 0;
1672 return tem;
1673}
704a9b45 1674DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
9597f4b8
KH
1675 /* Don't confuse make-docfile by having two doc strings for this function.
1676 make-docfile does not pay attention to #if, for good reason! */
1677 0)
704a9b45
RS
1678 (object)
1679 Lisp_Object object;
1680{
1681 return Qnil;
1682}
fd0c2bd1
JB
1683
1684DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
9597f4b8
KH
1685 /* Don't confuse make-docfile by having two doc strings for this function.
1686 make-docfile does not pay attention to #if, for good reason! */
1687 0)
fd0c2bd1
JB
1688 (frame, rows, pretend)
1689 Lisp_Object frame, rows, pretend;
1690{
1691 CHECK_NUMBER (rows, 0);
1692
1693 change_frame_size (0, XINT (rows), 0, !NILP (pretend), 0);
1694 return Qnil;
1695}
1696
1697DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
9597f4b8
KH
1698 /* Don't confuse make-docfile by having two doc strings for this function.
1699 make-docfile does not pay attention to #if, for good reason! */
1700 0)
fd0c2bd1
JB
1701 (frame, cols, pretend)
1702 Lisp_Object frame, cols, pretend;
1703{
1704 CHECK_NUMBER (cols, 0);
1705
1706 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1707 return Qnil;
1708}
1709
1710DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
9597f4b8
KH
1711 /* Don't confuse make-docfile by having two doc strings for this function.
1712 make-docfile does not pay attention to #if, for good reason! */
1713 0)
fd0c2bd1
JB
1714 (frame, cols, rows)
1715 Lisp_Object frame, cols, rows;
1716{
1717 CHECK_NUMBER (cols, 2);
1718 CHECK_NUMBER (rows, 1);
1719
1720 change_frame_size (0, XINT (rows), XINT (cols), 0, 0);
1721
1722 return Qnil;
1723}
1724
48c9d487
JB
1725DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 1, 0,
1726 "Return number of lines available for display on FRAME.\n\
1727If FRAME is omitted, describe the currently selected frame.")
1728 (frame)
1729 Lisp_Object frame;
cc38027b
JB
1730{
1731 return make_number (FRAME_HEIGHT (selected_frame));
1732}
1733
48c9d487
JB
1734DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 1, 0,
1735 "Return number of columns available for display on FRAME.\n\
1736If FRAME is omitted, describe the currently selected frame.")
1737 (frame)
1738 Lisp_Object frame;
cc38027b
JB
1739{
1740 return make_number (FRAME_WIDTH (selected_frame));
1741}
1742
a26a1f95
RS
1743DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
1744 0, 1, 0,
9597f4b8
KH
1745 /* Don't confuse make-docfile by having two doc strings for this function.
1746 make-docfile does not pay attention to #if, for good reason! */
1747 0)
a26a1f95
RS
1748 (frame)
1749 Lisp_Object frame;
1750{
1751 return make_number (1);
1752}
1753
1754
1755DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
1756 0, 1, 0,
9597f4b8
KH
1757 /* Don't confuse make-docfile by having two doc strings for this function.
1758 make-docfile does not pay attention to #if, for good reason! */
1759 0)
a26a1f95
RS
1760 (frame)
1761 Lisp_Object frame;
1762{
1763 return make_number (1);
1764}
1765
1766DEFUN ("frame-pixel-height", Fframe_pixel_height,
1767 Sframe_pixel_height, 0, 1, 0,
9597f4b8
KH
1768 /* Don't confuse make-docfile by having two doc strings for this function.
1769 make-docfile does not pay attention to #if, for good reason! */
1770 0)
a26a1f95
RS
1771 (frame)
1772 Lisp_Object frame;
1773{
1774 return make_number (FRAME_HEIGHT (f));
1775}
1776
1777DEFUN ("frame-pixel-width", Fframe_pixel_width,
1778 Sframe_pixel_width, 0, 1, 0,
9597f4b8
KH
1779 /* Don't confuse make-docfile by having two doc strings for this function.
1780 make-docfile does not pay attention to #if, for good reason! */
1781 0)
a26a1f95
RS
1782 (frame)
1783 Lisp_Object frame;
1784{
1785 return make_number (FRAME_WIDTH (f));
1786}
1787
cc38027b
JB
1788/* These are for backward compatibility with Emacs 18. */
1789
fd0c2bd1
JB
1790DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
1791 "Tell redisplay that the screen has LINES lines.\n\
1792Optional second arg non-nil means that redisplay should use LINES lines\n\
1793but that the idea of the actual height of the screen should not be changed.")
1794 (lines, pretend)
1795 Lisp_Object lines, pretend;
1796{
1797 CHECK_NUMBER (lines, 0);
1798
1799 change_frame_size (0, XINT (lines), 0, !NILP (pretend), 0);
1800 return Qnil;
1801}
1802
1803DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
1804 "Tell redisplay that the screen has COLS columns.\n\
1805Optional second arg non-nil means that redisplay should use COLS columns\n\
1806but that the idea of the actual width of the screen should not be changed.")
1807 (cols, pretend)
1808 Lisp_Object cols, pretend;
1809{
1810 CHECK_NUMBER (cols, 0);
1811
1812 change_frame_size (0, 0, XINT (cols), !NILP (pretend), 0);
1813 return Qnil;
1814}
1815
bc1ed486
RS
1816DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
1817 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
1818The position is given in character cells, where (0, 0) is the\n\
1819upper-left corner.\n\
1820If Emacs is running on a mouseless terminal or hasn't been programmed\n\
1821to read the mouse position, it returns the selected frame for FRAME\n\
1822and nil for X and Y.")
1823 ()
1824{
1825 FRAME_PTR f;
1826 Lisp_Object lispy_dummy;
1827 enum scroll_bar_part party_dummy;
1828 Lisp_Object x, y;
1829 unsigned long long_dummy;
1830
1831 f = selected_frame;
1832 x = y = Qnil;
1833
1834 /* It's okay for the hook to refrain from storing anything. */
1835 if (mouse_position_hook)
1836 (*mouse_position_hook) (&f,
1837 &lispy_dummy, &party_dummy,
1838 &x, &y,
1839 &long_dummy);
1840
5384466a
RS
1841 col = XINT (x);
1842 row = XINT (y);
1843 glyph_to_pixel_coords (f, col, row, &col, &row);
1844 XSETINT (x, col);
1845 XSETINT (y, row);
bc1ed486
RS
1846 /* Always return nil for frame. */
1847 return Fcons (Qnil, Fcons (x, y));
1848}
1849
fd0c2bd1
JB
1850syms_of_frame ()
1851{
91f5a8d7
KH
1852 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
1853 "The initial frame-object, which represents Emacs's stdout.");
1854 XFASTINT (Vterminal_frame) = 0;
1855
a26a1f95 1856 defsubr (&Sselected_frame);
704a9b45 1857 defsubr (&Sframep);
a26a1f95
RS
1858 defsubr (&Sframe_char_height);
1859 defsubr (&Sframe_char_width);
1860 defsubr (&Sframe_pixel_height);
1861 defsubr (&Sframe_pixel_width);
fd0c2bd1
JB
1862 defsubr (&Sset_frame_height);
1863 defsubr (&Sset_frame_width);
1864 defsubr (&Sset_frame_size);
1865 defsubr (&Sset_screen_height);
1866 defsubr (&Sset_screen_width);
1867 defsubr (&Sframe_height);
1868 Ffset (intern ("screen-height"), intern ("frame-height"));
1869 defsubr (&Sframe_width);
1870 Ffset (intern ("screen-width"), intern ("frame-width"));
bc1ed486 1871 defsubr (&Smouse_position);
fd0c2bd1
JB
1872}
1873
2f0b07e0
JB
1874keys_of_frame ()
1875{
1876}
1877
fd0c2bd1 1878#endif /* not MULTI_FRAME */