(xmenu_show): Enable asynchronous events.
[bpt/emacs.git] / src / frame.c
... / ...
CommitLineData
1/* Generic frame functions.
2 Copyright (C) 1993 Free Software Foundation.
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
8the Free Software Foundation; either version 2, or (at your option)
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
20#include <stdio.h>
21
22#include <config.h>
23#include "lisp.h"
24#include "frame.h"
25#include "termhooks.h"
26
27#ifdef MULTI_FRAME
28
29#include "buffer.h"
30#include "window.h"
31
32/* These help us bind and responding to switch-frame events. */
33#include "commands.h"
34#include "keyboard.h"
35
36Lisp_Object Vemacs_iconified;
37Lisp_Object Vframe_list;
38Lisp_Object Vterminal_frame;
39Lisp_Object Vdefault_minibuffer_frame;
40Lisp_Object Vdefault_frame_alist;
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;
77Lisp_Object Qframe_live_p;
78Lisp_Object Qheight;
79Lisp_Object Qicon;
80Lisp_Object Qminibuffer;
81Lisp_Object Qmodeline;
82Lisp_Object Qname;
83Lisp_Object Qonly;
84Lisp_Object Qunsplittable;
85Lisp_Object Qmenu_bar_lines;
86Lisp_Object Qwidth;
87Lisp_Object Qx;
88Lisp_Object Qvisible;
89
90extern Lisp_Object Vminibuffer_list;
91extern Lisp_Object get_minibuffer ();
92extern Lisp_Object Fhandle_switch_frame ();
93extern Lisp_Object Fredirect_frame_focus ();
94\f
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'.")
100 (object)
101 Lisp_Object object;
102{
103 if (XTYPE (object) != Lisp_Frame)
104 return Qnil;
105 switch (XFRAME (object)->output_method)
106 {
107 case output_termcap:
108 return Qt;
109 case output_x_window:
110 return Qx;
111 default:
112 abort ();
113 }
114}
115
116DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
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.")
122 (object)
123 Lisp_Object object;
124{
125 return ((FRAMEP (object)
126 && FRAME_LIVE_P (XFRAME (object)))
127 ? Fframep (object)
128 : Qnil);
129}
130
131struct frame *
132make_frame (mini_p)
133 int mini_p;
134{
135 Lisp_Object frame;
136 register struct frame *f;
137 register Lisp_Object root_window;
138 register Lisp_Object mini_window;
139
140 frame = Fmake_vector (((sizeof (struct frame) - (sizeof (Lisp_Vector)
141 - sizeof (Lisp_Object)))
142 / sizeof (Lisp_Object)),
143 make_number (0));
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;
152 f->async_visible = 0;
153 f->display.nothing = 0;
154 f->iconified = 0;
155 f->async_iconified = 0;
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;
162 f->focus_frame = Qnil;
163 f->explicit_name = 0;
164 f->can_have_scroll_bars = 0;
165 f->has_vertical_scroll_bars = 0;
166 f->param_alist = Qnil;
167 f->scroll_bars = Qnil;
168 f->condemned_scroll_bars = Qnil;
169 f->face_alist = Qnil;
170 f->menu_bar_items = Qnil;
171
172 root_window = make_window ();
173 if (mini_p)
174 {
175 mini_window = make_window ();
176 XWINDOW (root_window)->next = mini_window;
177 XWINDOW (mini_window)->prev = root_window;
178 XWINDOW (mini_window)->mini_p = Qt;
179 XWINDOW (mini_window)->frame = frame;
180 f->minibuffer_window = mini_window;
181 }
182 else
183 {
184 mini_window = Qnil;
185 XWINDOW (root_window)->next = Qnil;
186 f->minibuffer_window = Qnil;
187 }
188
189 XWINDOW (root_window)->frame = frame;
190
191 /* 10 is arbitrary,
192 just so that there is "something there."
193 Correct size will be set up later with change_frame_size. */
194
195 f->width = 10;
196 f->height = 10;
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
208 /* Choose a buffer for the frame's root window. */
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] == ' ')
217 buf = Fother_buffer (buf, Qnil);
218 Fset_window_buffer (root_window, buf);
219 }
220
221 if (mini_p)
222 {
223 XWINDOW (mini_window)->buffer = Qt;
224 Fset_window_buffer (mini_window,
225 (NILP (Vminibuffer_list)
226 ? get_minibuffer (0)
227 : Fcar (Vminibuffer_list)));
228 }
229
230 f->root_window = root_window;
231 f->selected_window = root_window;
232 /* Make sure this window seems more recently used than
233 a newly-created, never-selected window. */
234 XFASTINT (XWINDOW (f->selected_window)->use_time) = ++window_select_count;
235
236 return f;
237}
238\f
239/* Make a frame using a separate minibuffer window on another frame.
240 MINI_WINDOW is the minibuffer window to use. nil means use the
241 default (the global minibuffer). */
242
243struct frame *
244make_frame_without_minibuffer (mini_window)
245 register Lisp_Object mini_window;
246{
247 register struct frame *f;
248
249 /* Choose the minibuffer window to use. */
250 if (NILP (mini_window))
251 {
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;
257 }
258 else
259 {
260 CHECK_LIVE_WINDOW (mini_window, 0);
261 }
262
263 /* Make a frame containing just a root window. */
264 f = make_frame (0);
265
266 /* Install the chosen minibuffer window, with proper buffer. */
267 f->minibuffer_window = mini_window;
268 Fset_window_buffer (mini_window,
269 (NILP (Vminibuffer_list)
270 ? get_minibuffer (0)
271 : Fcar (Vminibuffer_list)));
272 return f;
273}
274
275/* Make a frame containing only a minibuffer window. */
276
277struct frame *
278make_minibuffer_frame ()
279{
280 /* First make a frame containing just a root window, no minibuffer. */
281
282 register struct frame *f = make_frame (0);
283 register Lisp_Object mini_window;
284 register Lisp_Object frame;
285
286 XSET (frame, Lisp_Frame, f);
287
288 f->auto_raise = 0;
289 f->auto_lower = 0;
290 f->no_split = 1;
291 f->wants_modeline = 0;
292 f->has_minibuffer = 1;
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
298 mini_window = f->minibuffer_window = f->root_window;
299 XWINDOW (mini_window)->mini_p = Qt;
300 XWINDOW (mini_window)->next = Qnil;
301 XWINDOW (mini_window)->prev = Qnil;
302 XWINDOW (mini_window)->frame = frame;
303
304 /* Put the proper buffer in that window. */
305
306 Fset_window_buffer (mini_window,
307 (NILP (Vminibuffer_list)
308 ? get_minibuffer (0)
309 : Fcar (Vminibuffer_list)));
310 return f;
311}
312\f
313/* Construct a frame that refers to the terminal (stdin and stdout). */
314
315struct frame *
316make_terminal_frame ()
317{
318 register struct frame *f;
319 Lisp_Object frame;
320
321 Vframe_list = Qnil;
322 f = make_frame (1);
323
324 XSET (frame, Lisp_Frame, f);
325 Vframe_list = Fcons (frame, Vframe_list);
326
327 f->name = build_string ("terminal");
328 FRAME_SET_VISIBLE (f, 1);
329 f->display.nothing = 1; /* Nonzero means frame isn't deleted. */
330 XSET (Vterminal_frame, Lisp_Frame, f);
331 return f;
332}
333\f
334static Lisp_Object
335do_switch_frame (frame, no_enter, track)
336 Lisp_Object frame, no_enter;
337 int track;
338{
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
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;
352
353 if (selected_frame == XFRAME (frame))
354 return frame;
355
356 /* This is too greedy; it causes inappropriate focus redirection
357 that's hard to get rid of. */
358#if 0
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. */
366 if (track)
367 {
368 Lisp_Object tail;
369
370 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
371 {
372 Lisp_Object focus;
373
374 if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
375 abort ();
376
377 focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
378
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 */
401
402 selected_frame = XFRAME (frame);
403 if (! FRAME_MINIBUF_ONLY_P (selected_frame))
404 last_nonminibuf_frame = selected_frame;
405
406 Fselect_window (XFRAME (frame)->selected_window);
407 choose_minibuf_frame ();
408
409 /* We want to make sure that the next event generates a frame-switch
410 event to the appropriate frame. This seems kludgy to me, but
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. */
415 internal_last_event_frame = Qnil;
416
417 return frame;
418}
419
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
449DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
450 "Return the frame that is now selected.")
451 ()
452{
453 Lisp_Object tem;
454 XSET (tem, Lisp_Frame, selected_frame);
455 return tem;
456}
457
458DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
459 "Return the frame object that window WINDOW is on.")
460 (window)
461 Lisp_Object window;
462{
463 CHECK_LIVE_WINDOW (window, 0);
464 return XWINDOW (window)->frame;
465}
466
467DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
468 "Returns the root-window of FRAME.\n\
469If omitted, FRAME defaults to the currently selected frame.")
470 (frame)
471 Lisp_Object frame;
472{
473 if (NILP (frame))
474 XSET (frame, Lisp_Frame, selected_frame);
475 else
476 CHECK_LIVE_FRAME (frame, 0);
477
478 return XFRAME (frame)->root_window;
479}
480
481DEFUN ("frame-selected-window", Fframe_selected_window,
482 Sframe_selected_window, 0, 1, 0,
483 "Return the selected window of frame object FRAME.\n\
484If omitted, FRAME defaults to the currently selected frame.")
485 (frame)
486 Lisp_Object frame;
487{
488 if (NILP (frame))
489 XSET (frame, Lisp_Frame, selected_frame);
490 else
491 CHECK_LIVE_FRAME (frame, 0);
492
493 return XFRAME (frame)->selected_window;
494}
495
496DEFUN ("frame-list", Fframe_list, Sframe_list,
497 0, 0, 0,
498 "Return a list of all frames.")
499 ()
500{
501 return Fcopy_sequence (Vframe_list);
502}
503
504/* Return the next frame in the frame list after FRAME.
505 If MINIBUF is nil, exclude minibuffer-only frames.
506 If MINIBUF is a window, include only frames using that window for
507 their minibuffer.
508 If MINIBUF is `visible', include all visible frames.
509 Otherwise, include all frames. */
510
511Lisp_Object
512next_frame (frame, minibuf)
513 Lisp_Object frame;
514 Lisp_Object minibuf;
515{
516 Lisp_Object tail;
517 int passed = 0;
518
519 /* There must always be at least one frame in Vframe_list. */
520 if (! CONSP (Vframe_list))
521 abort ();
522
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
527 while (1)
528 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
529 {
530 Lisp_Object f;
531
532 f = XCONS (tail)->car;
533 if (passed)
534 {
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 }
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))
555 {
556 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
557 return f;
558 }
559 else
560 return f;
561 }
562
563 if (EQ (frame, f))
564 passed++;
565 }
566}
567
568/* Return the previous frame in the frame list before FRAME.
569 If MINIBUF is nil, exclude minibuffer-only frames.
570 If MINIBUF is a window, include only frames using that window for
571 their minibuffer.
572 If MINIBUF is `visible', include all visible frames.
573 Otherwise, include all frames. */
574
575Lisp_Object
576prev_frame (frame, minibuf)
577 Lisp_Object frame;
578 Lisp_Object minibuf;
579{
580 Lisp_Object tail;
581 Lisp_Object prev;
582
583 /* There must always be at least one frame in Vframe_list. */
584 if (! CONSP (Vframe_list))
585 abort ();
586
587 prev = Qnil;
588 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
589 {
590 Lisp_Object f;
591
592 f = XCONS (tail)->car;
593 if (XTYPE (f) != Lisp_Frame)
594 abort ();
595
596 if (EQ (frame, f) && !NILP (prev))
597 return prev;
598
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;
605 }
606 else if (XTYPE (minibuf) == Lisp_Window)
607 {
608 if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
609 prev = f;
610 }
611 else if (EQ (minibuf, Qvisible))
612 {
613 FRAME_SAMPLE_VISIBILITY (XFRAME (f));
614 if (FRAME_VISIBLE_P (XFRAME (f)))
615 prev = f;
616 }
617 else
618 prev = f;
619 }
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;
631}
632
633
634DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
635 "Return the next frame in the frame list after FRAME.\n\
636By default, skip minibuffer-only frames.\n\
637If omitted, FRAME defaults to the selected frame.\n\
638If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
639If MINIFRAME is a window, include only frames using that window for their\n\
640minibuffer.\n\
641If MINIFRAME is `visible', include all visible frames.\n\
642Otherwise, include all frames.")
643 (frame, miniframe)
644 Lisp_Object frame, miniframe;
645{
646 Lisp_Object tail;
647
648 if (NILP (frame))
649 XSET (frame, Lisp_Frame, selected_frame);
650 else
651 CHECK_LIVE_FRAME (frame, 0);
652
653 return next_frame (frame, miniframe);
654}
655
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\
663If MINIFRAME is `visible', include all visible frames.\n\
664Otherwise, include all frames.")
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}
677\f
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.) */
681
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)
689 {
690 Lisp_Object frames;
691 int count = 0;
692
693 for (frames = Vframe_list;
694 CONSP (frames);
695 frames = XCONS (frames)->cdr)
696 {
697 Lisp_Object this;
698
699 this = XCONS (frames)->car;
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. */
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
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! */
715 || (FRAME_X_P (XFRAME (this)) && !FRAME_X_P (f)))
716 count++;
717 }
718 return count > 1;
719 }
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");
750
751 /* Does this frame have a minibuffer, and is it the surrogate
752 minibuffer for any other frame? */
753 if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
754 {
755 Lisp_Object frames;
756
757 for (frames = Vframe_list;
758 CONSP (frames);
759 frames = XCONS (frames)->cdr)
760 {
761 Lisp_Object this;
762 this = XCONS (frames)->car;
763
764 if (! EQ (this, frame)
765 && EQ (frame,
766 WINDOW_FRAME (XWINDOW
767 (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
768 error ("Attempt to delete a surrogate minibuffer frame");
769 }
770 }
771
772 /* Don't let the frame remain selected. */
773 if (f == selected_frame)
774 Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
775
776 /* Don't allow minibuf_window to remain on a deleted frame. */
777 if (EQ (f->minibuffer_window, minibuf_window))
778 {
779 Fset_window_buffer (selected_frame->minibuffer_window,
780 XWINDOW (minibuf_window)->buffer);
781 minibuf_window = selected_frame->minibuffer_window;
782 }
783
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
789 Vframe_list = Fdelq (frame, Vframe_list);
790 FRAME_SET_VISIBLE (f, 0);
791
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. */
797
798 /* I think this should be done with a hook. */
799#ifdef HAVE_X_WINDOWS
800 if (FRAME_X_P (f))
801 x_destroy_window (f);
802#endif
803
804 f->display.nothing = 0;
805
806 /* If we've deleted the last_nonminibuf_frame, then try to find
807 another one. */
808 if (f == last_nonminibuf_frame)
809 {
810 Lisp_Object frames;
811
812 last_nonminibuf_frame = 0;
813
814 for (frames = Vframe_list;
815 CONSP (frames);
816 frames = XCONS (frames)->cdr)
817 {
818 f = XFRAME (XCONS (frames)->car);
819 if (!FRAME_MINIBUF_ONLY_P (f))
820 {
821 last_nonminibuf_frame = f;
822 break;
823 }
824 }
825 }
826
827 /* If we've deleted Vdefault_minibuffer_frame, try to find another
828 one. Prefer minibuffer-only frames, but also notice frames
829 with other windows. */
830 if (EQ (frame, Vdefault_minibuffer_frame))
831 {
832 Lisp_Object frames;
833
834 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
835 Lisp_Object frame_with_minibuf;
836
837 frame_with_minibuf = Qnil;
838 for (frames = Vframe_list;
839 CONSP (frames);
840 frames = XCONS (frames)->cdr)
841 {
842 Lisp_Object this;
843
844 this = XCONS (frames)->car;
845 if (XTYPE (this) != Lisp_Frame)
846 abort ();
847 f = XFRAME (this);
848
849 if (FRAME_HAS_MINIBUF_P (f))
850 {
851 frame_with_minibuf = this;
852 if (FRAME_MINIBUF_ONLY_P (f))
853 break;
854 }
855 }
856
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
859 would have to be minibufferless, which implies that at some
860 point their minibuffer frames must have been deleted, but
861 that is prohibited at the top; you can't delete surrogate
862 minibuffer frames. */
863 if (NILP (frame_with_minibuf))
864 abort ();
865
866 Vdefault_minibuffer_frame = frame_with_minibuf;
867 }
868
869 return Qnil;
870}
871\f
872/* Return mouse position in character cell units. */
873
874DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
875 "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
876The position is given in character cells, where (0, 0) is the\n\
877upper-left corner.\n\
878If Emacs is running on a mouseless terminal or hasn't been programmed\n\
879to read the mouse position, it returns the selected frame for FRAME\n\
880and nil for X and Y.")
881 ()
882{
883 FRAME_PTR f;
884 Lisp_Object lispy_dummy;
885 enum scroll_bar_part party_dummy;
886 Lisp_Object x, y;
887 int col, row;
888 unsigned long long_dummy;
889
890 f = selected_frame;
891 x = y = Qnil;
892
893 /* It's okay for the hook to refrain from storing anything. */
894 if (mouse_position_hook)
895 (*mouse_position_hook) (&f,
896 &lispy_dummy, &party_dummy,
897 &x, &y,
898 &long_dummy);
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);
904 XSET (lispy_dummy, Lisp_Frame, f);
905 return Fcons (lispy_dummy, Fcons (x, y));
906}
907
908DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
909 "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
910WARNING: If you use this under X, you should do `unfocus-frame' afterwards.")
911 (frame, x, y)
912 Lisp_Object frame, x, y;
913{
914 CHECK_LIVE_FRAME (frame, 0);
915 CHECK_NUMBER (x, 2);
916 CHECK_NUMBER (y, 1);
917
918 /* I think this should be done with a hook. */
919#ifdef HAVE_X_WINDOWS
920 if (FRAME_X_P (XFRAME (frame)))
921 /* Warping the mouse will cause enternotify and focus events. */
922 x_set_mouse_position (XFRAME (frame), x, y);
923#endif
924
925 return Qnil;
926}
927\f
928DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
929 0, 1, "",
930 "Make the frame FRAME visible (assuming it is an X-window).\n\
931If omitted, FRAME defaults to the currently selected frame.")
932 (frame)
933 Lisp_Object frame;
934{
935 if (NILP (frame))
936 XSET (frame, Lisp_Frame, selected_frame);
937
938 CHECK_LIVE_FRAME (frame, 0);
939
940 /* I think this should be done with a hook. */
941#ifdef HAVE_X_WINDOWS
942 if (FRAME_X_P (XFRAME (frame)))
943 {
944 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
945 x_make_frame_visible (XFRAME (frame));
946 }
947#endif
948
949 return frame;
950}
951
952DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
953 0, 2, "",
954 "Make the frame FRAME invisible (assuming it is an X-window).\n\
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;
960{
961 if (NILP (frame))
962 XSET (frame, Lisp_Frame, selected_frame);
963
964 CHECK_LIVE_FRAME (frame, 0);
965
966 if (NILP (force) && !other_visible_frames (XFRAME (frame)))
967 error ("Attempt to make invisible the sole visible or iconified frame");
968
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
981 /* I think this should be done with a hook. */
982#ifdef HAVE_X_WINDOWS
983 if (FRAME_X_P (XFRAME (frame)))
984 x_make_frame_invisible (XFRAME (frame));
985#endif
986
987 return Qnil;
988}
989
990DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
991 0, 1, "",
992 "Make the frame FRAME into an icon.\n\
993If omitted, FRAME defaults to the currently selected frame.")
994 (frame)
995 Lisp_Object frame;
996{
997 if (NILP (frame))
998 XSET (frame, Lisp_Frame, selected_frame);
999
1000 CHECK_LIVE_FRAME (frame, 0);
1001
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
1014 /* I think this should be done with a hook. */
1015#ifdef HAVE_X_WINDOWS
1016 if (FRAME_X_P (XFRAME (frame)))
1017 x_iconify_frame (XFRAME (frame));
1018#endif
1019
1020 return Qnil;
1021}
1022
1023DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
1024 1, 1, 0,
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\
1027a window system, it may not show at all.\n\
1028Return the symbol `icon' if frame is visible only as an icon.")
1029 (frame)
1030 Lisp_Object frame;
1031{
1032 CHECK_LIVE_FRAME (frame, 0);
1033
1034 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1035
1036 if (FRAME_VISIBLE_P (XFRAME (frame)))
1037 return Qt;
1038 if (FRAME_ICONIFIED_P (XFRAME (frame)))
1039 return Qicon;
1040 return Qnil;
1041}
1042
1043DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
1044 0, 0, 0,
1045 "Return a list of all frames now \"visible\" (being updated).")
1046 ()
1047{
1048 Lisp_Object tail, frame;
1049 struct frame *f;
1050 Lisp_Object value;
1051
1052 value = Qnil;
1053 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1054 {
1055 frame = XCONS (tail)->car;
1056 if (XTYPE (frame) != Lisp_Frame)
1057 continue;
1058 f = XFRAME (frame);
1059 if (FRAME_VISIBLE_P (f))
1060 value = Fcons (frame, value);
1061 }
1062 return value;
1063}
1064
1065
1066DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 1, 1, 0,
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);
1075
1076 /* Do like the documentation says. */
1077 Fmake_frame_visible (frame);
1078
1079 if (frame_raise_lower_hook)
1080 (*frame_raise_lower_hook) (XFRAME (frame), 1);
1081
1082 return Qnil;
1083}
1084
1085/* Should we have a corresponding function called Flower_Power? */
1086DEFUN ("lower-frame", Flower_frame, Slower_frame, 1, 1, 0,
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
1101\f
1102DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
1103 1, 2, 0,
1104 "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
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\
1108\n\
1109If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
1110cancelled, and the frame again receives its own keystrokes.\n\
1111\n\
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\
1115\n\
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.")
1127 (frame, focus_frame)
1128 Lisp_Object frame, focus_frame;
1129{
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);
1134
1135 if (! NILP (focus_frame))
1136 CHECK_LIVE_FRAME (focus_frame, 1);
1137
1138 XFRAME (frame)->focus_frame = focus_frame;
1139
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
1147 if (frame_rehighlight_hook)
1148 (*frame_rehighlight_hook) ();
1149
1150 return Qnil;
1151}
1152
1153
1154DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
1155 "Return the frame to which FRAME's keystrokes are currently being sent.\n\
1156This returns nil if FRAME's focus is not redirected.\n\
1157See `redirect-frame-focus'.")
1158 (frame)
1159 Lisp_Object frame;
1160{
1161 CHECK_LIVE_FRAME (frame, 0);
1162
1163 return FRAME_FOCUS_FRAME (XFRAME (frame));
1164}
1165
1166
1167\f
1168Lisp_Object
1169get_frame_param (frame, prop)
1170 register struct frame *frame;
1171 Lisp_Object prop;
1172{
1173 register Lisp_Object tem;
1174
1175 tem = Fassq (prop, frame->param_alist);
1176 if (EQ (tem, Qnil))
1177 return tem;
1178 return Fcdr (tem);
1179}
1180
1181void
1182store_in_alist (alistptr, prop, val)
1183 Lisp_Object *alistptr, val;
1184 Lisp_Object prop;
1185{
1186 register Lisp_Object tem;
1187
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
1196store_frame_param (f, prop, val)
1197 struct frame *f;
1198 Lisp_Object prop, val;
1199{
1200 register Lisp_Object tem;
1201
1202 tem = Fassq (prop, f->param_alist);
1203 if (EQ (tem, Qnil))
1204 f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
1205 else
1206 Fsetcdr (tem, val);
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
1214 if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
1215 error ("can't change the surrogate minibuffer of a frame with its own minibuffer");
1216
1217 /* Install the chosen minibuffer window, with proper buffer. */
1218 f->minibuffer_window = val;
1219 }
1220}
1221
1222DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
1223 "Return the parameters-alist of frame FRAME.\n\
1224It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
1225The meaningful PARMs depend on the kind of frame.\n\
1226If FRAME is omitted, return information on the currently selected frame.")
1227 (frame)
1228 Lisp_Object frame;
1229{
1230 Lisp_Object alist;
1231 struct frame *f;
1232
1233 if (EQ (frame, Qnil))
1234 f = selected_frame;
1235 else
1236 {
1237 CHECK_FRAME (frame, 0);
1238 f = XFRAME (frame);
1239 }
1240
1241 if (f->display.nothing == 0)
1242 return Qnil;
1243
1244 alist = Fcopy_alist (f->param_alist);
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,
1250 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
1251 : (FRAME_MINIBUF_ONLY_P (f) ? Qonly
1252 : FRAME_MINIBUF_WINDOW (f))));
1253 store_in_alist (&alist, Qunsplittable, (f->no_split ? Qt : Qnil));
1254 store_in_alist (&alist, Qmenu_bar_lines, (FRAME_MENU_BAR_LINES (f)));
1255
1256 /* I think this should be done with a hook. */
1257#ifdef HAVE_X_WINDOWS
1258 if (FRAME_X_P (f))
1259 x_report_frame_params (f, &alist);
1260#endif
1261 return alist;
1262}
1263
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\
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\
1269The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
1270 (frame, alist)
1271 Lisp_Object frame, alist;
1272{
1273 FRAME_PTR f;
1274 register Lisp_Object tail, elt, prop, val;
1275
1276 if (EQ (frame, Qnil))
1277 f = selected_frame;
1278 else
1279 {
1280 CHECK_LIVE_FRAME (frame, 0);
1281 f = XFRAME (frame);
1282 }
1283
1284 /* I think this should be done with a hook. */
1285#ifdef HAVE_X_WINDOWS
1286 if (FRAME_X_P (f))
1287#if 1
1288 x_set_frame_parameters (f, alist);
1289#else
1290 for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
1291 {
1292 elt = Fcar (tail);
1293 prop = Fcar (elt);
1294 val = Fcdr (elt);
1295 x_set_frame_param (f, prop, val, get_frame_param (f, prop));
1296 store_frame_param (f, prop, val);
1297 }
1298#endif
1299#endif
1300
1301 return Qnil;
1302}
1303\f
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.")
1309 (frame)
1310 Lisp_Object frame;
1311{
1312 struct frame *f;
1313
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
1326#endif
1327 return make_number (1);
1328}
1329
1330
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;
1340{
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);
1357}
1358
1359DEFUN ("frame-pixel-height", Fframe_pixel_height,
1360 Sframe_pixel_height, 0, 1, 0,
1361 "Return a FRAME's height in pixels.\n\
1362For a terminal frame, the result really gives the height in characters.\n\
1363If FRAME is omitted, the selected frame is used.")
1364 (frame)
1365 Lisp_Object frame;
1366{
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
1381#endif
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\
1388For a terminal frame, the result really gives the width in characters.\n\
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 }
1402
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
1411DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
1412 "Specify that the frame FRAME has LINES lines.\n\
1413Optional third arg non-nil means that redisplay should use LINES lines\n\
1414but that the idea of the actual height of the frame should not be changed.")
1415 (frame, rows, pretend)
1416 Lisp_Object frame, rows, pretend;
1417{
1418 register struct frame *f;
1419
1420 CHECK_NUMBER (rows, 0);
1421 if (NILP (frame))
1422 f = selected_frame;
1423 else
1424 {
1425 CHECK_LIVE_FRAME (frame, 0);
1426 f = XFRAME (frame);
1427 }
1428
1429 /* I think this should be done with a hook. */
1430#ifdef HAVE_X_WINDOWS
1431 if (FRAME_X_P (f))
1432 {
1433 if (XINT (rows) != f->width)
1434 x_set_window_size (f, 1, f->width, XINT (rows));
1435 }
1436 else
1437#endif
1438 change_frame_size (f, XINT (rows), 0, !NILP (pretend), 0);
1439 return Qnil;
1440}
1441
1442DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
1443 "Specify that the frame FRAME has COLS columns.\n\
1444Optional third arg non-nil means that redisplay should use COLS columns\n\
1445but that the idea of the actual width of the frame should not be changed.")
1446 (frame, cols, pretend)
1447 Lisp_Object frame, cols, pretend;
1448{
1449 register struct frame *f;
1450 CHECK_NUMBER (cols, 0);
1451 if (NILP (frame))
1452 f = selected_frame;
1453 else
1454 {
1455 CHECK_LIVE_FRAME (frame, 0);
1456 f = XFRAME (frame);
1457 }
1458
1459 /* I think this should be done with a hook. */
1460#ifdef HAVE_X_WINDOWS
1461 if (FRAME_X_P (f))
1462 {
1463 if (XINT (cols) != f->width)
1464 x_set_window_size (f, 1, XINT (cols), f->height);
1465 }
1466 else
1467#endif
1468 change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0);
1469 return Qnil;
1470}
1471
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;
1476{
1477 register struct frame *f;
1478 int mask;
1479
1480 CHECK_LIVE_FRAME (frame, 0);
1481 CHECK_NUMBER (cols, 2);
1482 CHECK_NUMBER (rows, 1);
1483 f = XFRAME (frame);
1484
1485 /* I think this should be done with a hook. */
1486#ifdef HAVE_X_WINDOWS
1487 if (FRAME_X_P (f))
1488 {
1489 if (XINT (rows) != f->height || XINT (cols) != f->width)
1490 x_set_window_size (f, 1, XINT (cols), XINT (rows));
1491 }
1492 else
1493#endif
1494 change_frame_size (f, XINT (rows), XINT (cols), 0, 0);
1495
1496 return Qnil;
1497}
1498
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\
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\
1504the rightmost or bottommost possible position (that stays within the screen).")
1505 (frame, xoffset, yoffset)
1506 Lisp_Object frame, xoffset, yoffset;
1507{
1508 register struct frame *f;
1509 int mask;
1510
1511 CHECK_LIVE_FRAME (frame, 0);
1512 CHECK_NUMBER (xoffset, 1);
1513 CHECK_NUMBER (yoffset, 2);
1514 f = XFRAME (frame);
1515
1516 /* I think this should be done with a hook. */
1517#ifdef HAVE_X_WINDOWS
1518 if (FRAME_X_P (f))
1519 x_set_offset (f, XINT (xoffset), XINT (yoffset));
1520#endif
1521
1522 return Qt;
1523}
1524
1525\f
1526choose_minibuf_frame ()
1527{
1528 /* For lowest-level minibuf, put it on currently selected frame
1529 if frame has a minibuffer. */
1530
1531 if (minibuf_level == 0
1532 && selected_frame != 0
1533 && !EQ (minibuf_window, selected_frame->minibuffer_window))
1534 {
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
1540 Fset_window_buffer (selected_frame->minibuffer_window,
1541 XWINDOW (minibuf_window)->buffer);
1542 minibuf_window = selected_frame->minibuffer_window;
1543 }
1544}
1545\f
1546syms_of_frame ()
1547{
1548 /*&&& init symbols here &&&*/
1549 Qframep = intern ("framep");
1550 staticpro (&Qframep);
1551 Qframe_live_p = intern ("frame-live-p");
1552 staticpro (&Qframe_live_p);
1553 Qheight = intern ("height");
1554 staticpro (&Qheight);
1555 Qicon = intern ("icon");
1556 staticpro (&Qicon);
1557 Qminibuffer = intern ("minibuffer");
1558 staticpro (&Qminibuffer);
1559 Qmodeline = intern ("modeline");
1560 staticpro (&Qmodeline);
1561 Qname = intern ("name");
1562 staticpro (&Qname);
1563 Qonly = intern ("only");
1564 staticpro (&Qonly);
1565 Qunsplittable = intern ("unsplittable");
1566 staticpro (&Qunsplittable);
1567 Qmenu_bar_lines = intern ("menu-bar-lines");
1568 staticpro (&Qmenu_bar_lines);
1569 Qwidth = intern ("width");
1570 staticpro (&Qwidth);
1571 Qx = intern ("x");
1572 staticpro (&Qx);
1573 Qvisible = intern ("visible");
1574 staticpro (&Qvisible);
1575
1576 staticpro (&Vframe_list);
1577
1578 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
1579 "The initial frame-object, which represents Emacs's stdout.");
1580
1581 DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
1582 "Non-nil if all of emacs is iconified and frame updates are not needed.");
1583 Vemacs_iconified = Qnil;
1584
1585 DEFVAR_LISP ("default-minibuffer-frame", &Vdefault_minibuffer_frame,
1586 "Minibufferless frames use this frame's minibuffer.\n\
1587\n\
1588Emacs cannot create minibufferless frames unless this is set to an\n\
1589appropriate surrogate.\n\
1590\n\
1591Emacs consults this variable only when creating minibufferless\n\
1592frames; once the frame is created, it sticks with its assigned\n\
1593minibuffer, no matter what this variable is set to. This means that\n\
1594this variable doesn't necessarily say anything meaningful about the\n\
1595current set of frames, or where the minibuffer is currently being\n\
1596displayed.");
1597 Vdefault_minibuffer_frame = Qnil;
1598
1599 DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
1600 "Alist of default values for frame creation.\n\
1601These may be set in your init file, like this:\n\
1602 (setq default-frame-alist '((width . 80) (height . 55)))\n\
1603These override values given in window system configuration data, like\n\
1604X Windows' defaults database.\n\
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);
1611 defsubr (&Sframe_live_p);
1612 defsubr (&Shandle_switch_frame);
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);
1620 defsubr (&Sprevious_frame);
1621 defsubr (&Sdelete_frame);
1622 defsubr (&Smouse_position);
1623 defsubr (&Sset_mouse_position);
1624#if 0
1625 defsubr (&Sframe_configuration);
1626 defsubr (&Srestore_frame_configuration);
1627#endif
1628 defsubr (&Smake_frame_visible);
1629 defsubr (&Smake_frame_invisible);
1630 defsubr (&Siconify_frame);
1631 defsubr (&Sframe_visible_p);
1632 defsubr (&Svisible_frame_list);
1633 defsubr (&Sraise_frame);
1634 defsubr (&Slower_frame);
1635 defsubr (&Sredirect_frame_focus);
1636 defsubr (&Sframe_focus);
1637 defsubr (&Sframe_parameters);
1638 defsubr (&Smodify_frame_parameters);
1639 defsubr (&Sframe_char_height);
1640 defsubr (&Sframe_char_width);
1641 defsubr (&Sframe_pixel_height);
1642 defsubr (&Sframe_pixel_width);
1643 defsubr (&Sset_frame_height);
1644 defsubr (&Sset_frame_width);
1645 defsubr (&Sset_frame_size);
1646 defsubr (&Sset_frame_position);
1647}
1648
1649keys_of_frame ()
1650{
1651 initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
1652}
1653\f
1654#else /* not MULTI_FRAME */
1655
1656/* If we're not using multi-frame stuff, we still need to provide some
1657 support functions. */
1658
1659Lisp_Object Vterminal_frame;
1660
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,
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)
1668 ()
1669{
1670 Lisp_Object tem;
1671 XFASTINT (tem) = 0;
1672 return tem;
1673}
1674DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
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)
1678 (object)
1679 Lisp_Object object;
1680{
1681 return Qnil;
1682}
1683
1684DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
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)
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,
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)
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,
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)
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
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;
1730{
1731 return make_number (FRAME_HEIGHT (selected_frame));
1732}
1733
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;
1739{
1740 return make_number (FRAME_WIDTH (selected_frame));
1741}
1742
1743DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
1744 0, 1, 0,
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)
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,
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)
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,
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)
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,
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)
1782 (frame)
1783 Lisp_Object frame;
1784{
1785 return make_number (FRAME_WIDTH (f));
1786}
1787
1788/* These are for backward compatibility with Emacs 18. */
1789
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
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
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);
1846 /* Always return nil for frame. */
1847 return Fcons (Qnil, Fcons (x, y));
1848}
1849
1850syms_of_frame ()
1851{
1852 DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
1853 "The initial frame-object, which represents Emacs's stdout.");
1854 XFASTINT (Vterminal_frame) = 0;
1855
1856 defsubr (&Sselected_frame);
1857 defsubr (&Sframep);
1858 defsubr (&Sframe_char_height);
1859 defsubr (&Sframe_char_width);
1860 defsubr (&Sframe_pixel_height);
1861 defsubr (&Sframe_pixel_width);
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"));
1871 defsubr (&Smouse_position);
1872}
1873
1874keys_of_frame ()
1875{
1876}
1877
1878#endif /* not MULTI_FRAME */