Add seq-set-equal-p to test for set equality
[emacs.git] / src / frame.c
blob4d17a071dc754d0b2f9066961bbfb86303f765ec
1 /* Generic frame functions.
3 Copyright (C) 1993-1995, 1997, 1999-2017 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <limits.h>
27 #include <c-ctype.h>
29 #include "lisp.h"
31 #ifdef HAVE_WINDOW_SYSTEM
32 #include TERM_HEADER
33 #endif /* HAVE_WINDOW_SYSTEM */
35 #include "buffer.h"
36 /* These help us bind and responding to switch-frame events. */
37 #include "keyboard.h"
38 #include "frame.h"
39 #include "blockinput.h"
40 #include "termchar.h"
41 #include "termhooks.h"
42 #include "dispextern.h"
43 #include "window.h"
44 #ifdef HAVE_WINDOW_SYSTEM
45 #include "fontset.h"
46 #endif
47 #include "cm.h"
48 #ifdef MSDOS
49 #include "msdos.h"
50 #include "dosfns.h"
51 #endif
52 #ifdef USE_X_TOOLKIT
53 #include "widget.h"
54 #endif
56 /* The currently selected frame. */
58 Lisp_Object selected_frame;
60 /* A frame which is not just a mini-buffer, or NULL if there are no such
61 frames. This is usually the most recent such frame that was selected. */
63 static struct frame *last_nonminibuf_frame;
65 /* False means there are no visible garbaged frames. */
66 bool frame_garbaged;
68 /* The default tool bar height for future frames. */
69 #if defined USE_GTK || defined HAVE_NS
70 enum { frame_default_tool_bar_height = 0 };
71 #else
72 int frame_default_tool_bar_height;
73 #endif
75 #ifdef HAVE_WINDOW_SYSTEM
76 static void x_report_frame_params (struct frame *, Lisp_Object *);
77 #endif
79 /* These setters are used only in this file, so they can be private. */
80 static void
81 fset_buffer_predicate (struct frame *f, Lisp_Object val)
83 f->buffer_predicate = val;
85 static void
86 fset_minibuffer_window (struct frame *f, Lisp_Object val)
88 f->minibuffer_window = val;
91 struct frame *
92 decode_live_frame (register Lisp_Object frame)
94 if (NILP (frame))
95 frame = selected_frame;
96 CHECK_LIVE_FRAME (frame);
97 return XFRAME (frame);
100 struct frame *
101 decode_any_frame (register Lisp_Object frame)
103 if (NILP (frame))
104 frame = selected_frame;
105 CHECK_FRAME (frame);
106 return XFRAME (frame);
109 #ifdef HAVE_WINDOW_SYSTEM
110 bool
111 display_available (void)
113 return x_display_list != NULL;
115 #endif
117 struct frame *
118 decode_window_system_frame (Lisp_Object frame)
120 struct frame *f = decode_live_frame (frame);
121 check_window_system (f);
122 #ifdef HAVE_WINDOW_SYSTEM
123 return f;
124 #endif
127 void
128 check_window_system (struct frame *f)
130 #ifdef HAVE_WINDOW_SYSTEM
131 if (window_system_available (f))
132 return;
133 #endif
134 error (f ? "Window system frame should be used"
135 : "Window system is not in use or not initialized");
138 /* Return the value of frame parameter PROP in frame FRAME. */
140 Lisp_Object
141 get_frame_param (register struct frame *frame, Lisp_Object prop)
143 register Lisp_Object tem;
145 tem = Fassq (prop, frame->param_alist);
146 if (EQ (tem, Qnil))
147 return tem;
148 return Fcdr (tem);
152 void
153 frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
154 int width, int height, Lisp_Object rest)
156 Lisp_Object frame;
158 XSETFRAME (frame, f);
159 if (CONSP (frame_size_history)
160 && INTEGERP (XCAR (frame_size_history))
161 && 0 < XINT (XCAR (frame_size_history)))
162 frame_size_history =
163 Fcons (make_number (XINT (XCAR (frame_size_history)) - 1),
164 Fcons (list4
165 (frame, fun_symbol,
166 ((width > 0)
167 ? list4 (make_number (FRAME_TEXT_WIDTH (f)),
168 make_number (FRAME_TEXT_HEIGHT (f)),
169 make_number (width),
170 make_number (height))
171 : Qnil),
172 rest),
173 XCDR (frame_size_history)));
177 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
178 state of frame F would be affected by a vertical (horizontal if
179 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
180 parameter that is changed. */
181 bool
182 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
184 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
185 bool inhibit
186 = (f->after_make_frame
187 ? (EQ (frame_inhibit_implied_resize, Qt)
188 || (CONSP (frame_inhibit_implied_resize)
189 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
190 || (horizontal
191 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullheight))
192 || (!horizontal
193 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullwidth))
194 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
195 : ((horizontal && f->inhibit_horizontal_resize)
196 || (!horizontal && f->inhibit_vertical_resize)));
197 if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
198 frame_size_history_add
199 (f, Qframe_inhibit_resize, 0, 0,
200 list5 (horizontal ? Qt : Qnil, parameter,
201 f->after_make_frame ? Qt : Qnil,
202 frame_inhibit_implied_resize,
203 fullscreen));
205 return inhibit;
208 static void
209 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
211 int nlines;
212 int olines = FRAME_MENU_BAR_LINES (f);
214 /* Right now, menu bars don't work properly in minibuf-only frames;
215 most of the commands try to apply themselves to the minibuffer
216 frame itself, and get an error because you can't switch buffers
217 in or split the minibuffer window. */
218 if (FRAME_MINIBUF_ONLY_P (f))
219 return;
221 if (TYPE_RANGED_INTEGERP (int, value))
222 nlines = XINT (value);
223 else
224 nlines = 0;
226 if (nlines != olines)
228 windows_or_buffers_changed = 14;
229 FRAME_MENU_BAR_LINES (f) = nlines;
230 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
231 change_frame_size (f, FRAME_COLS (f),
232 FRAME_LINES (f) + olines - nlines,
233 0, 1, 0, 0);
237 Lisp_Object Vframe_list;
240 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
241 doc: /* Return non-nil if OBJECT is a frame.
242 Value is:
243 t for a termcap frame (a character-only terminal),
244 `x' for an Emacs frame that is really an X window,
245 `w32' for an Emacs frame that is a window on MS-Windows display,
246 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
247 `pc' for a direct-write MS-DOS frame.
248 See also `frame-live-p'. */)
249 (Lisp_Object object)
251 if (!FRAMEP (object))
252 return Qnil;
253 switch (XFRAME (object)->output_method)
255 case output_initial: /* The initial frame is like a termcap frame. */
256 case output_termcap:
257 return Qt;
258 case output_x_window:
259 return Qx;
260 case output_w32:
261 return Qw32;
262 case output_msdos_raw:
263 return Qpc;
264 case output_ns:
265 return Qns;
266 default:
267 emacs_abort ();
271 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
272 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
273 Value is nil if OBJECT is not a live frame. If object is a live
274 frame, the return value indicates what sort of terminal device it is
275 displayed on. See the documentation of `framep' for possible
276 return values. */)
277 (Lisp_Object object)
279 return ((FRAMEP (object)
280 && FRAME_LIVE_P (XFRAME (object)))
281 ? Fframep (object)
282 : Qnil);
285 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
286 doc: /* The name of the window system that FRAME is displaying through.
287 The value is a symbol:
288 nil for a termcap frame (a character-only terminal),
289 `x' for an Emacs frame that is really an X window,
290 `w32' for an Emacs frame that is a window on MS-Windows display,
291 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
292 `pc' for a direct-write MS-DOS frame.
294 FRAME defaults to the currently selected frame.
296 Use of this function as a predicate is deprecated. Instead,
297 use `display-graphic-p' or any of the other `display-*-p'
298 predicates which report frame's specific UI-related capabilities. */)
299 (Lisp_Object frame)
301 Lisp_Object type;
302 if (NILP (frame))
303 frame = selected_frame;
305 type = Fframep (frame);
307 if (NILP (type))
308 wrong_type_argument (Qframep, frame);
310 if (EQ (type, Qt))
311 return Qnil;
312 else
313 return type;
316 /* Placeholder used by temacs -nw before window.el is loaded. */
317 DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
318 Sframe_windows_min_size, 4, 4, 0,
319 doc: /* */
320 attributes: const)
321 (Lisp_Object frame, Lisp_Object horizontal,
322 Lisp_Object ignore, Lisp_Object pixelwise)
324 return make_number (0);
328 * frame_windows_min_size:
330 * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
331 * of FRAME. If PIXELWISE is non-nil, return the minimum height (width)
332 * in pixels.
334 * This value is calculated by the function `frame-windows-min-size' in
335 * window.el unless the `min-height' (`min-width' if HORIZONTAL is
336 * non-nil) parameter of FRAME is non-nil thus explicitly specifying the
337 * value to be returned. In that latter case IGNORE is ignored.
339 * If `frame-windows-min-size' is called, it will make sure that the
340 * return value accommodates all windows of FRAME respecting the values
341 * of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil).
342 * With IGNORE non-nil the values of these variables are ignored.
344 * In either case never return a value less than 1.
346 static int
347 frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
348 Lisp_Object ignore, Lisp_Object pixelwise)
350 struct frame *f = XFRAME (frame);
351 Lisp_Object par_size;
353 if ((!NILP (horizontal)
354 && NUMBERP (par_size = get_frame_param (f, Qmin_width)))
355 || (NILP (horizontal)
356 && NUMBERP (par_size = get_frame_param (f, Qmin_height))))
358 int min_size = XINT (par_size);
360 /* Don't allow phantom frames. */
361 if (min_size < 1)
362 min_size = 1;
364 return (NILP (pixelwise)
365 ? min_size
366 : min_size * (NILP (horizontal)
367 ? FRAME_LINE_HEIGHT (f)
368 : FRAME_COLUMN_WIDTH (f)));
370 else
371 return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
372 ignore, pixelwise));
376 /* Make sure windows sizes of frame F are OK. new_width and new_height
377 are in pixels. A value of -1 means no change is requested for that
378 size (but the frame may still have to be resized to accommodate
379 windows with their minimum sizes). This can either issue a request
380 to resize the frame externally (via x_set_window_size), to resize the
381 frame internally (via resize_frame_windows) or do nothing at all.
383 The argument INHIBIT can assume the following values:
385 0 means to unconditionally call x_set_window_size even if sizes
386 apparently do not change. Fx_create_frame uses this to pass the
387 initial size to the window manager.
389 1 means to call x_set_window_size if the outer frame size really
390 changes. Fset_frame_size, Fset_frame_height, ... use this.
392 2 means to call x_set_window_size provided frame_inhibit_resize
393 allows it. The menu and tool bar code use this ("3" won't work
394 here in general because menu and tool bar are often not counted in
395 the frame's text height).
397 3 means call x_set_window_size if window minimum sizes must be
398 preserved or frame_inhibit_resize allows it. x_set_left_fringe,
399 x_set_scroll_bar_width, x_new_font ... use (or should use) this.
401 4 means call x_set_window_size only if window minimum sizes must be
402 preserved. x_set_right_divider_width, x_set_border_width and the
403 code responsible for wrapping the tool bar use this.
405 5 means to never call x_set_window_size. change_frame_size uses
406 this.
408 Note that even when x_set_window_size is not called, individual
409 windows may have to be resized (via `window--sanitize-window-sizes')
410 in order to support minimum size constraints.
412 PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
413 symbol of the parameter changed (like `menu-bar-lines', `font', ...).
414 This is passed on to frame_inhibit_resize to let the latter decide on
415 a case-by-case basis whether the frame may be resized externally. */
416 void
417 adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
418 bool pretend, Lisp_Object parameter)
420 int unit_width = FRAME_COLUMN_WIDTH (f);
421 int unit_height = FRAME_LINE_HEIGHT (f);
422 int old_pixel_width = FRAME_PIXEL_WIDTH (f);
423 int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
424 int old_cols = FRAME_COLS (f);
425 int old_lines = FRAME_LINES (f);
426 int new_pixel_width, new_pixel_height;
427 /* The following two values are calculated from the old frame pixel
428 sizes and any "new" settings for tool bar, menu bar and internal
429 borders. We do it this way to detect whether we have to call
430 x_set_window_size as consequence of the new settings. */
431 int windows_width = FRAME_WINDOWS_WIDTH (f);
432 int windows_height = FRAME_WINDOWS_HEIGHT (f);
433 int min_windows_width, min_windows_height;
434 /* These are a bit tedious, maybe we should use a macro. */
435 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
436 int old_windows_width = WINDOW_PIXEL_WIDTH (r);
437 int old_windows_height
438 = (WINDOW_PIXEL_HEIGHT (r)
439 + ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
440 ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
441 : 0));
442 int new_windows_width, new_windows_height;
443 int old_text_width = FRAME_TEXT_WIDTH (f);
444 int old_text_height = FRAME_TEXT_HEIGHT (f);
445 /* If a size is < 0 use the old value. */
446 int new_text_width = (new_width >= 0) ? new_width : old_text_width;
447 int new_text_height = (new_height >= 0) ? new_height : old_text_height;
448 int new_cols, new_lines;
449 bool inhibit_horizontal, inhibit_vertical;
450 Lisp_Object frame;
452 XSETFRAME (frame, f);
454 frame_size_history_add
455 (f, Qadjust_frame_size_1, new_text_width, new_text_height,
456 list2 (parameter, make_number (inhibit)));
458 /* The following two values are calculated from the old window body
459 sizes and any "new" settings for scroll bars, dividers, fringes and
460 margins (though the latter should have been processed already). */
461 min_windows_width
462 = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
463 min_windows_height
464 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
466 if (inhibit >= 2 && inhibit <= 4)
467 /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
468 within the limits and either resizing is inhibited or INHIBIT
469 equals 4. */
471 inhibit_horizontal = (windows_width >= min_windows_width
472 && (inhibit == 4
473 || frame_inhibit_resize (f, true, parameter)));
474 inhibit_vertical = (windows_height >= min_windows_height
475 && (inhibit == 4
476 || frame_inhibit_resize (f, false, parameter)));
478 else
479 /* Otherwise inhibit if INHIBIT equals 5. */
480 inhibit_horizontal = inhibit_vertical = inhibit == 5;
482 new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
483 ? old_pixel_width
484 : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
485 min_windows_width
486 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
487 new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
488 new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
489 new_cols = new_text_width / unit_width;
491 new_pixel_height = ((inhibit_vertical && (inhibit < 5))
492 ? old_pixel_height
493 : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
494 min_windows_height
495 + FRAME_TOP_MARGIN_HEIGHT (f)
496 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
497 new_windows_height = (new_pixel_height
498 - FRAME_TOP_MARGIN_HEIGHT (f)
499 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
500 new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
501 new_lines = new_text_height / unit_height;
503 #ifdef HAVE_WINDOW_SYSTEM
504 if (FRAME_WINDOW_P (f)
505 && f->can_x_set_window_size
506 && ((!inhibit_horizontal
507 && (new_pixel_width != old_pixel_width
508 || inhibit == 0 || inhibit == 2))
509 || (!inhibit_vertical
510 && (new_pixel_height != old_pixel_height
511 || inhibit == 0 || inhibit == 2))))
512 /* We are either allowed to change the frame size or the minimum
513 sizes request such a change. Do not care for fixing minimum
514 sizes here, we do that eventually when we're called from
515 change_frame_size. */
517 /* Make sure we respect fullheight and fullwidth. */
518 if (inhibit_horizontal)
519 new_text_width = old_text_width;
520 else if (inhibit_vertical)
521 new_text_height = old_text_height;
523 frame_size_history_add
524 (f, Qadjust_frame_size_2, new_text_width, new_text_height,
525 list2 (inhibit_horizontal ? Qt : Qnil,
526 inhibit_vertical ? Qt : Qnil));
528 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
529 f->resized_p = true;
531 return;
533 #endif
535 if (new_text_width == old_text_width
536 && new_text_height == old_text_height
537 && new_windows_width == old_windows_width
538 && new_windows_height == old_windows_height
539 && new_pixel_width == old_pixel_width
540 && new_pixel_height == old_pixel_height
541 && new_cols == old_cols
542 && new_lines == old_lines)
543 /* No change. Sanitize window sizes and return. */
545 sanitize_window_sizes (Qt);
546 sanitize_window_sizes (Qnil);
548 return;
551 block_input ();
553 #ifdef MSDOS
554 /* We only can set screen dimensions to certain values supported by
555 our video hardware. Try to find the smallest size greater or
556 equal to the requested dimensions, while accounting for the fact
557 that the menu-bar lines are not counted in the frame height. */
558 int dos_new_lines = new_lines + FRAME_TOP_MARGIN (f);
559 dos_set_window_size (&dos_new_lines, &new_cols);
560 new_lines = dos_new_lines - FRAME_TOP_MARGIN (f);
561 #endif
563 if (new_windows_width != old_windows_width)
565 resize_frame_windows (f, new_windows_width, 1, 1);
567 /* MSDOS frames cannot PRETEND, as they change frame size by
568 manipulating video hardware. */
569 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
570 FrameCols (FRAME_TTY (f)) = new_cols;
572 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
573 if (WINDOWP (f->tool_bar_window))
575 XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
576 XWINDOW (f->tool_bar_window)->total_cols
577 = new_windows_width / unit_width;
579 #endif
581 else if (new_cols != old_cols)
582 call2 (Qwindow__pixel_to_total, frame, Qt);
584 if (new_windows_height != old_windows_height
585 /* When the top margin has changed we have to recalculate the top
586 edges of all windows. No such calculation is necessary for the
587 left edges. */
588 || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
590 resize_frame_windows (f, new_windows_height, 0, 1);
592 /* MSDOS frames cannot PRETEND, as they change frame size by
593 manipulating video hardware. */
594 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
595 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
597 else if (new_lines != old_lines)
598 call2 (Qwindow__pixel_to_total, frame, Qnil);
600 frame_size_history_add
601 (f, Qadjust_frame_size_3, new_text_width, new_text_height,
602 list4 (make_number (old_pixel_width), make_number (old_pixel_height),
603 make_number (new_pixel_width), make_number (new_pixel_height)));
605 /* Assign new sizes. */
606 FRAME_TEXT_WIDTH (f) = new_text_width;
607 FRAME_TEXT_HEIGHT (f) = new_text_height;
608 FRAME_PIXEL_WIDTH (f) = new_pixel_width;
609 FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
610 SET_FRAME_COLS (f, new_cols);
611 SET_FRAME_LINES (f, new_lines);
614 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
615 int text_area_x, text_area_y, text_area_width, text_area_height;
617 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
618 &text_area_height);
619 if (w->cursor.x >= text_area_x + text_area_width)
620 w->cursor.hpos = w->cursor.x = 0;
621 if (w->cursor.y >= text_area_y + text_area_height)
622 w->cursor.vpos = w->cursor.y = 0;
625 /* Sanitize window sizes. */
626 sanitize_window_sizes (Qt);
627 sanitize_window_sizes (Qnil);
629 adjust_frame_glyphs (f);
630 calculate_costs (f);
631 SET_FRAME_GARBAGED (f);
633 /* A frame was "resized" if one of its pixelsizes changed, even if its
634 X window wasn't resized at all. */
635 f->resized_p = (new_pixel_width != old_pixel_width
636 || new_pixel_height != old_pixel_height);
638 unblock_input ();
641 /* Allocate basically initialized frame. */
643 static struct frame *
644 allocate_frame (void)
646 return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
649 struct frame *
650 make_frame (bool mini_p)
652 Lisp_Object frame;
653 struct frame *f;
654 struct window *rw, *mw UNINIT;
655 Lisp_Object root_window;
656 Lisp_Object mini_window;
658 f = allocate_frame ();
659 XSETFRAME (frame, f);
661 #ifdef USE_GTK
662 /* Initialize Lisp data. Note that allocate_frame initializes all
663 Lisp data to nil, so do it only for slots which should not be nil. */
664 fset_tool_bar_position (f, Qtop);
665 #endif
667 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
668 non-Lisp data, so do it only for slots which should not be zero.
669 To avoid subtle bugs and for the sake of readability, it's better to
670 initialize enum members explicitly even if their values are zero. */
671 f->wants_modeline = true;
672 f->redisplay = true;
673 f->garbaged = true;
674 f->can_x_set_window_size = false;
675 f->after_make_frame = false;
676 f->inhibit_horizontal_resize = false;
677 f->inhibit_vertical_resize = false;
678 f->tool_bar_redisplayed = false;
679 f->tool_bar_resized = false;
680 f->column_width = 1; /* !FRAME_WINDOW_P value. */
681 f->line_height = 1; /* !FRAME_WINDOW_P value. */
682 #ifdef HAVE_WINDOW_SYSTEM
683 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
684 f->horizontal_scroll_bars = false;
685 f->want_fullscreen = FULLSCREEN_NONE;
686 f->undecorated = false;
687 #ifndef HAVE_NTGUI
688 f->override_redirect = false;
689 #endif
690 f->skip_taskbar = false;
691 f->no_focus_on_map = false;
692 f->no_accept_focus = false;
693 f->z_group = z_group_none;
694 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
695 f->last_tool_bar_item = -1;
696 #endif
697 #endif
699 root_window = make_window ();
700 rw = XWINDOW (root_window);
701 if (mini_p)
703 mini_window = make_window ();
704 mw = XWINDOW (mini_window);
705 wset_next (rw, mini_window);
706 wset_prev (mw, root_window);
707 mw->mini = 1;
708 wset_frame (mw, frame);
709 fset_minibuffer_window (f, mini_window);
710 store_frame_param (f, Qminibuffer, Qt);
712 else
714 mini_window = Qnil;
715 wset_next (rw, Qnil);
716 fset_minibuffer_window (f, Qnil);
719 wset_frame (rw, frame);
721 /* 10 is arbitrary,
722 just so that there is "something there."
723 Correct size will be set up later with adjust_frame_size. */
725 SET_FRAME_COLS (f, 10);
726 SET_FRAME_LINES (f, 10);
727 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
728 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
730 rw->total_cols = 10;
731 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
732 rw->total_lines = mini_p ? 9 : 10;
733 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
735 if (mini_p)
737 mw->top_line = rw->total_lines;
738 mw->pixel_top = rw->pixel_height;
739 mw->total_cols = rw->total_cols;
740 mw->pixel_width = rw->pixel_width;
741 mw->total_lines = 1;
742 mw->pixel_height = FRAME_LINE_HEIGHT (f);
745 /* Choose a buffer for the frame's root window. */
747 Lisp_Object buf = Fcurrent_buffer ();
749 /* If current buffer is hidden, try to find another one. */
750 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
751 buf = other_buffer_safely (buf);
753 /* Use set_window_buffer, not Fset_window_buffer, and don't let
754 hooks be run by it. The reason is that the whole frame/window
755 arrangement is not yet fully initialized at this point. Windows
756 don't have the right size, glyph matrices aren't initialized
757 etc. Running Lisp functions at this point surely ends in a
758 SEGV. */
759 set_window_buffer (root_window, buf, 0, 0);
760 fset_buffer_list (f, list1 (buf));
763 if (mini_p)
765 set_window_buffer (mini_window,
766 (NILP (Vminibuffer_list)
767 ? get_minibuffer (0)
768 : Fcar (Vminibuffer_list)),
769 0, 0);
770 /* No horizontal scroll bars in minibuffers. */
771 wset_horizontal_scroll_bar (mw, Qnil);
774 fset_root_window (f, root_window);
775 fset_selected_window (f, root_window);
776 /* Make sure this window seems more recently used than
777 a newly-created, never-selected window. */
778 XWINDOW (f->selected_window)->use_time = ++window_select_count;
780 return f;
783 #ifdef HAVE_WINDOW_SYSTEM
784 /* Make a frame using a separate minibuffer window on another frame.
785 MINI_WINDOW is the minibuffer window to use. nil means use the
786 default (the global minibuffer). */
788 struct frame *
789 make_frame_without_minibuffer (Lisp_Object mini_window, KBOARD *kb,
790 Lisp_Object display)
792 struct frame *f;
794 if (!NILP (mini_window))
795 CHECK_LIVE_WINDOW (mini_window);
797 if (!NILP (mini_window)
798 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
799 error ("Frame and minibuffer must be on the same terminal");
801 /* Make a frame containing just a root window. */
802 f = make_frame (0);
804 if (NILP (mini_window))
806 /* Use default-minibuffer-frame if possible. */
807 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
808 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
810 Lisp_Object frame_dummy;
812 XSETFRAME (frame_dummy, f);
813 /* If there's no minibuffer frame to use, create one. */
814 kset_default_minibuffer_frame
815 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
818 mini_window
819 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
822 fset_minibuffer_window (f, mini_window);
823 store_frame_param (f, Qminibuffer, mini_window);
825 /* Make the chosen minibuffer window display the proper minibuffer,
826 unless it is already showing a minibuffer. */
827 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
828 /* Use set_window_buffer instead of Fset_window_buffer (see
829 discussion of bug#11984, bug#12025, bug#12026). */
830 set_window_buffer (mini_window,
831 (NILP (Vminibuffer_list)
832 ? get_minibuffer (0)
833 : Fcar (Vminibuffer_list)), 0, 0);
834 return f;
837 /* Make a frame containing only a minibuffer window. */
839 struct frame *
840 make_minibuffer_frame (void)
842 /* First make a frame containing just a root window, no minibuffer. */
844 register struct frame *f = make_frame (0);
845 register Lisp_Object mini_window;
846 register Lisp_Object frame;
848 XSETFRAME (frame, f);
850 f->auto_raise = 0;
851 f->auto_lower = 0;
852 f->no_split = 1;
853 f->wants_modeline = 0;
855 /* Now label the root window as also being the minibuffer.
856 Avoid infinite looping on the window chain by marking next pointer
857 as nil. */
859 mini_window = f->root_window;
860 fset_minibuffer_window (f, mini_window);
861 store_frame_param (f, Qminibuffer, Qonly);
862 XWINDOW (mini_window)->mini = 1;
863 wset_next (XWINDOW (mini_window), Qnil);
864 wset_prev (XWINDOW (mini_window), Qnil);
865 wset_frame (XWINDOW (mini_window), frame);
867 /* Put the proper buffer in that window. */
869 /* Use set_window_buffer instead of Fset_window_buffer (see
870 discussion of bug#11984, bug#12025, bug#12026). */
871 set_window_buffer (mini_window,
872 (NILP (Vminibuffer_list)
873 ? get_minibuffer (0)
874 : Fcar (Vminibuffer_list)), 0, 0);
875 return f;
877 #endif /* HAVE_WINDOW_SYSTEM */
879 /* Construct a frame that refers to a terminal. */
881 static printmax_t tty_frame_count;
883 struct frame *
884 make_initial_frame (void)
886 struct frame *f;
887 struct terminal *terminal;
888 Lisp_Object frame;
890 eassert (initial_kboard);
892 /* The first call must initialize Vframe_list. */
893 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
894 Vframe_list = Qnil;
896 terminal = init_initial_terminal ();
898 f = make_frame (1);
899 XSETFRAME (frame, f);
901 Vframe_list = Fcons (frame, Vframe_list);
903 tty_frame_count = 1;
904 fset_name (f, build_pure_c_string ("F1"));
906 SET_FRAME_VISIBLE (f, 1);
908 f->output_method = terminal->type;
909 f->terminal = terminal;
910 f->terminal->reference_count++;
911 f->output_data.nothing = 0;
913 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
914 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
916 #ifdef HAVE_WINDOW_SYSTEM
917 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
918 f->horizontal_scroll_bars = false;
919 #endif
921 /* The default value of menu-bar-mode is t. */
922 set_menu_bar_lines (f, make_number (1), Qnil);
924 /* Allocate glyph matrices. */
925 adjust_frame_glyphs (f);
927 if (!noninteractive)
928 init_frame_faces (f);
930 last_nonminibuf_frame = f;
932 f->can_x_set_window_size = true;
933 f->after_make_frame = true;
935 return f;
939 static struct frame *
940 make_terminal_frame (struct terminal *terminal)
942 register struct frame *f;
943 Lisp_Object frame;
944 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
946 if (!terminal->name)
947 error ("Terminal is not live, can't create new frames on it");
949 f = make_frame (1);
951 XSETFRAME (frame, f);
952 Vframe_list = Fcons (frame, Vframe_list);
954 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
956 SET_FRAME_VISIBLE (f, 1);
958 f->terminal = terminal;
959 f->terminal->reference_count++;
960 #ifdef MSDOS
961 f->output_data.tty->display_info = &the_only_display_info;
962 if (!inhibit_window_system
963 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
964 || XFRAME (selected_frame)->output_method == output_msdos_raw))
965 f->output_method = output_msdos_raw;
966 else
967 f->output_method = output_termcap;
968 #else /* not MSDOS */
969 f->output_method = output_termcap;
970 create_tty_output (f);
971 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
972 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
973 #endif /* not MSDOS */
975 #ifdef HAVE_WINDOW_SYSTEM
976 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
977 f->horizontal_scroll_bars = false;
978 #endif
980 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
981 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
982 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
983 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
985 /* Set the top frame to the newly created frame. */
986 if (FRAMEP (FRAME_TTY (f)->top_frame)
987 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
988 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
990 FRAME_TTY (f)->top_frame = frame;
992 if (!noninteractive)
993 init_frame_faces (f);
995 return f;
998 /* Get a suitable value for frame parameter PARAMETER for a newly
999 created frame, based on (1) the user-supplied frame parameter
1000 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
1002 static Lisp_Object
1003 get_future_frame_param (Lisp_Object parameter,
1004 Lisp_Object supplied_parms,
1005 char *current_value)
1007 Lisp_Object result;
1009 result = Fassq (parameter, supplied_parms);
1010 if (NILP (result))
1011 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
1012 if (NILP (result) && current_value != NULL)
1013 result = build_string (current_value);
1014 if (!NILP (result) && !STRINGP (result))
1015 result = XCDR (result);
1016 if (NILP (result) || !STRINGP (result))
1017 result = Qnil;
1019 return result;
1022 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1023 1, 1, 0,
1024 doc: /* Create an additional terminal frame, possibly on another terminal.
1025 This function takes one argument, an alist specifying frame parameters.
1027 You can create multiple frames on a single text terminal, but only one
1028 of them (the selected terminal frame) is actually displayed.
1030 In practice, generally you don't need to specify any parameters,
1031 except when you want to create a new frame on another terminal.
1032 In that case, the `tty' parameter specifies the device file to open,
1033 and the `tty-type' parameter specifies the terminal type. Example:
1035 (make-terminal-frame \\='((tty . "/dev/pts/5") (tty-type . "xterm")))
1037 Note that changing the size of one terminal frame automatically
1038 affects all frames on the same terminal device. */)
1039 (Lisp_Object parms)
1041 struct frame *f;
1042 struct terminal *t = NULL;
1043 Lisp_Object frame, tem;
1044 struct frame *sf = SELECTED_FRAME ();
1046 #ifdef MSDOS
1047 if (sf->output_method != output_msdos_raw
1048 && sf->output_method != output_termcap)
1049 emacs_abort ();
1050 #else /* not MSDOS */
1052 #ifdef WINDOWSNT /* This should work now! */
1053 if (sf->output_method != output_termcap)
1054 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
1055 #endif
1056 #endif /* not MSDOS */
1059 Lisp_Object terminal;
1061 terminal = Fassq (Qterminal, parms);
1062 if (CONSP (terminal))
1064 terminal = XCDR (terminal);
1065 t = decode_live_terminal (terminal);
1067 #ifdef MSDOS
1068 if (t && t != the_only_display_info.terminal)
1069 /* msdos.c assumes a single tty_display_info object. */
1070 error ("Multiple terminals are not supported on this platform");
1071 if (!t)
1072 t = the_only_display_info.terminal;
1073 #endif
1076 if (!t)
1078 char *name = 0, *type = 0;
1079 Lisp_Object tty, tty_type;
1080 USE_SAFE_ALLOCA;
1082 tty = get_future_frame_param
1083 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1084 ? FRAME_TTY (XFRAME (selected_frame))->name
1085 : NULL));
1086 if (!NILP (tty))
1087 SAFE_ALLOCA_STRING (name, tty);
1089 tty_type = get_future_frame_param
1090 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1091 ? FRAME_TTY (XFRAME (selected_frame))->type
1092 : NULL));
1093 if (!NILP (tty_type))
1094 SAFE_ALLOCA_STRING (type, tty_type);
1096 t = init_tty (name, type, 0); /* Errors are not fatal. */
1097 SAFE_FREE ();
1100 f = make_terminal_frame (t);
1103 int width, height;
1104 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1105 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
1106 5, 0, Qterminal_frame);
1109 adjust_frame_glyphs (f);
1110 calculate_costs (f);
1111 XSETFRAME (frame, f);
1113 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
1114 store_in_alist (&parms, Qtty,
1115 (t->display_info.tty->name
1116 ? build_string (t->display_info.tty->name)
1117 : Qnil));
1118 /* On terminal frames the `minibuffer' frame parameter is always
1119 virtually t. Avoid that a different value in parms causes
1120 complaints, see Bug#24758. */
1121 store_in_alist (&parms, Qminibuffer, Qt);
1122 Fmodify_frame_parameters (frame, parms);
1124 /* Make the frame face alist be frame-specific, so that each
1125 frame could change its face definitions independently. */
1126 fset_face_alist (f, Fcopy_alist (sf->face_alist));
1127 /* Simple Fcopy_alist isn't enough, because we need the contents of
1128 the vectors which are the CDRs of associations in face_alist to
1129 be copied as well. */
1130 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
1131 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
1133 f->can_x_set_window_size = true;
1134 f->after_make_frame = true;
1136 return frame;
1140 /* Perform the switch to frame FRAME.
1142 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
1143 FRAME1 as frame.
1145 If TRACK is non-zero and the frame that currently has the focus
1146 redirects its focus to the selected frame, redirect that focused
1147 frame's focus to FRAME instead.
1149 FOR_DELETION non-zero means that the selected frame is being
1150 deleted, which includes the possibility that the frame's terminal
1151 is dead.
1153 The value of NORECORD is passed as argument to Fselect_window. */
1155 Lisp_Object
1156 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1158 struct frame *sf = SELECTED_FRAME (), *f;
1160 /* If FRAME is a switch-frame event, extract the frame we should
1161 switch to. */
1162 if (CONSP (frame)
1163 && EQ (XCAR (frame), Qswitch_frame)
1164 && CONSP (XCDR (frame)))
1165 frame = XCAR (XCDR (frame));
1167 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1168 a switch-frame event to arrive after a frame is no longer live,
1169 especially when deleting the initial frame during startup. */
1170 CHECK_FRAME (frame);
1171 f = XFRAME (frame);
1172 if (!FRAME_LIVE_P (f))
1173 return Qnil;
1174 else if (f == sf)
1175 return frame;
1177 /* If a frame's focus has been redirected toward the currently
1178 selected frame, we should change the redirection to point to the
1179 newly selected frame. This means that if the focus is redirected
1180 from a minibufferless frame to a surrogate minibuffer frame, we
1181 can use `other-window' to switch between all the frames using
1182 that minibuffer frame, and the focus redirection will follow us
1183 around. */
1184 #if 0
1185 /* This is too greedy; it causes inappropriate focus redirection
1186 that's hard to get rid of. */
1187 if (track)
1189 Lisp_Object tail;
1191 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1193 Lisp_Object focus;
1195 if (!FRAMEP (XCAR (tail)))
1196 emacs_abort ();
1198 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1200 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1201 Fredirect_frame_focus (XCAR (tail), frame);
1204 #else /* ! 0 */
1205 /* Instead, apply it only to the frame we're pointing to. */
1206 #ifdef HAVE_WINDOW_SYSTEM
1207 if (track && FRAME_WINDOW_P (f))
1209 Lisp_Object focus, xfocus;
1211 xfocus = x_get_focus_frame (f);
1212 if (FRAMEP (xfocus))
1214 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1215 if ((FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1216 /* Redirect frame focus also when FRAME has its minibuffer
1217 window on the selected frame (see Bug#24500). */
1218 || (NILP (focus)
1219 && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))
1220 Fredirect_frame_focus (xfocus, frame);
1223 #endif /* HAVE_X_WINDOWS */
1224 #endif /* ! 0 */
1226 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1227 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1229 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
1231 struct tty_display_info *tty = FRAME_TTY (f);
1232 Lisp_Object top_frame = tty->top_frame;
1234 /* Don't mark the frame garbaged and/or obscured if we are
1235 switching to the frame that is already the top frame of that
1236 TTY. */
1237 if (!EQ (frame, top_frame))
1239 if (FRAMEP (top_frame))
1240 /* Mark previously displayed frame as now obscured. */
1241 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1242 SET_FRAME_VISIBLE (f, 1);
1243 /* If the new TTY frame changed dimensions, we need to
1244 resync term.c's idea of the frame size with the new
1245 frame's data. */
1246 if (FRAME_COLS (f) != FrameCols (tty))
1247 FrameCols (tty) = FRAME_COLS (f);
1248 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1249 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1251 tty->top_frame = frame;
1254 selected_frame = frame;
1255 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1256 last_nonminibuf_frame = XFRAME (selected_frame);
1258 Fselect_window (f->selected_window, norecord);
1260 /* We want to make sure that the next event generates a frame-switch
1261 event to the appropriate frame. This seems kludgy to me, but
1262 before you take it out, make sure that evaluating something like
1263 (select-window (frame-root-window (new-frame))) doesn't end up
1264 with your typing being interpreted in the new frame instead of
1265 the one you're actually typing in. */
1266 #ifdef HAVE_WINDOW_SYSTEM
1267 if (!frame_ancestor_p (f, sf))
1268 #endif
1269 internal_last_event_frame = Qnil;
1271 return frame;
1274 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1275 doc: /* Select FRAME.
1276 Subsequent editing commands apply to its selected window.
1277 Optional argument NORECORD means to neither change the order of
1278 recently selected windows nor the buffer list.
1280 The selection of FRAME lasts until the next time the user does
1281 something to select a different frame, or until the next time
1282 this function is called. If you are using a window system, the
1283 previously selected frame may be restored as the selected frame
1284 when returning to the command loop, because it still may have
1285 the window system's input focus. On a text terminal, the next
1286 redisplay will display FRAME.
1288 This function returns FRAME, or nil if FRAME has been deleted. */)
1289 (Lisp_Object frame, Lisp_Object norecord)
1291 return do_switch_frame (frame, 1, 0, norecord);
1294 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1295 doc: /* Handle a switch-frame event EVENT.
1296 Switch-frame events are usually bound to this function.
1297 A switch-frame event tells Emacs that the window manager has requested
1298 that the user's events be directed to the frame mentioned in the event.
1299 This function selects the selected window of the frame of EVENT.
1301 If EVENT is frame object, handle it as if it were a switch-frame event
1302 to that frame. */)
1303 (Lisp_Object event)
1305 Lisp_Object value;
1307 /* Preserve prefix arg that the command loop just cleared. */
1308 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1309 run_hook (Qmouse_leave_buffer_hook);
1310 /* `switch-frame' implies a focus in. */
1311 value = do_switch_frame (event, 0, 0, Qnil);
1312 call1 (intern ("handle-focus-in"), event);
1313 return value;
1316 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1317 doc: /* Return the frame that is now selected. */)
1318 (void)
1320 return selected_frame;
1323 DEFUN ("frame-list", Fframe_list, Sframe_list,
1324 0, 0, 0,
1325 doc: /* Return a list of all live frames. */)
1326 (void)
1328 Lisp_Object frames;
1329 frames = Fcopy_sequence (Vframe_list);
1330 #ifdef HAVE_WINDOW_SYSTEM
1331 if (FRAMEP (tip_frame))
1332 frames = Fdelq (tip_frame, frames);
1333 #endif
1334 return frames;
1337 DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
1338 0, 1, 0,
1339 doc: /* Return the parent frame of FRAME.
1340 The parent frame of FRAME is the Emacs frame whose window-system window
1341 is the parent window of FRAME's window-system window. When such a frame
1342 exists, FRAME is considered a child frame of that frame.
1344 Return nil if FRAME has no parent frame. This means that FRAME's
1345 window-system window is either a "top-level" window (a window whose
1346 parent window is the window-system's root window) or an embedded window
1347 \(a window whose parent window is owned by some other application). */)
1348 (Lisp_Object frame)
1350 struct frame *f = decode_live_frame (frame);
1351 struct frame *p = FRAME_PARENT_FRAME (f);
1352 Lisp_Object parent;
1354 /* Can't return f->parent_frame directly since it might not be defined
1355 for this platform. */
1356 if (p)
1358 XSETFRAME (parent, p);
1360 return parent;
1362 else
1363 return Qnil;
1366 #ifdef HAVE_WINDOW_SYSTEM
1367 bool
1368 frame_ancestor_p (struct frame *af, struct frame *df)
1370 struct frame *pf = FRAME_PARENT_FRAME (df);
1372 while (pf)
1374 if (pf == af)
1375 return true;
1376 else
1377 pf = FRAME_PARENT_FRAME (pf);
1380 return false;
1382 #endif
1384 DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1385 2, 2, 0,
1386 doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
1387 ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
1388 parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
1389 ANCESTOR and DESCENDANT must be live frames and default to the selected
1390 frame. */)
1391 (Lisp_Object ancestor, Lisp_Object descendant)
1393 #ifdef HAVE_WINDOW_SYSTEM
1394 struct frame *af = decode_live_frame (ancestor);
1395 struct frame *df = decode_live_frame (descendant);
1397 return frame_ancestor_p (af, df) ? Qt : Qnil;
1398 #else
1399 return Qnil;
1400 #endif
1403 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1404 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1405 If MINIBUF is nil, do not consider minibuffer-only candidate.
1406 If MINIBUF is `visible', do not consider an invisible candidate.
1407 If MINIBUF is a window, consider only its own frame and candidate now
1408 using that window as the minibuffer.
1409 If MINIBUF is 0, consider candidate if it is visible or iconified.
1410 Otherwise consider any candidate and return nil if CANDIDATE is not
1411 acceptable. */
1413 static Lisp_Object
1414 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1416 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1418 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1419 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1420 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1421 && FRAME_TTY (c) == FRAME_TTY (f)))
1423 if (!NILP (get_frame_param (c, Qno_other_frame)))
1424 return Qnil;
1425 else if (NILP (minibuf))
1427 if (!FRAME_MINIBUF_ONLY_P (c))
1428 return candidate;
1430 else if (EQ (minibuf, Qvisible))
1432 if (FRAME_VISIBLE_P (c))
1433 return candidate;
1435 else if (WINDOWP (minibuf))
1437 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1438 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1439 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1440 FRAME_FOCUS_FRAME (c)))
1441 return candidate;
1443 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
1445 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1446 return candidate;
1448 else
1449 return candidate;
1451 return Qnil;
1454 /* Return the next frame in the frame list after FRAME. */
1456 static Lisp_Object
1457 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1459 Lisp_Object f, tail;
1460 int passed = 0;
1462 while (passed < 2)
1463 FOR_EACH_FRAME (tail, f)
1465 if (passed)
1467 f = candidate_frame (f, frame, minibuf);
1468 if (!NILP (f))
1469 return f;
1471 if (EQ (frame, f))
1472 passed++;
1474 return frame;
1477 /* Return the previous frame in the frame list before FRAME. */
1479 static Lisp_Object
1480 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1482 Lisp_Object f, tail, prev = Qnil;
1484 FOR_EACH_FRAME (tail, f)
1486 if (EQ (frame, f) && !NILP (prev))
1487 return prev;
1488 f = candidate_frame (f, frame, minibuf);
1489 if (!NILP (f))
1490 prev = f;
1493 /* We've scanned the entire list. */
1494 if (NILP (prev))
1495 /* We went through the whole frame list without finding a single
1496 acceptable frame. Return the original frame. */
1497 return frame;
1498 else
1499 /* There were no acceptable frames in the list before FRAME; otherwise,
1500 we would have returned directly from the loop. Since PREV is the last
1501 acceptable frame in the list, return it. */
1502 return prev;
1506 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1507 doc: /* Return the next frame in the frame list after FRAME.
1508 It considers only frames on the same terminal as FRAME.
1509 By default, skip minibuffer-only frames.
1510 If omitted, FRAME defaults to the selected frame.
1511 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1512 If MINIFRAME is a window, include only its own frame
1513 and any frame now using that window as the minibuffer.
1514 If MINIFRAME is `visible', include all visible frames.
1515 If MINIFRAME is 0, include all visible and iconified frames.
1516 Otherwise, include all frames. */)
1517 (Lisp_Object frame, Lisp_Object miniframe)
1519 if (NILP (frame))
1520 frame = selected_frame;
1521 CHECK_LIVE_FRAME (frame);
1522 return next_frame (frame, miniframe);
1525 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1526 doc: /* Return the previous frame in the frame list before FRAME.
1527 It considers only frames on the same terminal as FRAME.
1528 By default, skip minibuffer-only frames.
1529 If omitted, FRAME defaults to the selected frame.
1530 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1531 If MINIFRAME is a window, include only its own frame
1532 and any frame now using that window as the minibuffer.
1533 If MINIFRAME is `visible', include all visible frames.
1534 If MINIFRAME is 0, include all visible and iconified frames.
1535 Otherwise, include all frames. */)
1536 (Lisp_Object frame, Lisp_Object miniframe)
1538 if (NILP (frame))
1539 frame = selected_frame;
1540 CHECK_LIVE_FRAME (frame);
1541 return prev_frame (frame, miniframe);
1544 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1545 Slast_nonminibuf_frame, 0, 0, 0,
1546 doc: /* Return last non-minibuffer frame selected. */)
1547 (void)
1549 Lisp_Object frame = Qnil;
1551 if (last_nonminibuf_frame)
1552 XSETFRAME (frame, last_nonminibuf_frame);
1554 return frame;
1558 * other_frames:
1560 * Return true if there exists at least one visible or iconified frame
1561 * but F. Return false otherwise.
1563 * INVISIBLE true means we are called from make_frame_invisible where
1564 * such a frame must be visible or iconified. INVISIBLE nil means we
1565 * are called from delete_frame. In that case FORCE true means that the
1566 * visibility status of such a frame can be ignored.
1568 * If F is the terminal frame and we are using X, return true if at
1569 * least one X frame exists.
1571 static bool
1572 other_frames (struct frame *f, bool invisible, bool force)
1574 Lisp_Object frames, frame, frame1;
1575 struct frame *f1;
1576 Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
1578 XSETFRAME (frame, f);
1579 if (WINDOWP (minibuffer_window)
1580 && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
1581 minibuffer_window = Qnil;
1583 FOR_EACH_FRAME (frames, frame1)
1585 f1 = XFRAME (frame1);
1586 if (f != f1)
1588 /* Verify that we can still talk to the frame's X window, and
1589 note any recent change in visibility. */
1590 #ifdef HAVE_X_WINDOWS
1591 if (FRAME_WINDOW_P (f1))
1592 x_sync (f1);
1593 #endif
1594 if (NILP (Fframe_parameter (frame1, Qtooltip))
1595 /* Tooltips and child frames count neither for
1596 invisibility nor for deletions. */
1597 && !FRAME_PARENT_FRAME (f1)
1598 /* Frames with a non-nil `delete-before' parameter don't
1599 count for deletions. */
1600 && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
1601 /* For invisibility and normal deletions, at least one
1602 visible or iconified frame must remain (Bug#26682). */
1603 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
1604 || (!invisible
1605 && (force
1606 /* Allow deleting the terminal frame when at
1607 least one X frame exists. */
1608 || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))))
1609 return true;
1613 return false;
1616 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1617 window. Preferably use the selected frame's minibuffer window
1618 instead. If the selected frame doesn't have one, get some other
1619 frame's minibuffer window. SELECT non-zero means select the new
1620 minibuffer window. */
1621 static void
1622 check_minibuf_window (Lisp_Object frame, int select)
1624 struct frame *f = decode_live_frame (frame);
1626 XSETFRAME (frame, f);
1628 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1630 Lisp_Object frames, this, window = make_number (0);
1632 if (!EQ (frame, selected_frame)
1633 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1634 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1635 else
1636 FOR_EACH_FRAME (frames, this)
1638 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1640 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1641 break;
1645 /* Don't abort if no window was found (Bug#15247). */
1646 if (WINDOWP (window))
1648 /* Use set_window_buffer instead of Fset_window_buffer (see
1649 discussion of bug#11984, bug#12025, bug#12026). */
1650 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1651 minibuf_window = window;
1653 /* SELECT non-zero usually means that FRAME's minibuffer
1654 window was selected; select the new one. */
1655 if (select)
1656 Fselect_window (minibuf_window, Qnil);
1663 * delete_frame:
1665 * Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1666 * unconditionally. x_connection_closed and delete_terminal use this.
1667 * Any other value of FORCE implements the semantics described for
1668 * Fdelete_frame. */
1669 Lisp_Object
1670 delete_frame (Lisp_Object frame, Lisp_Object force)
1672 struct frame *f = decode_any_frame (frame);
1673 struct frame *sf;
1674 struct kboard *kb;
1675 Lisp_Object frames, frame1;
1676 int minibuffer_selected, is_tooltip_frame;
1677 bool nochild = !FRAME_PARENT_FRAME (f);
1679 if (!FRAME_LIVE_P (f))
1680 return Qnil;
1681 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1683 if (NILP (force))
1684 error ("Attempt to delete the sole visible or iconified frame");
1685 else
1686 error ("Attempt to delete the only frame");
1689 XSETFRAME (frame, f);
1691 /* Softly delete all frames with this frame as their parent frame or
1692 as their `delete-before' frame parameter value. */
1693 FOR_EACH_FRAME (frames, frame1)
1694 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
1695 /* Process `delete-before' parameter iff FRAME is not a child
1696 frame. This avoids that we enter an infinite chain of mixed
1697 dependencies. */
1698 || (nochild
1699 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
1700 delete_frame (frame1, Qnil);
1702 /* Does this frame have a minibuffer, and is it the surrogate
1703 minibuffer for any other frame? */
1704 if (FRAME_HAS_MINIBUF_P (f))
1706 FOR_EACH_FRAME (frames, frame1)
1708 Lisp_Object fminiw;
1710 if (EQ (frame1, frame))
1711 continue;
1713 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
1715 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1717 /* If we MUST delete this frame, delete the other first.
1718 But do this only if FORCE equals `noelisp'. */
1719 if (EQ (force, Qnoelisp))
1720 delete_frame (frame1, Qnoelisp);
1721 else
1722 error ("Attempt to delete a surrogate minibuffer frame");
1727 is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
1729 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1730 frame is a tooltip. FORCE is set to `noelisp' when handling
1731 a disconnect from the terminal, so we don't dare call Lisp
1732 code. */
1733 if (NILP (Vrun_hooks) || is_tooltip_frame)
1735 else if (EQ (force, Qnoelisp))
1736 pending_funcalls
1737 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1738 pending_funcalls);
1739 else
1741 #ifdef HAVE_X_WINDOWS
1742 /* Also, save clipboard to the clipboard manager. */
1743 x_clipboard_manager_save_frame (frame);
1744 #endif
1746 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1749 /* delete_frame_functions may have deleted any frame, including this
1750 one. */
1751 if (!FRAME_LIVE_P (f))
1752 return Qnil;
1753 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1755 if (NILP (force))
1756 error ("Attempt to delete the sole visible or iconified frame");
1757 else
1758 error ("Attempt to delete the only frame");
1761 /* At this point, we are committed to deleting the frame.
1762 There is no more chance for errors to prevent it. */
1763 minibuffer_selected = EQ (minibuf_window, selected_window);
1764 sf = SELECTED_FRAME ();
1765 /* Don't let the frame remain selected. */
1766 if (f == sf)
1768 Lisp_Object tail;
1770 /* Look for another visible frame on the same terminal.
1771 Do not call next_frame here because it may loop forever.
1772 See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1773 FOR_EACH_FRAME (tail, frame1)
1774 if (!EQ (frame, frame1)
1775 && (FRAME_TERMINAL (XFRAME (frame))
1776 == FRAME_TERMINAL (XFRAME (frame1)))
1777 && FRAME_VISIBLE_P (XFRAME (frame1)))
1778 break;
1780 /* If there is none, find *some* other frame. */
1781 if (NILP (frame1) || EQ (frame1, frame))
1783 FOR_EACH_FRAME (tail, frame1)
1785 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
1787 /* Do not change a text terminal's top-frame. */
1788 struct frame *f1 = XFRAME (frame1);
1789 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1791 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1792 if (!EQ (top_frame, frame))
1793 frame1 = top_frame;
1795 break;
1799 #ifdef NS_IMPL_COCOA
1800 else
1801 /* Under NS, there is no system mechanism for choosing a new
1802 window to get focus -- it is left to application code.
1803 So the portion of THIS application interfacing with NS
1804 needs to know about it. We call Fraise_frame, but the
1805 purpose is really to transfer focus. */
1806 Fraise_frame (frame1);
1807 #endif
1809 do_switch_frame (frame1, 0, 1, Qnil);
1810 sf = SELECTED_FRAME ();
1813 /* Don't allow minibuf_window to remain on a deleted frame. */
1814 check_minibuf_window (frame, minibuffer_selected);
1816 /* Don't let echo_area_window to remain on a deleted frame. */
1817 if (EQ (f->minibuffer_window, echo_area_window))
1818 echo_area_window = sf->minibuffer_window;
1820 /* Clear any X selections for this frame. */
1821 #ifdef HAVE_X_WINDOWS
1822 if (FRAME_X_P (f))
1823 x_clear_frame_selections (f);
1824 #endif
1826 /* Free glyphs.
1827 This function must be called before the window tree of the
1828 frame is deleted because windows contain dynamically allocated
1829 memory. */
1830 free_glyphs (f);
1832 #ifdef HAVE_WINDOW_SYSTEM
1833 /* Give chance to each font driver to free a frame specific data. */
1834 font_update_drivers (f, Qnil);
1835 #endif
1837 /* Mark all the windows that used to be on FRAME as deleted, and then
1838 remove the reference to them. */
1839 delete_all_child_windows (f->root_window);
1840 fset_root_window (f, Qnil);
1842 Vframe_list = Fdelq (frame, Vframe_list);
1843 SET_FRAME_VISIBLE (f, 0);
1845 /* Allow the vector of menu bar contents to be freed in the next
1846 garbage collection. The frame object itself may not be garbage
1847 collected until much later, because recent_keys and other data
1848 structures can still refer to it. */
1849 fset_menu_bar_vector (f, Qnil);
1851 /* If FRAME's buffer lists contains killed
1852 buffers, this helps GC to reclaim them. */
1853 fset_buffer_list (f, Qnil);
1854 fset_buried_buffer_list (f, Qnil);
1856 free_font_driver_list (f);
1857 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1858 xfree (f->namebuf);
1859 #endif
1860 xfree (f->decode_mode_spec_buffer);
1861 xfree (FRAME_INSERT_COST (f));
1862 xfree (FRAME_DELETEN_COST (f));
1863 xfree (FRAME_INSERTN_COST (f));
1864 xfree (FRAME_DELETE_COST (f));
1866 /* Since some events are handled at the interrupt level, we may get
1867 an event for f at any time; if we zero out the frame's terminal
1868 now, then we may trip up the event-handling code. Instead, we'll
1869 promise that the terminal of the frame must be valid until we
1870 have called the window-system-dependent frame destruction
1871 routine. */
1873 struct terminal *terminal;
1874 block_input ();
1875 if (FRAME_TERMINAL (f)->delete_frame_hook)
1876 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
1877 terminal = FRAME_TERMINAL (f);
1878 f->output_data.nothing = 0;
1879 f->terminal = 0; /* Now the frame is dead. */
1880 unblock_input ();
1882 /* If needed, delete the terminal that this frame was on.
1883 (This must be done after the frame is killed.) */
1884 terminal->reference_count--;
1885 #ifdef USE_GTK
1886 /* FIXME: Deleting the terminal crashes emacs because of a GTK
1887 bug.
1888 http://lists.gnu.org/archive/html/emacs-devel/2011-10/msg00363.html */
1889 if (terminal->reference_count == 0 && terminal->type == output_x_window)
1890 terminal->reference_count = 1;
1891 #endif /* USE_GTK */
1892 if (terminal->reference_count == 0)
1894 Lisp_Object tmp;
1895 XSETTERMINAL (tmp, terminal);
1897 kb = NULL;
1898 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
1900 else
1901 kb = terminal->kboard;
1904 /* If we've deleted the last_nonminibuf_frame, then try to find
1905 another one. */
1906 if (f == last_nonminibuf_frame)
1908 last_nonminibuf_frame = 0;
1910 FOR_EACH_FRAME (frames, frame1)
1912 struct frame *f1 = XFRAME (frame1);
1914 if (!FRAME_MINIBUF_ONLY_P (f1))
1916 last_nonminibuf_frame = f1;
1917 break;
1922 /* If there's no other frame on the same kboard, get out of
1923 single-kboard state if we're in it for this kboard. */
1924 if (kb != NULL)
1926 /* Some frame we found on the same kboard, or nil if there are none. */
1927 Lisp_Object frame_on_same_kboard = Qnil;
1929 FOR_EACH_FRAME (frames, frame1)
1930 if (kb == FRAME_KBOARD (XFRAME (frame1)))
1931 frame_on_same_kboard = frame1;
1933 if (NILP (frame_on_same_kboard))
1934 not_single_kboard_state (kb);
1938 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1939 find another one. Prefer minibuffer-only frames, but also notice
1940 frames with other windows. */
1941 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
1943 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
1944 Lisp_Object frame_with_minibuf = Qnil;
1945 /* Some frame we found on the same kboard, or nil if there are none. */
1946 Lisp_Object frame_on_same_kboard = Qnil;
1948 FOR_EACH_FRAME (frames, frame1)
1950 struct frame *f1 = XFRAME (frame1);
1952 /* Consider only frames on the same kboard
1953 and only those with minibuffers. */
1954 if (kb == FRAME_KBOARD (f1)
1955 && FRAME_HAS_MINIBUF_P (f1))
1957 frame_with_minibuf = frame1;
1958 if (FRAME_MINIBUF_ONLY_P (f1))
1959 break;
1962 if (kb == FRAME_KBOARD (f1))
1963 frame_on_same_kboard = frame1;
1966 if (!NILP (frame_on_same_kboard))
1968 /* We know that there must be some frame with a minibuffer out
1969 there. If this were not true, all of the frames present
1970 would have to be minibufferless, which implies that at some
1971 point their minibuffer frames must have been deleted, but
1972 that is prohibited at the top; you can't delete surrogate
1973 minibuffer frames. */
1974 if (NILP (frame_with_minibuf))
1975 emacs_abort ();
1977 kset_default_minibuffer_frame (kb, frame_with_minibuf);
1979 else
1980 /* No frames left on this kboard--say no minibuffer either. */
1981 kset_default_minibuffer_frame (kb, Qnil);
1984 /* Cause frame titles to update--necessary if we now have just one frame. */
1985 if (!is_tooltip_frame)
1986 update_mode_lines = 15;
1988 return Qnil;
1991 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
1992 doc: /* Delete FRAME, permanently eliminating it from use.
1993 FRAME must be a live frame and defaults to the selected one.
1995 A frame may not be deleted if its minibuffer serves as surrogate
1996 minibuffer for another frame. Normally, you may not delete a frame if
1997 all other frames are invisible, but if the second optional argument
1998 FORCE is non-nil, you may do so.
2000 This function runs `delete-frame-functions' before actually
2001 deleting the frame, unless the frame is a tooltip.
2002 The functions are run with one argument, the frame to be deleted. */)
2003 (Lisp_Object frame, Lisp_Object force)
2005 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
2009 /* Return mouse position in character cell units. */
2011 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
2012 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2013 The position is given in canonical character cells, where (0, 0) is the
2014 upper-left corner of the frame, X is the horizontal offset, and Y is the
2015 vertical offset, measured in units of the frame's default character size.
2016 If Emacs is running on a mouseless terminal or hasn't been programmed
2017 to read the mouse position, it returns the selected frame for FRAME
2018 and nil for X and Y.
2019 If `mouse-position-function' is non-nil, `mouse-position' calls it,
2020 passing the normal return value to that function as an argument,
2021 and returns whatever that function returns. */)
2022 (void)
2024 struct frame *f;
2025 Lisp_Object lispy_dummy;
2026 Lisp_Object x, y, retval;
2028 f = SELECTED_FRAME ();
2029 x = y = Qnil;
2031 /* It's okay for the hook to refrain from storing anything. */
2032 if (FRAME_TERMINAL (f)->mouse_position_hook)
2034 enum scroll_bar_part party_dummy;
2035 Time time_dummy;
2036 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2037 &lispy_dummy, &party_dummy,
2038 &x, &y,
2039 &time_dummy);
2042 if (! NILP (x))
2044 int col = XINT (x);
2045 int row = XINT (y);
2046 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
2047 XSETINT (x, col);
2048 XSETINT (y, row);
2050 XSETFRAME (lispy_dummy, f);
2051 retval = Fcons (lispy_dummy, Fcons (x, y));
2052 if (!NILP (Vmouse_position_function))
2053 retval = call1 (Vmouse_position_function, retval);
2054 return retval;
2057 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
2058 Smouse_pixel_position, 0, 0, 0,
2059 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2060 The position is given in pixel units, where (0, 0) is the
2061 upper-left corner of the frame, X is the horizontal offset, and Y is
2062 the vertical offset.
2063 If Emacs is running on a mouseless terminal or hasn't been programmed
2064 to read the mouse position, it returns the selected frame for FRAME
2065 and nil for X and Y. */)
2066 (void)
2068 struct frame *f;
2069 Lisp_Object lispy_dummy;
2070 Lisp_Object x, y, retval;
2072 f = SELECTED_FRAME ();
2073 x = y = Qnil;
2075 /* It's okay for the hook to refrain from storing anything. */
2076 if (FRAME_TERMINAL (f)->mouse_position_hook)
2078 enum scroll_bar_part party_dummy;
2079 Time time_dummy;
2080 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2081 &lispy_dummy, &party_dummy,
2082 &x, &y,
2083 &time_dummy);
2086 XSETFRAME (lispy_dummy, f);
2087 retval = Fcons (lispy_dummy, Fcons (x, y));
2088 if (!NILP (Vmouse_position_function))
2089 retval = call1 (Vmouse_position_function, retval);
2090 return retval;
2093 #ifdef HAVE_WINDOW_SYSTEM
2095 /* On frame F, convert character coordinates X and Y to pixel
2096 coordinates *PIX_X and *PIX_Y. */
2098 static void
2099 frame_char_to_pixel_position (struct frame *f, int x, int y,
2100 int *pix_x, int *pix_y)
2102 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
2103 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
2105 if (*pix_x < 0)
2106 *pix_x = 0;
2107 if (*pix_x > FRAME_PIXEL_WIDTH (f))
2108 *pix_x = FRAME_PIXEL_WIDTH (f);
2110 if (*pix_y < 0)
2111 *pix_y = 0;
2112 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
2113 *pix_y = FRAME_PIXEL_HEIGHT (f);
2116 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
2118 static void
2119 frame_set_mouse_position (struct frame *f, int x, int y)
2121 int pix_x, pix_y;
2123 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
2124 frame_set_mouse_pixel_position (f, pix_x, pix_y);
2127 #endif /* HAVE_WINDOW_SYSTEM */
2129 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
2130 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
2131 Coordinates are relative to the frame, not a window,
2132 so the coordinates of the top left character in the frame
2133 may be nonzero due to left-hand scroll bars or the menu bar.
2135 The position is given in canonical character cells, where (0, 0) is
2136 the upper-left corner of the frame, X is the horizontal offset, and
2137 Y is the vertical offset, measured in units of the frame's default
2138 character size.
2140 This function is a no-op for an X frame that is not visible.
2141 If you have just created a frame, you must wait for it to become visible
2142 before calling this function on it, like this.
2143 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2144 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2146 CHECK_LIVE_FRAME (frame);
2147 CHECK_TYPE_RANGED_INTEGER (int, x);
2148 CHECK_TYPE_RANGED_INTEGER (int, y);
2150 /* I think this should be done with a hook. */
2151 #ifdef HAVE_WINDOW_SYSTEM
2152 if (FRAME_WINDOW_P (XFRAME (frame)))
2153 /* Warping the mouse will cause enternotify and focus events. */
2154 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
2155 #else
2156 #if defined (MSDOS)
2157 if (FRAME_MSDOS_P (XFRAME (frame)))
2159 Fselect_frame (frame, Qnil);
2160 mouse_moveto (XINT (x), XINT (y));
2162 #else
2163 #ifdef HAVE_GPM
2165 Fselect_frame (frame, Qnil);
2166 term_mouse_moveto (XINT (x), XINT (y));
2168 #endif
2169 #endif
2170 #endif
2172 return Qnil;
2175 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
2176 Sset_mouse_pixel_position, 3, 3, 0,
2177 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
2178 The position is given in pixels, where (0, 0) is the upper-left corner
2179 of the frame, X is the horizontal offset, and Y is the vertical offset.
2181 Note, this is a no-op for an X frame that is not visible.
2182 If you have just created a frame, you must wait for it to become visible
2183 before calling this function on it, like this.
2184 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2185 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2187 CHECK_LIVE_FRAME (frame);
2188 CHECK_TYPE_RANGED_INTEGER (int, x);
2189 CHECK_TYPE_RANGED_INTEGER (int, y);
2191 /* I think this should be done with a hook. */
2192 #ifdef HAVE_WINDOW_SYSTEM
2193 if (FRAME_WINDOW_P (XFRAME (frame)))
2194 /* Warping the mouse will cause enternotify and focus events. */
2195 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
2196 #else
2197 #if defined (MSDOS)
2198 if (FRAME_MSDOS_P (XFRAME (frame)))
2200 Fselect_frame (frame, Qnil);
2201 mouse_moveto (XINT (x), XINT (y));
2203 #else
2204 #ifdef HAVE_GPM
2206 Fselect_frame (frame, Qnil);
2207 term_mouse_moveto (XINT (x), XINT (y));
2209 #endif
2210 #endif
2211 #endif
2213 return Qnil;
2216 static void make_frame_visible_1 (Lisp_Object);
2218 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
2219 0, 1, "",
2220 doc: /* Make the frame FRAME visible (assuming it is an X window).
2221 If omitted, FRAME defaults to the currently selected frame. */)
2222 (Lisp_Object frame)
2224 struct frame *f = decode_live_frame (frame);
2226 /* I think this should be done with a hook. */
2227 #ifdef HAVE_WINDOW_SYSTEM
2228 if (FRAME_WINDOW_P (f))
2229 x_make_frame_visible (f);
2230 #endif
2232 make_frame_visible_1 (f->root_window);
2234 /* Make menu bar update for the Buffers and Frames menus. */
2235 /* windows_or_buffers_changed = 15; FIXME: Why? */
2237 XSETFRAME (frame, f);
2238 return frame;
2241 /* Update the display_time slot of the buffers shown in WINDOW
2242 and all its descendants. */
2244 static void
2245 make_frame_visible_1 (Lisp_Object window)
2247 struct window *w;
2249 for (; !NILP (window); window = w->next)
2251 w = XWINDOW (window);
2252 if (WINDOWP (w->contents))
2253 make_frame_visible_1 (w->contents);
2254 else
2255 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2259 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2260 0, 2, "",
2261 doc: /* Make the frame FRAME invisible.
2262 If omitted, FRAME defaults to the currently selected frame.
2263 On graphical displays, invisible frames are not updated and are
2264 usually not displayed at all, even in a window system's \"taskbar\".
2266 Normally you may not make FRAME invisible if all other frames are invisible,
2267 but if the second optional argument FORCE is non-nil, you may do so.
2269 This function has no effect on text terminal frames. Such frames are
2270 always considered visible, whether or not they are currently being
2271 displayed in the terminal. */)
2272 (Lisp_Object frame, Lisp_Object force)
2274 struct frame *f = decode_live_frame (frame);
2276 if (NILP (force) && !other_frames (f, true, false))
2277 error ("Attempt to make invisible the sole visible or iconified frame");
2279 /* Don't allow minibuf_window to remain on an invisible frame. */
2280 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2282 /* I think this should be done with a hook. */
2283 #ifdef HAVE_WINDOW_SYSTEM
2284 if (FRAME_WINDOW_P (f))
2285 x_make_frame_invisible (f);
2286 #endif
2288 /* Make menu bar update for the Buffers and Frames menus. */
2289 windows_or_buffers_changed = 16;
2291 return Qnil;
2294 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2295 0, 1, "",
2296 doc: /* Make the frame FRAME into an icon.
2297 If omitted, FRAME defaults to the currently selected frame. */)
2298 (Lisp_Object frame)
2300 struct frame *f = decode_live_frame (frame);
2302 /* Don't allow minibuf_window to remain on an iconified frame. */
2303 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2305 /* I think this should be done with a hook. */
2306 if (FRAME_WINDOW_P (f))
2308 #ifdef HAVE_WINDOW_SYSTEM
2309 x_iconify_frame (f);
2310 #endif
2313 return Qnil;
2316 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2317 1, 1, 0,
2318 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2319 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2320 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2321 On graphical displays, invisible frames are not updated and are
2322 usually not displayed at all, even in a window system's \"taskbar\".
2324 If FRAME is a text terminal frame, this always returns t.
2325 Such frames are always considered visible, whether or not they are
2326 currently being displayed on the terminal. */)
2327 (Lisp_Object frame)
2329 CHECK_LIVE_FRAME (frame);
2331 if (FRAME_VISIBLE_P (XFRAME (frame)))
2332 return Qt;
2333 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2334 return Qicon;
2335 return Qnil;
2338 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2339 0, 0, 0,
2340 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2341 (void)
2343 Lisp_Object tail, frame, value = Qnil;
2345 FOR_EACH_FRAME (tail, frame)
2346 if (FRAME_VISIBLE_P (XFRAME (frame)))
2347 value = Fcons (frame, value);
2349 return value;
2353 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2354 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2355 If FRAME is invisible or iconified, make it visible.
2356 If you don't specify a frame, the selected frame is used.
2357 If Emacs is displaying on an ordinary terminal or some other device which
2358 doesn't support multiple overlapping frames, this function selects FRAME. */)
2359 (Lisp_Object frame)
2361 struct frame *f = decode_live_frame (frame);
2363 XSETFRAME (frame, f);
2365 if (FRAME_TERMCAP_P (f))
2366 /* On a text terminal select FRAME. */
2367 Fselect_frame (frame, Qnil);
2368 else
2369 /* Do like the documentation says. */
2370 Fmake_frame_visible (frame);
2372 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2373 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2375 return Qnil;
2378 /* Should we have a corresponding function called Flower_Power? */
2379 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2380 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2381 If you don't specify a frame, the selected frame is used.
2382 If Emacs is displaying on an ordinary terminal or some other device which
2383 doesn't support multiple overlapping frames, this function does nothing. */)
2384 (Lisp_Object frame)
2386 struct frame *f = decode_live_frame (frame);
2388 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2389 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2391 return Qnil;
2395 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2396 1, 2, 0,
2397 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2398 In other words, switch-frame events caused by events in FRAME will
2399 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2400 FOCUS-FRAME after reading an event typed at FRAME.
2402 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2403 frame again receives its own keystrokes.
2405 Focus redirection is useful for temporarily redirecting keystrokes to
2406 a surrogate minibuffer frame when a frame doesn't have its own
2407 minibuffer window.
2409 A frame's focus redirection can be changed by `select-frame'. If frame
2410 FOO is selected, and then a different frame BAR is selected, any
2411 frames redirecting their focus to FOO are shifted to redirect their
2412 focus to BAR. This allows focus redirection to work properly when the
2413 user switches from one frame to another using `select-window'.
2415 This means that a frame whose focus is redirected to itself is treated
2416 differently from a frame whose focus is redirected to nil; the former
2417 is affected by `select-frame', while the latter is not.
2419 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2420 (Lisp_Object frame, Lisp_Object focus_frame)
2422 /* Note that we don't check for a live frame here. It's reasonable
2423 to redirect the focus of a frame you're about to delete, if you
2424 know what other frame should receive those keystrokes. */
2425 struct frame *f = decode_any_frame (frame);
2427 if (! NILP (focus_frame))
2428 CHECK_LIVE_FRAME (focus_frame);
2430 fset_focus_frame (f, focus_frame);
2432 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2433 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2435 return Qnil;
2439 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2440 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2441 If FRAME is omitted or nil, the selected frame is used.
2442 Return nil if FRAME's focus is not redirected.
2443 See `redirect-frame-focus'. */)
2444 (Lisp_Object frame)
2446 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2449 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 2, 0,
2450 doc: /* Set the input focus to FRAME.
2451 FRAME nil means use the selected frame. Optional argument NOACTIVATE
2452 means do not activate FRAME.
2454 If there is no window system support, this function does nothing. */)
2455 (Lisp_Object frame, Lisp_Object noactivate)
2457 #ifdef HAVE_WINDOW_SYSTEM
2458 x_focus_frame (decode_window_system_frame (frame), !NILP (noactivate));
2459 #endif
2460 return Qnil;
2463 DEFUN ("frame-after-make-frame",
2464 Fframe_after_make_frame,
2465 Sframe_after_make_frame, 2, 2, 0,
2466 doc: /* Mark FRAME as made.
2467 FRAME nil means use the selected frame. Second argument MADE non-nil
2468 means functions on `window-configuration-change-hook' are called
2469 whenever the window configuration of FRAME changes. MADE nil means
2470 these functions are not called.
2472 This function is currently called by `make-frame' only and should be
2473 otherwise used with utter care to avoid that running functions on
2474 `window-configuration-change-hook' is impeded forever. */)
2475 (Lisp_Object frame, Lisp_Object made)
2477 struct frame *f = decode_live_frame (frame);
2478 f->after_make_frame = !NILP (made);
2479 f->inhibit_horizontal_resize = false;
2480 f->inhibit_vertical_resize = false;
2481 return made;
2485 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2487 void
2488 frames_discard_buffer (Lisp_Object buffer)
2490 Lisp_Object frame, tail;
2492 FOR_EACH_FRAME (tail, frame)
2494 fset_buffer_list
2495 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2496 fset_buried_buffer_list
2497 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2501 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2502 If the alist already has an element for PROP, we change it. */
2504 void
2505 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2507 register Lisp_Object tem;
2509 tem = Fassq (prop, *alistptr);
2510 if (EQ (tem, Qnil))
2511 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2512 else
2513 Fsetcdr (tem, val);
2516 static int
2517 frame_name_fnn_p (char *str, ptrdiff_t len)
2519 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2521 char *p = str + 2;
2522 while ('0' <= *p && *p <= '9')
2523 p++;
2524 if (p == str + len)
2525 return 1;
2527 return 0;
2530 /* Set the name of the terminal frame. Also used by MSDOS frames.
2531 Modeled after x_set_name which is used for WINDOW frames. */
2533 static void
2534 set_term_frame_name (struct frame *f, Lisp_Object name)
2536 f->explicit_name = ! NILP (name);
2538 /* If NAME is nil, set the name to F<num>. */
2539 if (NILP (name))
2541 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2543 /* Check for no change needed in this very common case
2544 before we do any consing. */
2545 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2546 return;
2548 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2550 else
2552 CHECK_STRING (name);
2554 /* Don't change the name if it's already NAME. */
2555 if (! NILP (Fstring_equal (name, f->name)))
2556 return;
2558 /* Don't allow the user to set the frame name to F<num>, so it
2559 doesn't clash with the names we generate for terminal frames. */
2560 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2561 error ("Frame names of the form F<num> are usurped by Emacs");
2564 fset_name (f, name);
2565 update_mode_lines = 16;
2568 void
2569 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2571 register Lisp_Object old_alist_elt;
2573 if (EQ (prop, Qminibuffer))
2575 if (WINDOWP (val))
2577 if (!MINI_WINDOW_P (XWINDOW (val)))
2578 error ("The `minibuffer' parameter does not specify a valid minibuffer window");
2579 else if (FRAME_MINIBUF_ONLY_P (f))
2581 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2582 val = Qonly;
2583 else
2584 error ("Can't change the minibuffer window of a minibuffer-only frame");
2586 else if (FRAME_HAS_MINIBUF_P (f))
2588 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2589 val = Qt;
2590 else
2591 error ("Can't change the minibuffer window of a frame with its own minibuffer");
2593 else
2594 /* Store the chosen minibuffer window. */
2595 fset_minibuffer_window (f, val);
2597 else
2599 Lisp_Object old_val = Fcdr (Fassq (Qminibuffer, f->param_alist));
2601 if (!NILP (old_val))
2603 if (WINDOWP (old_val) && NILP (val))
2604 /* Don't change the value for a minibuffer-less frame if
2605 only nil was specified as new value. */
2606 val = old_val;
2607 else if (!EQ (old_val, val))
2608 error ("Can't change the `minibuffer' parameter of this frame");
2613 /* Check each parent-frame and delete-before parameter for a
2614 circular dependency. Do not check between parameters, so you can
2615 still create circular dependencies with different properties, for
2616 example a chain of frames F1->F2->...Fn such that F1 is an ancestor
2617 frame of Fn and thus cannot be deleted before Fn and a second chain
2618 Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
2619 else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
2621 Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
2623 if (!EQ (oldval, val) && !NILP (val))
2625 Lisp_Object frame;
2626 Lisp_Object frame1 = val;
2628 if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
2629 error ("Invalid `%s' frame parameter",
2630 SSDATA (SYMBOL_NAME (prop)));
2632 XSETFRAME (frame, f);
2634 while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
2635 if (EQ (frame1, frame))
2636 error ("Circular specification of `%s' frame parameter",
2637 SSDATA (SYMBOL_NAME (prop)));
2638 else
2639 frame1 = get_frame_param (XFRAME (frame1), prop);
2643 /* The buffer-list parameters are stored in a special place and not
2644 in the alist. All buffers must be live. */
2645 else if (EQ (prop, Qbuffer_list))
2647 Lisp_Object list = Qnil;
2648 for (; CONSP (val); val = XCDR (val))
2649 if (!NILP (Fbuffer_live_p (XCAR (val))))
2650 list = Fcons (XCAR (val), list);
2651 fset_buffer_list (f, Fnreverse (list));
2652 return;
2654 else if (EQ (prop, Qburied_buffer_list))
2656 Lisp_Object list = Qnil;
2657 for (; CONSP (val); val = XCDR (val))
2658 if (!NILP (Fbuffer_live_p (XCAR (val))))
2659 list = Fcons (XCAR (val), list);
2660 fset_buried_buffer_list (f, Fnreverse (list));
2661 return;
2664 /* The tty color needed to be set before the frame's parameter
2665 alist was updated with the new value. This is not true any more,
2666 but we still do this test early on. */
2667 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2668 && f == FRAME_TTY (f)->previous_frame)
2669 /* Force redisplay of this tty. */
2670 FRAME_TTY (f)->previous_frame = NULL;
2672 /* Update the frame parameter alist. */
2673 old_alist_elt = Fassq (prop, f->param_alist);
2674 if (EQ (old_alist_elt, Qnil))
2675 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2676 else
2677 Fsetcdr (old_alist_elt, val);
2679 /* Update some other special parameters in their special places
2680 in addition to the alist. */
2682 if (EQ (prop, Qbuffer_predicate))
2683 fset_buffer_predicate (f, val);
2685 if (! FRAME_WINDOW_P (f))
2687 if (EQ (prop, Qmenu_bar_lines))
2688 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2689 else if (EQ (prop, Qname))
2690 set_term_frame_name (f, val);
2694 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2695 is not an unspecified foreground or background color. */
2697 static Lisp_Object
2698 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
2700 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
2701 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
2702 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
2703 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
2706 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
2707 doc: /* Return the parameters-alist of frame FRAME.
2708 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2709 The meaningful PARMs depend on the kind of frame.
2710 If FRAME is omitted or nil, return information on the currently selected frame. */)
2711 (Lisp_Object frame)
2713 Lisp_Object alist;
2714 struct frame *f = decode_any_frame (frame);
2715 int height, width;
2717 if (!FRAME_LIVE_P (f))
2718 return Qnil;
2720 alist = Fcopy_alist (f->param_alist);
2722 if (!FRAME_WINDOW_P (f))
2724 Lisp_Object elt;
2726 /* If the frame's parameter alist says the colors are
2727 unspecified and reversed, take the frame's background pixel
2728 for foreground and vice versa. */
2729 elt = Fassq (Qforeground_color, alist);
2730 if (CONSP (elt) && STRINGP (XCDR (elt)))
2732 elt = frame_unspecified_color (f, XCDR (elt));
2733 if (!NILP (elt))
2734 store_in_alist (&alist, Qforeground_color, elt);
2736 else
2737 store_in_alist (&alist, Qforeground_color,
2738 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
2739 elt = Fassq (Qbackground_color, alist);
2740 if (CONSP (elt) && STRINGP (XCDR (elt)))
2742 elt = frame_unspecified_color (f, XCDR (elt));
2743 if (!NILP (elt))
2744 store_in_alist (&alist, Qbackground_color, elt);
2746 else
2747 store_in_alist (&alist, Qbackground_color,
2748 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
2749 store_in_alist (&alist, Qfont,
2750 build_string (FRAME_MSDOS_P (f)
2751 ? "ms-dos"
2752 : FRAME_W32_P (f) ? "w32term"
2753 :"tty"));
2755 store_in_alist (&alist, Qname, f->name);
2756 height = (f->new_height
2757 ? (f->new_pixelwise
2758 ? (f->new_height / FRAME_LINE_HEIGHT (f))
2759 : f->new_height)
2760 : FRAME_LINES (f));
2761 store_in_alist (&alist, Qheight, make_number (height));
2762 width = (f->new_width
2763 ? (f->new_pixelwise
2764 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
2765 : f->new_width)
2766 : FRAME_COLS (f));
2767 store_in_alist (&alist, Qwidth, make_number (width));
2768 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
2769 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
2770 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
2771 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
2773 /* I think this should be done with a hook. */
2774 #ifdef HAVE_WINDOW_SYSTEM
2775 if (FRAME_WINDOW_P (f))
2776 x_report_frame_params (f, &alist);
2777 else
2778 #endif
2780 /* This ought to be correct in f->param_alist for an X frame. */
2781 Lisp_Object lines;
2782 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
2783 store_in_alist (&alist, Qmenu_bar_lines, lines);
2786 return alist;
2790 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
2791 doc: /* Return FRAME's value for parameter PARAMETER.
2792 If FRAME is nil, describe the currently selected frame. */)
2793 (Lisp_Object frame, Lisp_Object parameter)
2795 struct frame *f = decode_any_frame (frame);
2796 Lisp_Object value = Qnil;
2798 CHECK_SYMBOL (parameter);
2800 XSETFRAME (frame, f);
2802 if (FRAME_LIVE_P (f))
2804 /* Avoid consing in frequent cases. */
2805 if (EQ (parameter, Qname))
2806 value = f->name;
2807 #ifdef HAVE_WINDOW_SYSTEM
2808 /* These are used by vertical motion commands. */
2809 else if (EQ (parameter, Qvertical_scroll_bars))
2810 value = (f->vertical_scroll_bar_type == vertical_scroll_bar_none
2811 ? Qnil
2812 : (f->vertical_scroll_bar_type == vertical_scroll_bar_left
2813 ? Qleft : Qright));
2814 else if (EQ (parameter, Qhorizontal_scroll_bars))
2815 value = f->horizontal_scroll_bars ? Qt : Qnil;
2816 else if (EQ (parameter, Qline_spacing) && f->extra_line_spacing == 0)
2817 /* If this is non-zero, we can't determine whether the user specified
2818 an integer or float value without looking through 'param_alist'. */
2819 value = make_number (0);
2820 else if (EQ (parameter, Qfont) && FRAME_X_P (f))
2821 value = FRAME_FONT (f)->props[FONT_NAME_INDEX];
2822 #endif /* HAVE_WINDOW_SYSTEM */
2823 #ifdef HAVE_X_WINDOWS
2824 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2825 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
2826 #endif /* HAVE_X_WINDOWS */
2827 else if (EQ (parameter, Qbackground_color)
2828 || EQ (parameter, Qforeground_color))
2830 value = Fassq (parameter, f->param_alist);
2831 if (CONSP (value))
2833 value = XCDR (value);
2834 /* Fframe_parameters puts the actual fg/bg color names,
2835 even if f->param_alist says otherwise. This is
2836 important when param_alist's notion of colors is
2837 "unspecified". We need to do the same here. */
2838 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2840 Lisp_Object tem = frame_unspecified_color (f, value);
2842 if (!NILP (tem))
2843 value = tem;
2846 else
2847 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2849 else if (EQ (parameter, Qdisplay_type)
2850 || EQ (parameter, Qbackground_mode))
2851 value = Fcdr (Fassq (parameter, f->param_alist));
2852 else
2853 /* FIXME: Avoid this code path at all (as well as code duplication)
2854 by sharing more code with Fframe_parameters. */
2855 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2858 return value;
2862 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
2863 Smodify_frame_parameters, 2, 2, 0,
2864 doc: /* Modify FRAME according to new values of its parameters in ALIST.
2865 If FRAME is nil, it defaults to the selected frame.
2866 ALIST is an alist of parameters to change and their new values.
2867 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
2868 Which PARMs are meaningful depends on the kind of frame.
2869 The meaningful parameters are acted upon, i.e. the frame is changed
2870 according to their new values, and are also stored in the frame's
2871 parameter list so that `frame-parameters' will return them.
2872 PARMs that are not meaningful are still stored in the frame's parameter
2873 list, but are otherwise ignored. */)
2874 (Lisp_Object frame, Lisp_Object alist)
2876 struct frame *f = decode_live_frame (frame);
2877 Lisp_Object prop, val;
2879 /* I think this should be done with a hook. */
2880 #ifdef HAVE_WINDOW_SYSTEM
2881 if (FRAME_WINDOW_P (f))
2882 x_set_frame_parameters (f, alist);
2883 else
2884 #endif
2885 #ifdef MSDOS
2886 if (FRAME_MSDOS_P (f))
2887 IT_set_frame_parameters (f, alist);
2888 else
2889 #endif
2892 EMACS_INT length = XFASTINT (Flength (alist));
2893 ptrdiff_t i;
2894 Lisp_Object *parms;
2895 Lisp_Object *values;
2896 USE_SAFE_ALLOCA;
2897 SAFE_ALLOCA_LISP (parms, 2 * length);
2898 values = parms + length;
2900 /* Extract parm names and values into those vectors. */
2902 for (i = 0; CONSP (alist); alist = XCDR (alist))
2904 Lisp_Object elt;
2906 elt = XCAR (alist);
2907 parms[i] = Fcar (elt);
2908 values[i] = Fcdr (elt);
2909 i++;
2912 /* Now process them in reverse of specified order. */
2913 while (--i >= 0)
2915 prop = parms[i];
2916 val = values[i];
2917 store_frame_param (f, prop, val);
2919 if (EQ (prop, Qforeground_color)
2920 || EQ (prop, Qbackground_color))
2921 update_face_from_frame_parameter (f, prop, val);
2924 SAFE_FREE ();
2926 return Qnil;
2929 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
2930 0, 1, 0,
2931 doc: /* Height in pixels of a line in the font in frame FRAME.
2932 If FRAME is omitted or nil, the selected frame is used.
2933 For a terminal frame, the value is always 1. */)
2934 (Lisp_Object frame)
2936 #ifdef HAVE_WINDOW_SYSTEM
2937 struct frame *f = decode_any_frame (frame);
2939 if (FRAME_WINDOW_P (f))
2940 return make_number (FRAME_LINE_HEIGHT (f));
2941 else
2942 #endif
2943 return make_number (1);
2947 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
2948 0, 1, 0,
2949 doc: /* Width in pixels of characters in the font in frame FRAME.
2950 If FRAME is omitted or nil, the selected frame is used.
2951 On a graphical screen, the width is the standard width of the default font.
2952 For a terminal screen, the value is always 1. */)
2953 (Lisp_Object frame)
2955 #ifdef HAVE_WINDOW_SYSTEM
2956 struct frame *f = decode_any_frame (frame);
2958 if (FRAME_WINDOW_P (f))
2959 return make_number (FRAME_COLUMN_WIDTH (f));
2960 else
2961 #endif
2962 return make_number (1);
2965 DEFUN ("frame-pixel-height", Fframe_pixel_height,
2966 Sframe_pixel_height, 0, 1, 0,
2967 doc: /* Return a FRAME's height in pixels.
2968 If FRAME is omitted or nil, the selected frame is used. The exact value
2969 of the result depends on the window-system and toolkit in use:
2971 In the Gtk+ version of Emacs, it includes only any window (including
2972 the minibuffer or echo area), mode line, and header line. It does not
2973 include the tool bar or menu bar.
2975 With other graphical versions, it also includes the tool bar and the
2976 menu bar.
2978 For a text terminal, it includes the menu bar. In this case, the
2979 result is really in characters rather than pixels (i.e., is identical
2980 to `frame-height'). */)
2981 (Lisp_Object frame)
2983 struct frame *f = decode_any_frame (frame);
2985 #ifdef HAVE_WINDOW_SYSTEM
2986 if (FRAME_WINDOW_P (f))
2987 return make_number (FRAME_PIXEL_HEIGHT (f));
2988 else
2989 #endif
2990 return make_number (FRAME_TOTAL_LINES (f));
2993 DEFUN ("frame-pixel-width", Fframe_pixel_width,
2994 Sframe_pixel_width, 0, 1, 0,
2995 doc: /* Return FRAME's width in pixels.
2996 For a terminal frame, the result really gives the width in characters.
2997 If FRAME is omitted or nil, the selected frame is used. */)
2998 (Lisp_Object frame)
3000 struct frame *f = decode_any_frame (frame);
3002 #ifdef HAVE_WINDOW_SYSTEM
3003 if (FRAME_WINDOW_P (f))
3004 return make_number (FRAME_PIXEL_WIDTH (f));
3005 else
3006 #endif
3007 return make_number (FRAME_TOTAL_COLS (f));
3010 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
3011 Stool_bar_pixel_width, 0, 1, 0,
3012 doc: /* Return width in pixels of FRAME's tool bar.
3013 The result is greater than zero only when the tool bar is on the left
3014 or right side of FRAME. If FRAME is omitted or nil, the selected frame
3015 is used. */)
3016 (Lisp_Object frame)
3018 #ifdef FRAME_TOOLBAR_WIDTH
3019 struct frame *f = decode_any_frame (frame);
3021 if (FRAME_WINDOW_P (f))
3022 return make_number (FRAME_TOOLBAR_WIDTH (f));
3023 #endif
3024 return make_number (0);
3027 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
3028 doc: /* Return width in columns of FRAME's text area. */)
3029 (Lisp_Object frame)
3031 return make_number (FRAME_COLS (decode_any_frame (frame)));
3034 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
3035 doc: /* Return height in lines of FRAME's text area. */)
3036 (Lisp_Object frame)
3038 return make_number (FRAME_LINES (decode_any_frame (frame)));
3041 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
3042 doc: /* Return number of total columns of FRAME. */)
3043 (Lisp_Object frame)
3045 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
3048 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
3049 doc: /* Return number of total lines of FRAME. */)
3050 (Lisp_Object frame)
3052 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
3055 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
3056 doc: /* Return text area width of FRAME in pixels. */)
3057 (Lisp_Object frame)
3059 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
3062 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
3063 doc: /* Return text area height of FRAME in pixels. */)
3064 (Lisp_Object frame)
3066 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
3069 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
3070 doc: /* Return scroll bar width of FRAME in pixels. */)
3071 (Lisp_Object frame)
3073 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
3076 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
3077 doc: /* Return scroll bar height of FRAME in pixels. */)
3078 (Lisp_Object frame)
3080 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
3083 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
3084 doc: /* Return fringe width of FRAME in pixels. */)
3085 (Lisp_Object frame)
3087 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
3090 DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0,
3091 doc: /* Return border width of FRAME in pixels. */)
3092 (Lisp_Object frame)
3094 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
3097 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
3098 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
3099 (Lisp_Object frame)
3101 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
3104 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
3105 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
3106 (Lisp_Object frame)
3108 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
3111 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
3112 doc: /* Set text height of frame FRAME to HEIGHT lines.
3113 Optional third arg PRETEND non-nil means that redisplay should use
3114 HEIGHT lines but that the idea of the actual height of the frame should
3115 not be changed.
3117 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3118 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
3119 window managers may refuse to honor a HEIGHT that is not an integer
3120 multiple of the default frame font height. */)
3121 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
3123 struct frame *f = decode_live_frame (frame);
3124 int pixel_height;
3126 CHECK_TYPE_RANGED_INTEGER (int, height);
3128 pixel_height = (!NILP (pixelwise)
3129 ? XINT (height)
3130 : XINT (height) * FRAME_LINE_HEIGHT (f));
3131 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
3133 return Qnil;
3136 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
3137 doc: /* Set text width of frame FRAME to WIDTH columns.
3138 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
3139 columns but that the idea of the actual width of the frame should not
3140 be changed.
3142 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3143 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
3144 window managers may refuse to honor a WIDTH that is not an integer
3145 multiple of the default frame font width. */)
3146 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
3148 struct frame *f = decode_live_frame (frame);
3149 int pixel_width;
3151 CHECK_TYPE_RANGED_INTEGER (int, width);
3153 pixel_width = (!NILP (pixelwise)
3154 ? XINT (width)
3155 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3156 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
3158 return Qnil;
3161 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
3162 doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
3163 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
3164 When `frame-resize-pixelwise' is nil, some window managers may refuse to
3165 honor a WIDTH that is not an integer multiple of the default frame font
3166 width or a HEIGHT that is not an integer multiple of the default frame
3167 font height. */)
3168 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
3170 struct frame *f = decode_live_frame (frame);
3171 int pixel_width, pixel_height;
3173 CHECK_TYPE_RANGED_INTEGER (int, width);
3174 CHECK_TYPE_RANGED_INTEGER (int, height);
3176 pixel_width = (!NILP (pixelwise)
3177 ? XINT (width)
3178 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3179 pixel_height = (!NILP (pixelwise)
3180 ? XINT (height)
3181 : XINT (height) * FRAME_LINE_HEIGHT (f));
3182 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
3184 return Qnil;
3187 DEFUN ("frame-position", Fframe_position,
3188 Sframe_position, 0, 1, 0,
3189 doc: /* Return top left corner of FRAME in pixels.
3190 FRAME must be a live frame and defaults to the selected one. The return
3191 value is a cons (x, y) of the coordinates of the top left corner of
3192 FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
3193 display. */)
3194 (Lisp_Object frame)
3196 register struct frame *f = decode_live_frame (frame);
3198 return Fcons (make_number (f->left_pos), make_number (f->top_pos));
3201 DEFUN ("set-frame-position", Fset_frame_position,
3202 Sset_frame_position, 3, 3, 0,
3203 doc: /* Set position of FRAME to (X, Y).
3204 FRAME must be a live frame and defaults to the selected one. X and Y,
3205 if positive, specify the coordinate of the left and top edge of FRAME's
3206 outer frame in pixels relative to an origin (0, 0) of FRAME's display.
3207 If any of X or Y is negative, it specifies the coordinates of the right
3208 or bottom edge of the outer frame of FRAME relative to the right or
3209 bottom edge of FRAME's display. */)
3210 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
3212 struct frame *f = decode_live_frame (frame);
3214 CHECK_TYPE_RANGED_INTEGER (int, x);
3215 CHECK_TYPE_RANGED_INTEGER (int, y);
3217 /* I think this should be done with a hook. */
3218 if (FRAME_WINDOW_P (f))
3220 #ifdef HAVE_WINDOW_SYSTEM
3221 x_set_offset (f, XINT (x), XINT (y), 1);
3222 #endif
3225 return Qt;
3229 /***********************************************************************
3230 Frame Parameters
3231 ***********************************************************************/
3233 /* Connect the frame-parameter names for X frames
3234 to the ways of passing the parameter values to the window system.
3236 The name of a parameter, as a Lisp symbol,
3237 has an `x-frame-parameter' property which is an integer in Lisp
3238 that is an index in this table. */
3240 struct frame_parm_table {
3241 const char *name;
3242 int sym;
3245 static const struct frame_parm_table frame_parms[] =
3247 {"auto-raise", SYMBOL_INDEX (Qauto_raise)},
3248 {"auto-lower", SYMBOL_INDEX (Qauto_lower)},
3249 {"background-color", -1},
3250 {"border-color", SYMBOL_INDEX (Qborder_color)},
3251 {"border-width", SYMBOL_INDEX (Qborder_width)},
3252 {"cursor-color", SYMBOL_INDEX (Qcursor_color)},
3253 {"cursor-type", SYMBOL_INDEX (Qcursor_type)},
3254 {"font", -1},
3255 {"foreground-color", -1},
3256 {"icon-name", SYMBOL_INDEX (Qicon_name)},
3257 {"icon-type", SYMBOL_INDEX (Qicon_type)},
3258 {"internal-border-width", SYMBOL_INDEX (Qinternal_border_width)},
3259 {"right-divider-width", SYMBOL_INDEX (Qright_divider_width)},
3260 {"bottom-divider-width", SYMBOL_INDEX (Qbottom_divider_width)},
3261 {"menu-bar-lines", SYMBOL_INDEX (Qmenu_bar_lines)},
3262 {"mouse-color", SYMBOL_INDEX (Qmouse_color)},
3263 {"name", SYMBOL_INDEX (Qname)},
3264 {"scroll-bar-width", SYMBOL_INDEX (Qscroll_bar_width)},
3265 {"scroll-bar-height", SYMBOL_INDEX (Qscroll_bar_height)},
3266 {"title", SYMBOL_INDEX (Qtitle)},
3267 {"unsplittable", SYMBOL_INDEX (Qunsplittable)},
3268 {"vertical-scroll-bars", SYMBOL_INDEX (Qvertical_scroll_bars)},
3269 {"horizontal-scroll-bars", SYMBOL_INDEX (Qhorizontal_scroll_bars)},
3270 {"visibility", SYMBOL_INDEX (Qvisibility)},
3271 {"tool-bar-lines", SYMBOL_INDEX (Qtool_bar_lines)},
3272 {"scroll-bar-foreground", SYMBOL_INDEX (Qscroll_bar_foreground)},
3273 {"scroll-bar-background", SYMBOL_INDEX (Qscroll_bar_background)},
3274 {"screen-gamma", SYMBOL_INDEX (Qscreen_gamma)},
3275 {"line-spacing", SYMBOL_INDEX (Qline_spacing)},
3276 {"left-fringe", SYMBOL_INDEX (Qleft_fringe)},
3277 {"right-fringe", SYMBOL_INDEX (Qright_fringe)},
3278 {"wait-for-wm", SYMBOL_INDEX (Qwait_for_wm)},
3279 {"fullscreen", SYMBOL_INDEX (Qfullscreen)},
3280 {"font-backend", SYMBOL_INDEX (Qfont_backend)},
3281 {"alpha", SYMBOL_INDEX (Qalpha)},
3282 {"sticky", SYMBOL_INDEX (Qsticky)},
3283 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3284 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3285 {"undecorated", SYMBOL_INDEX (Qundecorated)},
3286 {"parent-frame", SYMBOL_INDEX (Qparent_frame)},
3287 {"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
3288 {"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
3289 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3290 {"z-group", SYMBOL_INDEX (Qz_group)},
3291 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3294 #ifdef HAVE_WINDOW_SYSTEM
3296 /* Change the parameters of frame F as specified by ALIST.
3297 If a parameter is not specially recognized, do nothing special;
3298 otherwise call the `x_set_...' function for that parameter.
3299 Except for certain geometry properties, always call store_frame_param
3300 to store the new value in the parameter alist. */
3302 void
3303 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3305 Lisp_Object tail;
3307 /* If both of these parameters are present, it's more efficient to
3308 set them both at once. So we wait until we've looked at the
3309 entire list before we set them. */
3310 int width = -1, height = -1; /* -1 denotes they were not changed. */
3312 /* Same here. */
3313 Lisp_Object left, top;
3315 /* Same with these. */
3316 Lisp_Object icon_left, icon_top;
3318 /* And with this. */
3319 Lisp_Object fullscreen;
3320 bool fullscreen_change = false;
3322 /* Record in these vectors all the parms specified. */
3323 Lisp_Object *parms;
3324 Lisp_Object *values;
3325 ptrdiff_t i, j, size;
3326 bool left_no_change = 0, top_no_change = 0;
3327 #ifdef HAVE_X_WINDOWS
3328 bool icon_left_no_change = 0, icon_top_no_change = 0;
3329 #endif
3331 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
3332 size++;
3333 CHECK_LIST_END (tail, alist);
3335 USE_SAFE_ALLOCA;
3336 SAFE_ALLOCA_LISP (parms, 2 * size);
3337 values = parms + size;
3339 /* Extract parm names and values into those vectors. */
3341 i = 0, j = size - 1;
3342 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3344 Lisp_Object elt = XCAR (tail), prop = Fcar (elt), val = Fcdr (elt);
3346 /* Some properties are independent of other properties, but other
3347 properties are dependent upon them. These special properties
3348 are foreground_color, background_color (affects cursor_color)
3349 and font (affects fringe widths); they're recorded starting
3350 from the end of PARMS and VALUES to process them first by using
3351 reverse iteration. */
3353 if (EQ (prop, Qforeground_color)
3354 || EQ (prop, Qbackground_color)
3355 || EQ (prop, Qfont))
3357 parms[j] = prop;
3358 values[j] = val;
3359 j--;
3361 else
3363 parms[i] = prop;
3364 values[i] = val;
3365 i++;
3369 /* TAIL and ALIST are not used again below here. */
3370 alist = tail = Qnil;
3372 top = left = Qunbound;
3373 icon_left = icon_top = Qunbound;
3375 /* Reverse order is used to make sure that special
3376 properties noticed above are processed first. */
3377 for (i = size - 1; i >= 0; i--)
3379 Lisp_Object prop, val;
3381 prop = parms[i];
3382 val = values[i];
3384 if (EQ (prop, Qwidth))
3386 if (RANGED_INTEGERP (0, val, INT_MAX))
3387 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3388 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3389 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3390 width = XFASTINT (XCDR (val));
3392 else if (EQ (prop, Qheight))
3394 if (RANGED_INTEGERP (0, val, INT_MAX))
3395 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3396 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3397 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3398 height = XFASTINT (XCDR (val));
3400 else if (EQ (prop, Qtop))
3401 top = val;
3402 else if (EQ (prop, Qleft))
3403 left = val;
3404 else if (EQ (prop, Qicon_top))
3405 icon_top = val;
3406 else if (EQ (prop, Qicon_left))
3407 icon_left = val;
3408 else if (EQ (prop, Qfullscreen))
3410 fullscreen = val;
3411 fullscreen_change = true;
3413 else
3415 register Lisp_Object param_index, old_value;
3417 old_value = get_frame_param (f, prop);
3419 store_frame_param (f, prop, val);
3421 param_index = Fget (prop, Qx_frame_parameter);
3422 if (NATNUMP (param_index)
3423 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3424 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3425 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3429 /* Don't die if just one of these was set. */
3430 if (EQ (left, Qunbound))
3432 left_no_change = 1;
3433 if (f->left_pos < 0)
3434 left = list2 (Qplus, make_number (f->left_pos));
3435 else
3436 XSETINT (left, f->left_pos);
3438 if (EQ (top, Qunbound))
3440 top_no_change = 1;
3441 if (f->top_pos < 0)
3442 top = list2 (Qplus, make_number (f->top_pos));
3443 else
3444 XSETINT (top, f->top_pos);
3447 /* If one of the icon positions was not set, preserve or default it. */
3448 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3450 #ifdef HAVE_X_WINDOWS
3451 icon_left_no_change = 1;
3452 #endif
3453 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3454 if (NILP (icon_left))
3455 XSETINT (icon_left, 0);
3457 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3459 #ifdef HAVE_X_WINDOWS
3460 icon_top_no_change = 1;
3461 #endif
3462 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3463 if (NILP (icon_top))
3464 XSETINT (icon_top, 0);
3467 /* Don't set these parameters unless they've been explicitly
3468 specified. The window might be mapped or resized while we're in
3469 this function, and we don't want to override that unless the lisp
3470 code has asked for it.
3472 Don't set these parameters unless they actually differ from the
3473 window's current parameters; the window may not actually exist
3474 yet. */
3476 Lisp_Object frame;
3478 XSETFRAME (frame, f);
3480 if ((width != -1 && width != FRAME_TEXT_WIDTH (f))
3481 || (height != -1 && height != FRAME_TEXT_HEIGHT (f)))
3482 /* We could consider checking f->after_make_frame here, but I
3483 don't have the faintest idea why the following is needed at
3484 all. With the old setting it can get a Heisenbug when
3485 EmacsFrameResize intermittently provokes a delayed
3486 change_frame_size in the middle of adjust_frame_size. */
3487 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
3488 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters);
3490 if ((!NILP (left) || !NILP (top))
3491 && ! (left_no_change && top_no_change)
3492 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3493 && NUMBERP (top) && XINT (top) == f->top_pos))
3495 int leftpos = 0;
3496 int toppos = 0;
3498 /* Record the signs. */
3499 f->size_hint_flags &= ~ (XNegative | YNegative);
3500 if (EQ (left, Qminus))
3501 f->size_hint_flags |= XNegative;
3502 else if (TYPE_RANGED_INTEGERP (int, left))
3504 leftpos = XINT (left);
3505 if (leftpos < 0)
3506 f->size_hint_flags |= XNegative;
3508 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3509 && CONSP (XCDR (left))
3510 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3512 leftpos = - XINT (XCAR (XCDR (left)));
3513 f->size_hint_flags |= XNegative;
3515 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3516 && CONSP (XCDR (left))
3517 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3519 leftpos = XINT (XCAR (XCDR (left)));
3522 if (EQ (top, Qminus))
3523 f->size_hint_flags |= YNegative;
3524 else if (TYPE_RANGED_INTEGERP (int, top))
3526 toppos = XINT (top);
3527 if (toppos < 0)
3528 f->size_hint_flags |= YNegative;
3530 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3531 && CONSP (XCDR (top))
3532 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3534 toppos = - XINT (XCAR (XCDR (top)));
3535 f->size_hint_flags |= YNegative;
3537 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3538 && CONSP (XCDR (top))
3539 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
3541 toppos = XINT (XCAR (XCDR (top)));
3545 /* Store the numeric value of the position. */
3546 f->top_pos = toppos;
3547 f->left_pos = leftpos;
3549 f->win_gravity = NorthWestGravity;
3551 /* Actually set that position, and convert to absolute. */
3552 x_set_offset (f, leftpos, toppos, -1);
3555 if (fullscreen_change)
3557 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
3559 frame_size_history_add
3560 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
3562 store_frame_param (f, Qfullscreen, fullscreen);
3563 if (!EQ (fullscreen, old_value))
3564 x_set_fullscreen (f, fullscreen, old_value);
3568 #ifdef HAVE_X_WINDOWS
3569 if ((!NILP (icon_left) || !NILP (icon_top))
3570 && ! (icon_left_no_change && icon_top_no_change))
3571 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3572 #endif /* HAVE_X_WINDOWS */
3575 SAFE_FREE ();
3579 /* Insert a description of internally-recorded parameters of frame X
3580 into the parameter alist *ALISTPTR that is to be given to the user.
3581 Only parameters that are specific to the X window system
3582 and whose values are not correctly recorded in the frame's
3583 param_alist need to be considered here. */
3585 void
3586 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
3588 Lisp_Object tem;
3589 uprintmax_t w;
3590 char buf[INT_BUFSIZE_BOUND (w)];
3592 /* Represent negative positions (off the top or left screen edge)
3593 in a way that Fmodify_frame_parameters will understand correctly. */
3594 XSETINT (tem, f->left_pos);
3595 if (f->left_pos >= 0)
3596 store_in_alist (alistptr, Qleft, tem);
3597 else
3598 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
3600 XSETINT (tem, f->top_pos);
3601 if (f->top_pos >= 0)
3602 store_in_alist (alistptr, Qtop, tem);
3603 else
3604 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
3606 store_in_alist (alistptr, Qborder_width,
3607 make_number (f->border_width));
3608 store_in_alist (alistptr, Qinternal_border_width,
3609 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
3610 store_in_alist (alistptr, Qright_divider_width,
3611 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
3612 store_in_alist (alistptr, Qbottom_divider_width,
3613 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
3614 store_in_alist (alistptr, Qleft_fringe,
3615 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
3616 store_in_alist (alistptr, Qright_fringe,
3617 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
3618 store_in_alist (alistptr, Qscroll_bar_width,
3619 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3620 ? make_number (0)
3621 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3622 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
3623 /* nil means "use default width"
3624 for non-toolkit scroll bar.
3625 ruler-mode.el depends on this. */
3626 : Qnil));
3627 store_in_alist (alistptr, Qscroll_bar_height,
3628 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
3629 ? make_number (0)
3630 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
3631 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
3632 /* nil means "use default height"
3633 for non-toolkit scroll bar. */
3634 : Qnil));
3635 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
3636 MS-Windows it returns a value whose type is HANDLE, which is
3637 actually a pointer. Explicit casting avoids compiler
3638 warnings. */
3639 w = (uintptr_t) FRAME_X_WINDOW (f);
3640 store_in_alist (alistptr, Qwindow_id,
3641 make_formatted_string (buf, "%"pMu, w));
3642 #ifdef HAVE_X_WINDOWS
3643 #ifdef USE_X_TOOLKIT
3644 /* Tooltip frame may not have this widget. */
3645 if (FRAME_X_OUTPUT (f)->widget)
3646 #endif
3647 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
3648 store_in_alist (alistptr, Qouter_window_id,
3649 make_formatted_string (buf, "%"pMu, w));
3650 #endif
3651 store_in_alist (alistptr, Qicon_name, f->icon_name);
3652 store_in_alist (alistptr, Qvisibility,
3653 (FRAME_VISIBLE_P (f) ? Qt
3654 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3655 store_in_alist (alistptr, Qdisplay,
3656 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
3658 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
3659 tem = Qnil;
3660 else
3661 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
3662 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
3663 store_in_alist (alistptr, Qparent_id, tem);
3664 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
3668 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3669 the previous value of that parameter, NEW_VALUE is the new value. */
3671 void
3672 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3674 if (NILP (new_value))
3675 f->want_fullscreen = FULLSCREEN_NONE;
3676 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
3677 f->want_fullscreen = FULLSCREEN_BOTH;
3678 else if (EQ (new_value, Qfullwidth))
3679 f->want_fullscreen = FULLSCREEN_WIDTH;
3680 else if (EQ (new_value, Qfullheight))
3681 f->want_fullscreen = FULLSCREEN_HEIGHT;
3682 else if (EQ (new_value, Qmaximized))
3683 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
3685 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
3686 FRAME_TERMINAL (f)->fullscreen_hook (f);
3690 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3691 the previous value of that parameter, NEW_VALUE is the new value. */
3693 void
3694 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3696 if (NILP (new_value))
3697 f->extra_line_spacing = 0;
3698 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
3699 f->extra_line_spacing = XFASTINT (new_value);
3700 else if (FLOATP (new_value))
3702 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
3704 if (new_spacing >= 0)
3705 f->extra_line_spacing = new_spacing;
3706 else
3707 signal_error ("Invalid line-spacing", new_value);
3709 else
3710 signal_error ("Invalid line-spacing", new_value);
3711 if (FRAME_VISIBLE_P (f))
3712 redraw_frame (f);
3716 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3717 the previous value of that parameter, NEW_VALUE is the new value. */
3719 void
3720 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3722 Lisp_Object bgcolor;
3724 if (NILP (new_value))
3725 f->gamma = 0;
3726 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
3727 /* The value 0.4545 is the normal viewing gamma. */
3728 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
3729 else
3730 signal_error ("Invalid screen-gamma", new_value);
3732 /* Apply the new gamma value to the frame background. */
3733 bgcolor = Fassq (Qbackground_color, f->param_alist);
3734 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3736 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
3737 if (NATNUMP (parm_index)
3738 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
3739 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3740 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3741 (f, bgcolor, Qnil);
3744 clear_face_cache (true); /* FIXME: Why of all frames? */
3745 fset_redisplay (f);
3749 void
3750 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3752 Lisp_Object font_object;
3753 int fontset = -1;
3754 #ifdef HAVE_X_WINDOWS
3755 Lisp_Object font_param = arg;
3756 #endif
3758 /* Set the frame parameter back to the old value because we may
3759 fail to use ARG as the new parameter value. */
3760 store_frame_param (f, Qfont, oldval);
3762 /* ARG is a fontset name, a font name, a cons of fontset name and a
3763 font object, or a font object. In the last case, this function
3764 never fail. */
3765 if (STRINGP (arg))
3767 fontset = fs_query_fontset (arg, 0);
3768 if (fontset < 0)
3770 font_object = font_open_by_name (f, arg);
3771 if (NILP (font_object))
3772 error ("Font `%s' is not defined", SSDATA (arg));
3773 arg = AREF (font_object, FONT_NAME_INDEX);
3775 else if (fontset > 0)
3777 font_object = font_open_by_name (f, fontset_ascii (fontset));
3778 if (NILP (font_object))
3779 error ("Font `%s' is not defined", SDATA (arg));
3780 arg = AREF (font_object, FONT_NAME_INDEX);
3782 else
3783 error ("The default fontset can't be used for a frame font");
3785 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
3787 /* This is the case that the ASCII font of F's fontset XCAR
3788 (arg) is changed to the font XCDR (arg) by
3789 `set-fontset-font'. */
3790 fontset = fs_query_fontset (XCAR (arg), 0);
3791 if (fontset < 0)
3792 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
3793 font_object = XCDR (arg);
3794 arg = AREF (font_object, FONT_NAME_INDEX);
3795 #ifdef HAVE_X_WINDOWS
3796 font_param = Ffont_get (font_object, QCname);
3797 #endif
3799 else if (FONT_OBJECT_P (arg))
3801 font_object = arg;
3802 #ifdef HAVE_X_WINDOWS
3803 font_param = Ffont_get (font_object, QCname);
3804 #endif
3805 /* This is to store the XLFD font name in the frame parameter for
3806 backward compatibility. We should store the font-object
3807 itself in the future. */
3808 arg = AREF (font_object, FONT_NAME_INDEX);
3809 fontset = FRAME_FONTSET (f);
3810 /* Check if we can use the current fontset. If not, set FONTSET
3811 to -1 to generate a new fontset from FONT-OBJECT. */
3812 if (fontset >= 0)
3814 Lisp_Object ascii_font = fontset_ascii (fontset);
3815 Lisp_Object spec = font_spec_from_name (ascii_font);
3817 /* SPEC might be nil because ASCII_FONT's name doesn't parse
3818 according to stupid XLFD rules, which, for example,
3819 disallow font names that include a dash followed by a
3820 number. So in those cases we simply request x_new_font
3821 below to generate a new fontset. */
3822 if (NILP (spec) || ! font_match_p (spec, font_object))
3823 fontset = -1;
3826 else
3827 signal_error ("Invalid font", arg);
3829 if (! NILP (Fequal (font_object, oldval)))
3830 return;
3832 x_new_font (f, font_object, fontset);
3833 store_frame_param (f, Qfont, arg);
3834 #ifdef HAVE_X_WINDOWS
3835 store_frame_param (f, Qfont_parameter, font_param);
3836 #endif
3837 /* Recalculate toolbar height. */
3838 f->n_tool_bar_rows = 0;
3840 /* Ensure we redraw it. */
3841 clear_current_matrices (f);
3843 /* Attempt to hunt down bug#16028. */
3844 SET_FRAME_GARBAGED (f);
3846 /* This is important if we are called by some Lisp as part of
3847 redisplaying the frame, see redisplay_internal. */
3848 f->fonts_changed = true;
3850 recompute_basic_faces (f);
3852 do_pending_window_change (0);
3854 /* We used to call face-set-after-frame-default here, but it leads to
3855 recursive calls (since that function can set the `default' face's
3856 font which in turns changes the frame's `font' parameter).
3857 Also I don't know what this call is meant to do, but it seems the
3858 wrong way to do it anyway (it does a lot more work than what seems
3859 reasonable in response to a change to `font'). */
3863 void
3864 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3866 if (! NILP (new_value)
3867 && !CONSP (new_value))
3869 char *p0, *p1;
3871 CHECK_STRING (new_value);
3872 p0 = p1 = SSDATA (new_value);
3873 new_value = Qnil;
3874 while (*p0)
3876 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
3877 if (p0 < p1)
3878 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
3879 new_value);
3880 if (*p1)
3882 int c;
3884 while ((c = *++p1) && c_isspace (c));
3886 p0 = p1;
3888 new_value = Fnreverse (new_value);
3891 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
3892 return;
3894 if (FRAME_FONT (f))
3895 free_all_realized_faces (Qnil);
3897 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
3898 if (NILP (new_value))
3900 if (NILP (old_value))
3901 error ("No font backend available");
3902 font_update_drivers (f, old_value);
3903 error ("None of specified font backends are available");
3905 store_frame_param (f, Qfont_backend, new_value);
3907 if (FRAME_FONT (f))
3909 Lisp_Object frame;
3911 XSETFRAME (frame, f);
3912 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
3913 face_change = true;
3914 windows_or_buffers_changed = 18;
3918 void
3919 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3921 int unit = FRAME_COLUMN_WIDTH (f);
3922 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
3923 int new_width;
3925 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3926 ? eabs (XINT (new_value)) : 8);
3928 if (new_width != old_width)
3930 f->left_fringe_width = new_width;
3931 f->fringe_cols /* Round up. */
3932 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
3934 if (FRAME_X_WINDOW (f) != 0)
3935 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
3937 SET_FRAME_GARBAGED (f);
3942 void
3943 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3945 int unit = FRAME_COLUMN_WIDTH (f);
3946 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
3947 int new_width;
3949 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3950 ? eabs (XINT (new_value)) : 8);
3952 if (new_width != old_width)
3954 f->right_fringe_width = new_width;
3955 f->fringe_cols /* Round up. */
3956 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
3958 if (FRAME_X_WINDOW (f) != 0)
3959 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
3961 SET_FRAME_GARBAGED (f);
3966 void
3967 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3969 CHECK_TYPE_RANGED_INTEGER (int, arg);
3971 if (XINT (arg) == f->border_width)
3972 return;
3974 if (FRAME_X_WINDOW (f) != 0)
3975 error ("Cannot change the border width of a frame");
3977 f->border_width = XINT (arg);
3980 void
3981 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3983 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
3984 CHECK_TYPE_RANGED_INTEGER (int, arg);
3985 int new = max (0, XINT (arg));
3986 if (new != old)
3988 f->right_divider_width = new;
3989 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
3990 adjust_frame_glyphs (f);
3991 SET_FRAME_GARBAGED (f);
3996 void
3997 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3999 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
4000 CHECK_TYPE_RANGED_INTEGER (int, arg);
4001 int new = max (0, XINT (arg));
4002 if (new != old)
4004 f->bottom_divider_width = new;
4005 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
4006 adjust_frame_glyphs (f);
4007 SET_FRAME_GARBAGED (f);
4011 void
4012 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
4014 Lisp_Object frame;
4015 XSETFRAME (frame, f);
4017 if (NILP (value))
4018 Fmake_frame_invisible (frame, Qt);
4019 else if (EQ (value, Qicon))
4020 Ficonify_frame (frame);
4021 else
4022 Fmake_frame_visible (frame);
4025 void
4026 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4028 f->auto_raise = !EQ (Qnil, arg);
4031 void
4032 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4034 f->auto_lower = !EQ (Qnil, arg);
4037 void
4038 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4040 f->no_split = !NILP (arg);
4043 void
4044 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4046 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4047 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
4048 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4049 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
4051 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
4052 = (NILP (arg)
4053 ? vertical_scroll_bar_none
4054 : EQ (Qleft, arg)
4055 ? vertical_scroll_bar_left
4056 : EQ (Qright, arg)
4057 ? vertical_scroll_bar_right
4058 : EQ (Qleft, Vdefault_frame_scroll_bars)
4059 ? vertical_scroll_bar_left
4060 : EQ (Qright, Vdefault_frame_scroll_bars)
4061 ? vertical_scroll_bar_right
4062 : vertical_scroll_bar_none);
4064 /* We set this parameter before creating the X window for the
4065 frame, so we can get the geometry right from the start.
4066 However, if the window hasn't been created yet, we shouldn't
4067 call x_set_window_size. */
4068 if (FRAME_X_WINDOW (f))
4069 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
4071 SET_FRAME_GARBAGED (f);
4075 void
4076 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4078 #if USE_HORIZONTAL_SCROLL_BARS
4079 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
4080 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
4082 f->horizontal_scroll_bars = NILP (arg) ? false : true;
4084 /* We set this parameter before creating the X window for the
4085 frame, so we can get the geometry right from the start.
4086 However, if the window hasn't been created yet, we shouldn't
4087 call x_set_window_size. */
4088 if (FRAME_X_WINDOW (f))
4089 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
4091 SET_FRAME_GARBAGED (f);
4093 #endif
4096 void
4097 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4099 int unit = FRAME_COLUMN_WIDTH (f);
4101 if (NILP (arg))
4103 x_set_scroll_bar_default_width (f);
4105 if (FRAME_X_WINDOW (f))
4106 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4108 SET_FRAME_GARBAGED (f);
4110 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4111 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4113 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
4114 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
4115 if (FRAME_X_WINDOW (f))
4116 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4118 SET_FRAME_GARBAGED (f);
4121 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
4122 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
4125 void
4126 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4128 #if USE_HORIZONTAL_SCROLL_BARS
4129 int unit = FRAME_LINE_HEIGHT (f);
4131 if (NILP (arg))
4133 x_set_scroll_bar_default_height (f);
4135 if (FRAME_X_WINDOW (f))
4136 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4138 SET_FRAME_GARBAGED (f);
4140 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4141 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4143 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
4144 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
4145 if (FRAME_X_WINDOW (f))
4146 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4148 SET_FRAME_GARBAGED (f);
4151 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
4152 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
4153 #endif
4156 void
4157 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4159 double alpha = 1.0;
4160 double newval[2];
4161 int i;
4162 Lisp_Object item;
4164 for (i = 0; i < 2; i++)
4166 newval[i] = 1.0;
4167 if (CONSP (arg))
4169 item = CAR (arg);
4170 arg = CDR (arg);
4172 else
4173 item = arg;
4175 if (NILP (item))
4176 alpha = - 1.0;
4177 else if (FLOATP (item))
4179 alpha = XFLOAT_DATA (item);
4180 if (! (0 <= alpha && alpha <= 1.0))
4181 args_out_of_range (make_float (0.0), make_float (1.0));
4183 else if (INTEGERP (item))
4185 EMACS_INT ialpha = XINT (item);
4186 if (! (0 <= ialpha && ialpha <= 100))
4187 args_out_of_range (make_number (0), make_number (100));
4188 alpha = ialpha / 100.0;
4190 else
4191 wrong_type_argument (Qnumberp, item);
4192 newval[i] = alpha;
4195 for (i = 0; i < 2; i++)
4196 f->alpha[i] = newval[i];
4198 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
4199 block_input ();
4200 x_set_frame_alpha (f);
4201 unblock_input ();
4202 #endif
4204 return;
4207 #ifndef HAVE_NS
4209 /* Non-zero if mouse is grabbed on DPYINFO
4210 and we know the frame where it is. */
4212 bool x_mouse_grabbed (Display_Info *dpyinfo)
4214 return (dpyinfo->grabbed
4215 && dpyinfo->last_mouse_frame
4216 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
4219 /* Re-highlight something with mouse-face properties
4220 on DPYINFO using saved frame and mouse position. */
4222 void
4223 x_redo_mouse_highlight (Display_Info *dpyinfo)
4225 if (dpyinfo->last_mouse_motion_frame
4226 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
4227 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
4228 dpyinfo->last_mouse_motion_x,
4229 dpyinfo->last_mouse_motion_y);
4232 #endif /* HAVE_NS */
4234 /* Subroutines of creating an X frame. */
4236 /* Make sure that Vx_resource_name is set to a reasonable value.
4237 Fix it up, or set it to `emacs' if it is too hopeless. */
4239 void
4240 validate_x_resource_name (void)
4242 ptrdiff_t len = 0;
4243 /* Number of valid characters in the resource name. */
4244 ptrdiff_t good_count = 0;
4245 /* Number of invalid characters in the resource name. */
4246 ptrdiff_t bad_count = 0;
4247 Lisp_Object new;
4248 ptrdiff_t i;
4250 if (!STRINGP (Vx_resource_class))
4251 Vx_resource_class = build_string (EMACS_CLASS);
4253 if (STRINGP (Vx_resource_name))
4255 unsigned char *p = SDATA (Vx_resource_name);
4257 len = SBYTES (Vx_resource_name);
4259 /* Only letters, digits, - and _ are valid in resource names.
4260 Count the valid characters and count the invalid ones. */
4261 for (i = 0; i < len; i++)
4263 int c = p[i];
4264 if (! ((c >= 'a' && c <= 'z')
4265 || (c >= 'A' && c <= 'Z')
4266 || (c >= '0' && c <= '9')
4267 || c == '-' || c == '_'))
4268 bad_count++;
4269 else
4270 good_count++;
4273 else
4274 /* Not a string => completely invalid. */
4275 bad_count = 5, good_count = 0;
4277 /* If name is valid already, return. */
4278 if (bad_count == 0)
4279 return;
4281 /* If name is entirely invalid, or nearly so, or is so implausibly
4282 large that alloca might not work, use `emacs'. */
4283 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
4285 Vx_resource_name = build_string ("emacs");
4286 return;
4289 /* Name is partly valid. Copy it and replace the invalid characters
4290 with underscores. */
4292 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
4294 for (i = 0; i < len; i++)
4296 int c = SREF (new, i);
4297 if (! ((c >= 'a' && c <= 'z')
4298 || (c >= 'A' && c <= 'Z')
4299 || (c >= '0' && c <= '9')
4300 || c == '-' || c == '_'))
4301 SSET (new, i, '_');
4305 /* Get specified attribute from resource database RDB.
4306 See Fx_get_resource below for other parameters. */
4308 static Lisp_Object
4309 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
4311 CHECK_STRING (attribute);
4312 CHECK_STRING (class);
4314 if (!NILP (component))
4315 CHECK_STRING (component);
4316 if (!NILP (subclass))
4317 CHECK_STRING (subclass);
4318 if (NILP (component) != NILP (subclass))
4319 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
4321 validate_x_resource_name ();
4323 /* Allocate space for the components, the dots which separate them,
4324 and the final '\0'. Make them big enough for the worst case. */
4325 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4326 + (STRINGP (component)
4327 ? SBYTES (component) : 0)
4328 + SBYTES (attribute)
4329 + 3);
4331 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4332 + SBYTES (class)
4333 + (STRINGP (subclass)
4334 ? SBYTES (subclass) : 0)
4335 + 3);
4336 USE_SAFE_ALLOCA;
4337 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4338 char *class_key = name_key + name_keysize;
4340 /* Start with emacs.FRAMENAME for the name (the specific one)
4341 and with `Emacs' for the class key (the general one). */
4342 char *nz = lispstpcpy (name_key, Vx_resource_name);
4343 char *cz = lispstpcpy (class_key, Vx_resource_class);
4345 *cz++ = '.';
4346 cz = lispstpcpy (cz, class);
4348 if (!NILP (component))
4350 *cz++ = '.';
4351 lispstpcpy (cz, subclass);
4353 *nz++ = '.';
4354 nz = lispstpcpy (nz, component);
4357 *nz++ = '.';
4358 lispstpcpy (nz, attribute);
4360 char *value = x_get_string_resource (rdb, name_key, class_key);
4361 SAFE_FREE();
4363 if (value && *value)
4364 return build_string (value);
4365 else
4366 return Qnil;
4370 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4371 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4372 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4373 class, where INSTANCE is the name under which Emacs was invoked, or
4374 the name specified by the `-name' or `-rn' command-line arguments.
4376 The optional arguments COMPONENT and SUBCLASS add to the key and the
4377 class, respectively. You must specify both of them or neither.
4378 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4379 and the class is `Emacs.CLASS.SUBCLASS'. */)
4380 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4381 Lisp_Object subclass)
4383 check_window_system (NULL);
4385 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4386 attribute, class, component, subclass);
4389 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4391 Lisp_Object
4392 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4393 Lisp_Object class, Lisp_Object component,
4394 Lisp_Object subclass)
4396 return xrdb_get_resource (dpyinfo->xrdb,
4397 attribute, class, component, subclass);
4400 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
4401 /* Used when C code wants a resource value. */
4402 /* Called from oldXMenu/Create.c. */
4403 char *
4404 x_get_resource_string (const char *attribute, const char *class)
4406 char *result;
4407 struct frame *sf = SELECTED_FRAME ();
4408 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4409 USE_SAFE_ALLOCA;
4411 /* Allocate space for the components, the dots which separate them,
4412 and the final '\0'. */
4413 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4414 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4415 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4416 char *class_key = name_key + name_keysize;
4418 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4419 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4421 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4422 name_key, class_key);
4423 SAFE_FREE ();
4424 return result;
4426 #endif
4428 /* Return the value of parameter PARAM.
4430 First search ALIST, then Vdefault_frame_alist, then the X defaults
4431 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4433 Convert the resource to the type specified by desired_type.
4435 If no default is specified, return Qunbound. If you call
4436 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4437 and don't let it get stored in any Lisp-visible variables! */
4439 Lisp_Object
4440 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4441 const char *attribute, const char *class, enum resource_types type)
4443 Lisp_Object tem;
4445 tem = Fassq (param, alist);
4447 if (!NILP (tem))
4449 /* If we find this parm in ALIST, clear it out
4450 so that it won't be "left over" at the end. */
4451 Lisp_Object tail;
4452 XSETCAR (tem, Qnil);
4453 /* In case the parameter appears more than once in the alist,
4454 clear it out. */
4455 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4456 if (CONSP (XCAR (tail))
4457 && EQ (XCAR (XCAR (tail)), param))
4458 XSETCAR (XCAR (tail), Qnil);
4460 else
4461 tem = Fassq (param, Vdefault_frame_alist);
4463 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4464 look in the X resources. */
4465 if (EQ (tem, Qnil))
4467 if (attribute && dpyinfo)
4469 AUTO_STRING (at, attribute);
4470 AUTO_STRING (cl, class);
4471 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4473 if (NILP (tem))
4474 return Qunbound;
4476 switch (type)
4478 case RES_TYPE_NUMBER:
4479 return make_number (atoi (SSDATA (tem)));
4481 case RES_TYPE_BOOLEAN_NUMBER:
4482 if (!strcmp (SSDATA (tem), "on")
4483 || !strcmp (SSDATA (tem), "true"))
4484 return make_number (1);
4485 return make_number (atoi (SSDATA (tem)));
4486 break;
4488 case RES_TYPE_FLOAT:
4489 return make_float (atof (SSDATA (tem)));
4491 case RES_TYPE_BOOLEAN:
4492 tem = Fdowncase (tem);
4493 if (!strcmp (SSDATA (tem), "on")
4494 #ifdef HAVE_NS
4495 || !strcmp (SSDATA (tem), "yes")
4496 #endif
4497 || !strcmp (SSDATA (tem), "true"))
4498 return Qt;
4499 else
4500 return Qnil;
4502 case RES_TYPE_STRING:
4503 return tem;
4505 case RES_TYPE_SYMBOL:
4506 /* As a special case, we map the values `true' and `on'
4507 to Qt, and `false' and `off' to Qnil. */
4509 Lisp_Object lower;
4510 lower = Fdowncase (tem);
4511 if (!strcmp (SSDATA (lower), "on")
4512 #ifdef HAVE_NS
4513 || !strcmp (SSDATA (lower), "yes")
4514 #endif
4515 || !strcmp (SSDATA (lower), "true"))
4516 return Qt;
4517 else if (!strcmp (SSDATA (lower), "off")
4518 #ifdef HAVE_NS
4519 || !strcmp (SSDATA (lower), "no")
4520 #endif
4521 || !strcmp (SSDATA (lower), "false"))
4522 return Qnil;
4523 else
4524 return Fintern (tem, Qnil);
4527 default:
4528 emacs_abort ();
4531 else
4532 return Qunbound;
4534 return Fcdr (tem);
4537 static Lisp_Object
4538 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
4539 const char *attribute, const char *class,
4540 enum resource_types type)
4542 return x_get_arg (FRAME_DISPLAY_INFO (f),
4543 alist, param, attribute, class, type);
4546 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
4548 Lisp_Object
4549 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
4550 Lisp_Object param,
4551 const char *attribute, const char *class,
4552 enum resource_types type)
4554 Lisp_Object value;
4556 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
4557 attribute, class, type);
4558 if (! NILP (value) && ! EQ (value, Qunbound))
4559 store_frame_param (f, param, value);
4561 return value;
4565 /* Record in frame F the specified or default value according to ALIST
4566 of the parameter named PROP (a Lisp symbol).
4567 If no value is specified for PROP, look for an X default for XPROP
4568 on the frame named NAME.
4569 If that is not found either, use the value DEFLT. */
4571 Lisp_Object
4572 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
4573 Lisp_Object deflt, const char *xprop, const char *xclass,
4574 enum resource_types type)
4576 Lisp_Object tem;
4578 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
4579 if (EQ (tem, Qunbound))
4580 tem = deflt;
4581 AUTO_FRAME_ARG (arg, prop, tem);
4582 x_set_frame_parameters (f, arg);
4583 return tem;
4587 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
4590 * XParseGeometry parses strings of the form
4591 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
4592 * width, height, xoffset, and yoffset are unsigned integers.
4593 * Example: "=80x24+300-49"
4594 * The equal sign is optional.
4595 * It returns a bitmask that indicates which of the four values
4596 * were actually found in the string. For each value found,
4597 * the corresponding argument is updated; for each value
4598 * not found, the corresponding argument is left unchanged.
4601 static int
4602 XParseGeometry (char *string,
4603 int *x, int *y,
4604 unsigned int *width, unsigned int *height)
4606 int mask = NoValue;
4607 char *strind;
4608 unsigned long tempWidth UNINIT, tempHeight UNINIT;
4609 long int tempX UNINIT, tempY UNINIT;
4610 char *nextCharacter;
4612 if (string == NULL || *string == '\0')
4613 return mask;
4614 if (*string == '=')
4615 string++; /* ignore possible '=' at beg of geometry spec */
4617 strind = string;
4618 if (*strind != '+' && *strind != '-' && *strind != 'x')
4620 tempWidth = strtoul (strind, &nextCharacter, 10);
4621 if (strind == nextCharacter)
4622 return 0;
4623 strind = nextCharacter;
4624 mask |= WidthValue;
4627 if (*strind == 'x' || *strind == 'X')
4629 strind++;
4630 tempHeight = strtoul (strind, &nextCharacter, 10);
4631 if (strind == nextCharacter)
4632 return 0;
4633 strind = nextCharacter;
4634 mask |= HeightValue;
4637 if (*strind == '+' || *strind == '-')
4639 if (*strind == '-')
4640 mask |= XNegative;
4641 tempX = strtol (strind, &nextCharacter, 10);
4642 if (strind == nextCharacter)
4643 return 0;
4644 strind = nextCharacter;
4645 mask |= XValue;
4646 if (*strind == '+' || *strind == '-')
4648 if (*strind == '-')
4649 mask |= YNegative;
4650 tempY = strtol (strind, &nextCharacter, 10);
4651 if (strind == nextCharacter)
4652 return 0;
4653 strind = nextCharacter;
4654 mask |= YValue;
4658 /* If strind isn't at the end of the string then it's an invalid
4659 geometry specification. */
4661 if (*strind != '\0')
4662 return 0;
4664 if (mask & XValue)
4665 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
4666 if (mask & YValue)
4667 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
4668 if (mask & WidthValue)
4669 *width = min (tempWidth, UINT_MAX);
4670 if (mask & HeightValue)
4671 *height = min (tempHeight, UINT_MAX);
4672 return mask;
4675 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
4678 /* NS used to define x-parse-geometry in ns-win.el, but that confused
4679 make-docfile: the documentation string in ns-win.el was used for
4680 x-parse-geometry even in non-NS builds.
4682 With two definitions of x-parse-geometry in this file, various
4683 things still get confused (eg M-x apropos documentation), so that
4684 it is best if the two definitions just share the same doc-string.
4686 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
4687 doc: /* Parse a display geometry string STRING.
4688 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
4689 The properties returned may include `top', `left', `height', and `width'.
4690 For X, the value of `left' or `top' may be an integer,
4691 or a list (+ N) meaning N pixels relative to top/left corner,
4692 or a list (- N) meaning -N pixels relative to bottom/right corner.
4693 On Nextstep, this just calls `ns-parse-geometry'. */)
4694 (Lisp_Object string)
4696 int geometry, x, y;
4697 unsigned int width, height;
4698 Lisp_Object result;
4700 CHECK_STRING (string);
4702 #ifdef HAVE_NS
4703 if (strchr (SSDATA (string), ' ') != NULL)
4704 return call1 (Qns_parse_geometry, string);
4705 #endif
4706 geometry = XParseGeometry (SSDATA (string),
4707 &x, &y, &width, &height);
4708 result = Qnil;
4709 if (geometry & XValue)
4711 Lisp_Object element;
4713 if (x >= 0 && (geometry & XNegative))
4714 element = list3 (Qleft, Qminus, make_number (-x));
4715 else if (x < 0 && ! (geometry & XNegative))
4716 element = list3 (Qleft, Qplus, make_number (x));
4717 else
4718 element = Fcons (Qleft, make_number (x));
4719 result = Fcons (element, result);
4722 if (geometry & YValue)
4724 Lisp_Object element;
4726 if (y >= 0 && (geometry & YNegative))
4727 element = list3 (Qtop, Qminus, make_number (-y));
4728 else if (y < 0 && ! (geometry & YNegative))
4729 element = list3 (Qtop, Qplus, make_number (y));
4730 else
4731 element = Fcons (Qtop, make_number (y));
4732 result = Fcons (element, result);
4735 if (geometry & WidthValue)
4736 result = Fcons (Fcons (Qwidth, make_number (width)), result);
4737 if (geometry & HeightValue)
4738 result = Fcons (Fcons (Qheight, make_number (height)), result);
4740 return result;
4744 /* Calculate the desired size and position of frame F.
4745 Return the flags saying which aspects were specified.
4747 Also set the win_gravity and size_hint_flags of F.
4749 Adjust height for toolbar if TOOLBAR_P is 1.
4751 This function does not make the coordinates positive. */
4753 #define DEFAULT_ROWS 36
4754 #define DEFAULT_COLS 80
4756 long
4757 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x_width, int *x_height)
4759 Lisp_Object height, width, user_size, top, left, user_position;
4760 long window_prompting = 0;
4761 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
4763 /* Default values if we fall through.
4764 Actually, if that happens we should get
4765 window manager prompting. */
4766 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
4767 SET_FRAME_COLS (f, DEFAULT_COLS);
4768 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
4769 SET_FRAME_LINES (f, DEFAULT_ROWS);
4771 /* Window managers expect that if program-specified
4772 positions are not (0,0), they're intentional, not defaults. */
4773 f->top_pos = 0;
4774 f->left_pos = 0;
4776 /* Calculate a tool bar height so that the user gets a text display
4777 area of the size he specified with -g or via .Xdefaults. Later
4778 changes of the tool bar height don't change the frame size. This
4779 is done so that users can create tall Emacs frames without having
4780 to guess how tall the tool bar will get. */
4781 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4783 if (frame_default_tool_bar_height)
4784 FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
4785 else
4787 int margin, relief;
4789 relief = (tool_bar_button_relief >= 0
4790 ? tool_bar_button_relief
4791 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4793 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
4794 margin = XFASTINT (Vtool_bar_button_margin);
4795 else if (CONSP (Vtool_bar_button_margin)
4796 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
4797 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4798 else
4799 margin = 0;
4801 FRAME_TOOL_BAR_HEIGHT (f)
4802 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4806 /* Ensure that earlier new_width and new_height settings won't
4807 override what we specify below. */
4808 f->new_width = f->new_height = 0;
4810 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4811 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4812 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
4814 if (!EQ (width, Qunbound))
4816 if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
4818 CHECK_NUMBER (XCDR (width));
4819 if ((XINT (XCDR (width)) < 0 || XINT (XCDR (width)) > INT_MAX))
4820 xsignal1 (Qargs_out_of_range, XCDR (width));
4822 SET_FRAME_WIDTH (f, XINT (XCDR (width)));
4823 f->inhibit_horizontal_resize = true;
4824 *x_width = XINT (XCDR (width));
4826 else
4828 CHECK_NUMBER (width);
4829 if ((XINT (width) < 0 || XINT (width) > INT_MAX))
4830 xsignal1 (Qargs_out_of_range, width);
4832 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
4836 if (!EQ (height, Qunbound))
4838 if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
4840 CHECK_NUMBER (XCDR (height));
4841 if ((XINT (XCDR (height)) < 0 || XINT (XCDR (height)) > INT_MAX))
4842 xsignal1 (Qargs_out_of_range, XCDR (height));
4844 SET_FRAME_HEIGHT (f, XINT (XCDR (height)));
4845 f->inhibit_vertical_resize = true;
4846 *x_height = XINT (XCDR (height));
4848 else
4850 CHECK_NUMBER (height);
4851 if ((XINT (height) < 0) || (XINT (height) > INT_MAX))
4852 xsignal1 (Qargs_out_of_range, height);
4854 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
4858 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4859 if (!NILP (user_size) && !EQ (user_size, Qunbound))
4860 window_prompting |= USSize;
4861 else
4862 window_prompting |= PSize;
4865 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4866 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4867 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4868 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
4870 if (EQ (top, Qminus))
4872 f->top_pos = 0;
4873 window_prompting |= YNegative;
4875 else if (CONSP (top) && EQ (XCAR (top), Qminus)
4876 && CONSP (XCDR (top))
4877 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
4879 f->top_pos = - XINT (XCAR (XCDR (top)));
4880 window_prompting |= YNegative;
4882 else if (CONSP (top) && EQ (XCAR (top), Qplus)
4883 && CONSP (XCDR (top))
4884 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
4886 f->top_pos = XINT (XCAR (XCDR (top)));
4888 else if (EQ (top, Qunbound))
4889 f->top_pos = 0;
4890 else
4892 CHECK_TYPE_RANGED_INTEGER (int, top);
4893 f->top_pos = XINT (top);
4894 if (f->top_pos < 0)
4895 window_prompting |= YNegative;
4898 if (EQ (left, Qminus))
4900 f->left_pos = 0;
4901 window_prompting |= XNegative;
4903 else if (CONSP (left) && EQ (XCAR (left), Qminus)
4904 && CONSP (XCDR (left))
4905 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
4907 f->left_pos = - XINT (XCAR (XCDR (left)));
4908 window_prompting |= XNegative;
4910 else if (CONSP (left) && EQ (XCAR (left), Qplus)
4911 && CONSP (XCDR (left))
4912 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
4914 f->left_pos = XINT (XCAR (XCDR (left)));
4916 else if (EQ (left, Qunbound))
4917 f->left_pos = 0;
4918 else
4920 CHECK_TYPE_RANGED_INTEGER (int, left);
4921 f->left_pos = XINT (left);
4922 if (f->left_pos < 0)
4923 window_prompting |= XNegative;
4926 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
4927 window_prompting |= USPosition;
4928 else
4929 window_prompting |= PPosition;
4932 if (window_prompting & XNegative)
4934 if (window_prompting & YNegative)
4935 f->win_gravity = SouthEastGravity;
4936 else
4937 f->win_gravity = NorthEastGravity;
4939 else
4941 if (window_prompting & YNegative)
4942 f->win_gravity = SouthWestGravity;
4943 else
4944 f->win_gravity = NorthWestGravity;
4947 f->size_hint_flags = window_prompting;
4949 return window_prompting;
4954 #endif /* HAVE_WINDOW_SYSTEM */
4956 void
4957 frame_make_pointer_invisible (struct frame *f)
4959 if (! NILP (Vmake_pointer_invisible))
4961 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
4962 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4964 f->mouse_moved = 0;
4965 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
4966 f->pointer_invisible = 1;
4971 void
4972 frame_make_pointer_visible (struct frame *f)
4974 /* We don't check Vmake_pointer_invisible here in case the
4975 pointer was invisible when Vmake_pointer_invisible was set to nil. */
4976 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
4977 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4979 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
4980 f->pointer_invisible = 0;
4984 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
4985 Sframe_pointer_visible_p, 0, 1, 0,
4986 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
4987 Otherwise it returns nil. FRAME omitted or nil means the
4988 selected frame. This is useful when `make-pointer-invisible' is set. */)
4989 (Lisp_Object frame)
4991 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
4996 /***********************************************************************
4997 Multimonitor data
4998 ***********************************************************************/
5000 #ifdef HAVE_WINDOW_SYSTEM
5002 # if (defined HAVE_NS \
5003 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
5004 void
5005 free_monitors (struct MonitorInfo *monitors, int n_monitors)
5007 int i;
5008 for (i = 0; i < n_monitors; ++i)
5009 xfree (monitors[i].name);
5010 xfree (monitors);
5012 # endif
5014 Lisp_Object
5015 make_monitor_attribute_list (struct MonitorInfo *monitors,
5016 int n_monitors,
5017 int primary_monitor,
5018 Lisp_Object monitor_frames,
5019 const char *source)
5021 Lisp_Object attributes_list = Qnil;
5022 Lisp_Object primary_monitor_attributes = Qnil;
5023 int i;
5025 for (i = 0; i < n_monitors; ++i)
5027 Lisp_Object geometry, workarea, attributes = Qnil;
5028 struct MonitorInfo *mi = &monitors[i];
5030 if (mi->geom.width == 0) continue;
5032 workarea = list4i (mi->work.x, mi->work.y,
5033 mi->work.width, mi->work.height);
5034 geometry = list4i (mi->geom.x, mi->geom.y,
5035 mi->geom.width, mi->geom.height);
5036 attributes = Fcons (Fcons (Qsource, build_string (source)),
5037 attributes);
5038 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
5039 attributes);
5040 attributes = Fcons (Fcons (Qmm_size,
5041 list2i (mi->mm_width, mi->mm_height)),
5042 attributes);
5043 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5044 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5045 if (mi->name)
5046 attributes = Fcons (Fcons (Qname, make_string (mi->name,
5047 strlen (mi->name))),
5048 attributes);
5050 if (i == primary_monitor)
5051 primary_monitor_attributes = attributes;
5052 else
5053 attributes_list = Fcons (attributes, attributes_list);
5056 if (!NILP (primary_monitor_attributes))
5057 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
5058 return attributes_list;
5061 #endif /* HAVE_WINDOW_SYSTEM */
5064 /***********************************************************************
5065 Initialization
5066 ***********************************************************************/
5068 void
5069 syms_of_frame (void)
5071 DEFSYM (Qframep, "framep");
5072 DEFSYM (Qframe_live_p, "frame-live-p");
5073 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
5074 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
5075 DEFSYM (Qexplicit_name, "explicit-name");
5076 DEFSYM (Qheight, "height");
5077 DEFSYM (Qicon, "icon");
5078 DEFSYM (Qminibuffer, "minibuffer");
5079 DEFSYM (Qundecorated, "undecorated");
5080 DEFSYM (Qparent_frame, "parent-frame");
5081 DEFSYM (Qskip_taskbar, "skip-taskbar");
5082 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
5083 DEFSYM (Qno_accept_focus, "no-accept-focus");
5084 DEFSYM (Qz_group, "z-group");
5085 DEFSYM (Qoverride_redirect, "override-redirect");
5086 DEFSYM (Qdelete_before, "delete-before");
5087 DEFSYM (Qmodeline, "modeline");
5088 DEFSYM (Qonly, "only");
5089 DEFSYM (Qnone, "none");
5090 DEFSYM (Qwidth, "width");
5091 DEFSYM (Qtext_pixels, "text-pixels");
5092 DEFSYM (Qgeometry, "geometry");
5093 DEFSYM (Qicon_left, "icon-left");
5094 DEFSYM (Qicon_top, "icon-top");
5095 DEFSYM (Qtooltip, "tooltip");
5096 DEFSYM (Quser_position, "user-position");
5097 DEFSYM (Quser_size, "user-size");
5098 DEFSYM (Qwindow_id, "window-id");
5099 #ifdef HAVE_X_WINDOWS
5100 DEFSYM (Qouter_window_id, "outer-window-id");
5101 #endif
5102 DEFSYM (Qparent_id, "parent-id");
5103 DEFSYM (Qx, "x");
5104 DEFSYM (Qw32, "w32");
5105 DEFSYM (Qpc, "pc");
5106 DEFSYM (Qns, "ns");
5107 DEFSYM (Qvisible, "visible");
5108 DEFSYM (Qbuffer_predicate, "buffer-predicate");
5109 DEFSYM (Qbuffer_list, "buffer-list");
5110 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
5111 DEFSYM (Qdisplay_type, "display-type");
5112 DEFSYM (Qbackground_mode, "background-mode");
5113 DEFSYM (Qnoelisp, "noelisp");
5114 DEFSYM (Qtty_color_mode, "tty-color-mode");
5115 DEFSYM (Qtty, "tty");
5116 DEFSYM (Qtty_type, "tty-type");
5118 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
5120 DEFSYM (Qfullwidth, "fullwidth");
5121 DEFSYM (Qfullheight, "fullheight");
5122 DEFSYM (Qfullboth, "fullboth");
5123 DEFSYM (Qmaximized, "maximized");
5124 DEFSYM (Qx_resource_name, "x-resource-name");
5125 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
5127 DEFSYM (Qworkarea, "workarea");
5128 DEFSYM (Qmm_size, "mm-size");
5129 DEFSYM (Qframes, "frames");
5130 DEFSYM (Qsource, "source");
5132 DEFSYM (Qouter_edges, "outer-edges");
5133 DEFSYM (Qouter_position, "outer-position");
5134 DEFSYM (Qouter_size, "outer-size");
5135 DEFSYM (Qnative_edges, "native-edges");
5136 DEFSYM (Qinner_edges, "inner-edges");
5137 DEFSYM (Qexternal_border_size, "external-border-size");
5138 DEFSYM (Qtitle_bar_size, "title-bar-size");
5139 DEFSYM (Qmenu_bar_external, "menu-bar-external");
5140 DEFSYM (Qmenu_bar_size, "menu-bar-size");
5141 DEFSYM (Qtool_bar_external, "tool-bar-external");
5142 DEFSYM (Qtool_bar_size, "tool-bar-size");
5143 /* The following are used for frame_size_history. */
5144 DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
5145 DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
5146 DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
5147 DEFSYM (Qx_set_frame_parameters, "x-set-frame-parameters");
5148 DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
5149 DEFSYM (Qset_frame_size, "set-frame-size");
5150 DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
5151 DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
5152 DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
5153 DEFSYM (Qxg_frame_resized, "xg-frame-resized");
5154 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
5155 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
5156 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
5157 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
5158 DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
5159 DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
5160 DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
5161 DEFSYM (Qx_net_wm_state, "x-net-wm-state");
5162 DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
5163 DEFSYM (Qtb_size_cb, "tb-size-cb");
5164 DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
5165 DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
5166 DEFSYM (Qx_set_menu_bar_lines, "x-set-menu-bar-lines");
5167 DEFSYM (Qchange_frame_size, "change-frame-size");
5168 DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
5169 DEFSYM (Qset_window_configuration, "set-window-configuration");
5170 DEFSYM (Qx_create_frame_1, "x-create-frame-1");
5171 DEFSYM (Qx_create_frame_2, "x-create-frame-2");
5172 DEFSYM (Qterminal_frame, "terminal-frame");
5174 #ifdef HAVE_NS
5175 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
5176 #endif
5178 DEFSYM (Qalpha, "alpha");
5179 DEFSYM (Qauto_lower, "auto-lower");
5180 DEFSYM (Qauto_raise, "auto-raise");
5181 DEFSYM (Qborder_color, "border-color");
5182 DEFSYM (Qborder_width, "border-width");
5183 DEFSYM (Qouter_border_width, "outer-border-width");
5184 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
5185 DEFSYM (Qcursor_color, "cursor-color");
5186 DEFSYM (Qcursor_type, "cursor-type");
5187 DEFSYM (Qfont_backend, "font-backend");
5188 DEFSYM (Qfullscreen, "fullscreen");
5189 DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
5190 DEFSYM (Qicon_name, "icon-name");
5191 DEFSYM (Qicon_type, "icon-type");
5192 DEFSYM (Qinternal_border_width, "internal-border-width");
5193 DEFSYM (Qleft_fringe, "left-fringe");
5194 DEFSYM (Qline_spacing, "line-spacing");
5195 DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
5196 DEFSYM (Qupdate_frame_menubar, "update-frame-menubar");
5197 DEFSYM (Qfree_frame_menubar_1, "free-frame-menubar-1");
5198 DEFSYM (Qfree_frame_menubar_2, "free-frame-menubar-2");
5199 DEFSYM (Qmouse_color, "mouse-color");
5200 DEFSYM (Qname, "name");
5201 DEFSYM (Qright_divider_width, "right-divider-width");
5202 DEFSYM (Qright_fringe, "right-fringe");
5203 DEFSYM (Qscreen_gamma, "screen-gamma");
5204 DEFSYM (Qscroll_bar_background, "scroll-bar-background");
5205 DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
5206 DEFSYM (Qscroll_bar_height, "scroll-bar-height");
5207 DEFSYM (Qscroll_bar_width, "scroll-bar-width");
5208 DEFSYM (Qsticky, "sticky");
5209 DEFSYM (Qtitle, "title");
5210 DEFSYM (Qtool_bar_lines, "tool-bar-lines");
5211 DEFSYM (Qtool_bar_position, "tool-bar-position");
5212 DEFSYM (Qunsplittable, "unsplittable");
5213 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
5214 DEFSYM (Qvisibility, "visibility");
5215 DEFSYM (Qwait_for_wm, "wait-for-wm");
5216 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5217 DEFSYM (Qno_other_frame, "no-other-frame");
5218 DEFSYM (Qbelow, "below");
5219 DEFSYM (Qabove_suspended, "above-suspended");
5220 DEFSYM (Qmin_width, "min-width");
5221 DEFSYM (Qmin_height, "min-height");
5222 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
5225 int i;
5227 for (i = 0; i < ARRAYELTS (frame_parms); i++)
5229 Lisp_Object v = (frame_parms[i].sym < 0
5230 ? intern_c_string (frame_parms[i].name)
5231 : builtin_lisp_symbol (frame_parms[i].sym));
5232 Fput (v, Qx_frame_parameter, make_number (i));
5236 #ifdef HAVE_WINDOW_SYSTEM
5237 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
5238 doc: /* The name Emacs uses to look up X resources.
5239 `x-get-resource' uses this as the first component of the instance name
5240 when requesting resource values.
5241 Emacs initially sets `x-resource-name' to the name under which Emacs
5242 was invoked, or to the value specified with the `-name' or `-rn'
5243 switches, if present.
5245 It may be useful to bind this variable locally around a call
5246 to `x-get-resource'. See also the variable `x-resource-class'. */);
5247 Vx_resource_name = Qnil;
5249 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
5250 doc: /* The class Emacs uses to look up X resources.
5251 `x-get-resource' uses this as the first component of the instance class
5252 when requesting resource values.
5254 Emacs initially sets `x-resource-class' to "Emacs".
5256 Setting this variable permanently is not a reasonable thing to do,
5257 but binding this variable locally around a call to `x-get-resource'
5258 is a reasonable practice. See also the variable `x-resource-name'. */);
5259 Vx_resource_class = build_string (EMACS_CLASS);
5261 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
5262 doc: /* The lower limit of the frame opacity (alpha transparency).
5263 The value should range from 0 (invisible) to 100 (completely opaque).
5264 You can also use a floating number between 0.0 and 1.0. */);
5265 Vframe_alpha_lower_limit = make_number (20);
5266 #endif
5268 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
5269 doc: /* Alist of default values for frame creation.
5270 These may be set in your init file, like this:
5271 (setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
5272 These override values given in window system configuration data,
5273 including X Windows' defaults database.
5274 For values specific to the first Emacs frame, see `initial-frame-alist'.
5275 For window-system specific values, see `window-system-default-frame-alist'.
5276 For values specific to the separate minibuffer frame, see
5277 `minibuffer-frame-alist'.
5278 The `menu-bar-lines' element of the list controls whether new frames
5279 have menu bars; `menu-bar-mode' works by altering this element.
5280 Setting this variable does not affect existing frames, only new ones. */);
5281 Vdefault_frame_alist = Qnil;
5283 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
5284 doc: /* Default position of vertical scroll bars on this window-system. */);
5285 #ifdef HAVE_WINDOW_SYSTEM
5286 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
5287 /* MS-Windows, macOS, and GTK have scroll bars on the right by
5288 default. */
5289 Vdefault_frame_scroll_bars = Qright;
5290 #else
5291 Vdefault_frame_scroll_bars = Qleft;
5292 #endif
5293 #else
5294 Vdefault_frame_scroll_bars = Qnil;
5295 #endif
5297 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
5298 scroll_bar_adjust_thumb_portion_p,
5299 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
5300 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
5301 even if the end of the buffer is shown (i.e. overscrolling).
5302 Set to nil if you want the thumb to be at the bottom when the end of the buffer
5303 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
5304 is visible. In this case you can not overscroll. */);
5305 scroll_bar_adjust_thumb_portion_p = 1;
5307 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
5308 doc: /* The initial frame-object, which represents Emacs's stdout. */);
5310 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
5311 doc: /* If non-nil, function to transform normal value of `mouse-position'.
5312 `mouse-position' and `mouse-pixel-position' call this function, passing their
5313 usual return value as argument, and return whatever this function returns.
5314 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
5315 which need to do mouse handling at the Lisp level. */);
5316 Vmouse_position_function = Qnil;
5318 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
5319 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
5320 If the value is an integer, highlighting is only shown after moving the
5321 mouse, while keyboard input turns off the highlight even when the mouse
5322 is over the clickable text. However, the mouse shape still indicates
5323 when the mouse is over clickable text. */);
5324 Vmouse_highlight = Qt;
5326 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
5327 doc: /* If non-nil, make pointer invisible while typing.
5328 The pointer becomes visible again when the mouse is moved. */);
5329 Vmake_pointer_invisible = Qt;
5331 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
5332 doc: /* Normal hook run when a frame gains input focus.
5333 The frame gaining focus is selected at the time this hook is run. */);
5334 Vfocus_in_hook = Qnil;
5336 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
5337 doc: /* Normal hook run when all frames lost input focus. */);
5338 Vfocus_out_hook = Qnil;
5340 DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
5341 doc: /* Functions run after a frame was moved.
5342 The functions are run with one arg, the frame that moved. */);
5343 Vmove_frame_functions = Qnil;
5345 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
5346 doc: /* Functions run before deleting a frame.
5347 The functions are run with one arg, the frame to be deleted.
5348 See `delete-frame'.
5350 Note that functions in this list may be called just before the frame is
5351 actually deleted, or some time later (or even both when an earlier function
5352 in `delete-frame-functions' (indirectly) calls `delete-frame'
5353 recursively). */);
5354 Vdelete_frame_functions = Qnil;
5355 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
5357 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
5358 doc: /* Non-nil if Menu-Bar mode is enabled.
5359 See the command `menu-bar-mode' for a description of this minor mode.
5360 Setting this variable directly does not take effect;
5361 either customize it (see the info node `Easy Customization')
5362 or call the function `menu-bar-mode'. */);
5363 Vmenu_bar_mode = Qt;
5365 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
5366 doc: /* Non-nil if Tool-Bar mode is enabled.
5367 See the command `tool-bar-mode' for a description of this minor mode.
5368 Setting this variable directly does not take effect;
5369 either customize it (see the info node `Easy Customization')
5370 or call the function `tool-bar-mode'. */);
5371 #ifdef HAVE_WINDOW_SYSTEM
5372 Vtool_bar_mode = Qt;
5373 #else
5374 Vtool_bar_mode = Qnil;
5375 #endif
5377 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
5378 doc: /* Minibufferless frames use this frame's minibuffer.
5379 Emacs cannot create minibufferless frames unless this is set to an
5380 appropriate surrogate.
5382 Emacs consults this variable only when creating minibufferless
5383 frames; once the frame is created, it sticks with its assigned
5384 minibuffer, no matter what this variable is set to. This means that
5385 this variable doesn't necessarily say anything meaningful about the
5386 current set of frames, or where the minibuffer is currently being
5387 displayed.
5389 This variable is local to the current terminal and cannot be buffer-local. */);
5391 DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
5392 doc: /* Non-nil if window system changes focus when you move the mouse.
5393 You should set this variable to tell Emacs how your window manager
5394 handles focus, since there is no way in general for Emacs to find out
5395 automatically.
5397 There are three meaningful values:
5399 - The default nil should be used when your window manager follows a
5400 "click-to-focus" policy where you have to click the mouse inside of a
5401 frame in order for that frame to get focus.
5403 - The value t should be used when your window manager has the focus
5404 automatically follow the position of the mouse pointer but a window
5405 that gains focus is not raised automatically.
5407 - The value `auto-raise' should be used when your window manager has the
5408 focus automatically follow the position of the mouse pointer and a
5409 window that gains focus is raised automatically.
5411 If this option is non-nil, Emacs moves the mouse pointer to the frame
5412 selected by `select-frame-set-input-focus'. This function is used by a
5413 number of commands like, for example, `other-frame' and `pop-to-buffer'.
5414 If this option is nil and your focus follows mouse window manager does
5415 not autonomously move the mouse pointer to the newly selected frame, the
5416 previously selected window manager window might get reselected instead
5417 immediately.
5419 The distinction between the values t and `auto-raise' is not needed for
5420 "normal" frames because the window manager takes care of raising them.
5421 Setting this to `auto-raise' will, however, override the standard
5422 behavior of a window manager that does not automatically raise the frame
5423 that gets focus. Setting this to `auto-raise' is also necessary to
5424 automatically raise child frames which are usually left alone by the
5425 window manager.
5427 Note that this option does not distinguish "sloppy" focus (where the
5428 frame that previously had focus retains focus as long as the mouse
5429 pointer does not move into another window manager window) from "strict"
5430 focus (where a frame immediately loses focus when it's left by the mouse
5431 pointer).
5433 In order to extend a "focus follows mouse" policy to individual Emacs
5434 windows, customize the variable `mouse-autoselect-window'. */);
5435 focus_follows_mouse = Qnil;
5437 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5438 doc: /* Non-nil means resize frames pixelwise.
5439 If this option is nil, resizing a frame rounds its sizes to the frame's
5440 current values of `frame-char-height' and `frame-char-width'. If this
5441 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5442 by one pixel.
5444 With some window managers you may have to set this to non-nil in order
5445 to set the size of a frame in pixels, to maximize frames or to make them
5446 fullscreen. To resize your initial frame pixelwise, set this option to
5447 a non-nil value in your init file. */);
5448 frame_resize_pixelwise = 0;
5450 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
5451 doc: /* Whether frames should be resized implicitly.
5452 If this option is nil, setting font, menu bar, tool bar, internal
5453 borders, fringes or scroll bars of a specific frame may resize the frame
5454 in order to preserve the number of columns or lines it displays. If
5455 this option is t, no such resizing is done. Note that the size of
5456 fullscreen and maximized frames, the height of fullheight frames and the
5457 width of fullwidth frames never change implicitly.
5459 The value of this option can be also be a list of frame parameters. In
5460 this case, resizing is inhibited when changing a parameter that appears
5461 in that list. The parameters currently handled by this option include
5462 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
5463 `tool-bar-lines'.
5465 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
5466 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
5467 `right-fringe' is handled as if the frame contained just one live
5468 window. This means, for example, that removing vertical scroll bars on
5469 a frame containing several side by side windows will shrink the frame
5470 width by the width of one scroll bar provided this option is nil and
5471 keep it unchanged if this option is either t or a list containing
5472 `vertical-scroll-bars'.
5474 The default value is \\='(tool-bar-lines) on Lucid, Motif and Windows
5475 \(which means that adding/removing a tool bar does not change the frame
5476 height), nil on all other window systems including GTK+ (which means
5477 that changing any of the parameters listed above may change the size of
5478 the frame), and t otherwise (which means the frame size never changes
5479 implicitly when there's no window system support).
5481 Note that when a frame is not large enough to accommodate a change of
5482 any of the parameters listed above, Emacs may try to enlarge the frame
5483 even if this option is non-nil. */);
5484 #if defined (HAVE_WINDOW_SYSTEM)
5485 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
5486 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
5487 #else
5488 frame_inhibit_implied_resize = Qnil;
5489 #endif
5490 #else
5491 frame_inhibit_implied_resize = Qt;
5492 #endif
5494 DEFVAR_LISP ("frame-size-history", frame_size_history,
5495 doc: /* History of frame size adjustments.
5496 If non-nil, list recording frame size adjustment. Adjustments are
5497 recorded only if the first element of this list is a positive number.
5498 Adding an adjustment decrements that number by one.
5500 The remaining elements are the adjustments. Each adjustment is a list
5501 of four elements `frame', `function', `sizes' and `more'. `frame' is
5502 the affected frame and `function' the invoking function. `sizes' is
5503 usually a list of four elements `old-width', `old-height', `new-width'
5504 and `new-height' representing the old and new sizes recorded/requested
5505 by `function'. `more' is a list with additional information.
5507 The function `frame--size-history' displays the value of this variable
5508 in a more readable form. */);
5509 frame_size_history = Qnil;
5511 DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame,
5512 doc: /* Non-nil means reuse hidden tooltip frames.
5513 When this is nil, delete a tooltip frame when hiding the associated
5514 tooltip. When this is non-nil, make the tooltip frame invisible only,
5515 so it can be reused when the next tooltip is shown.
5517 Setting this to non-nil may drastically reduce the consing overhead
5518 incurred by creating new tooltip frames. However, a value of non-nil
5519 means also that intermittent changes of faces or `default-frame-alist'
5520 are not applied when showing a tooltip in a reused frame.
5522 This variable is effective only with the X toolkit (and there only when
5523 Gtk+ tooltips are not used) and on Windows. */);
5524 tooltip_reuse_hidden_frame = false;
5526 staticpro (&Vframe_list);
5528 defsubr (&Sframep);
5529 defsubr (&Sframe_live_p);
5530 defsubr (&Swindow_system);
5531 defsubr (&Sframe_windows_min_size);
5532 defsubr (&Smake_terminal_frame);
5533 defsubr (&Shandle_switch_frame);
5534 defsubr (&Sselect_frame);
5535 defsubr (&Sselected_frame);
5536 defsubr (&Sframe_list);
5537 defsubr (&Sframe_parent);
5538 defsubr (&Sframe_ancestor_p);
5539 defsubr (&Snext_frame);
5540 defsubr (&Sprevious_frame);
5541 defsubr (&Slast_nonminibuf_frame);
5542 defsubr (&Sdelete_frame);
5543 defsubr (&Smouse_position);
5544 defsubr (&Smouse_pixel_position);
5545 defsubr (&Sset_mouse_position);
5546 defsubr (&Sset_mouse_pixel_position);
5547 #if 0
5548 defsubr (&Sframe_configuration);
5549 defsubr (&Srestore_frame_configuration);
5550 #endif
5551 defsubr (&Smake_frame_visible);
5552 defsubr (&Smake_frame_invisible);
5553 defsubr (&Siconify_frame);
5554 defsubr (&Sframe_visible_p);
5555 defsubr (&Svisible_frame_list);
5556 defsubr (&Sraise_frame);
5557 defsubr (&Slower_frame);
5558 defsubr (&Sx_focus_frame);
5559 defsubr (&Sframe_after_make_frame);
5560 defsubr (&Sredirect_frame_focus);
5561 defsubr (&Sframe_focus);
5562 defsubr (&Sframe_parameters);
5563 defsubr (&Sframe_parameter);
5564 defsubr (&Smodify_frame_parameters);
5565 defsubr (&Sframe_char_height);
5566 defsubr (&Sframe_char_width);
5567 defsubr (&Sframe_pixel_height);
5568 defsubr (&Sframe_pixel_width);
5569 defsubr (&Sframe_text_cols);
5570 defsubr (&Sframe_text_lines);
5571 defsubr (&Sframe_total_cols);
5572 defsubr (&Sframe_total_lines);
5573 defsubr (&Sframe_text_width);
5574 defsubr (&Sframe_text_height);
5575 defsubr (&Sscroll_bar_width);
5576 defsubr (&Sscroll_bar_height);
5577 defsubr (&Sfringe_width);
5578 defsubr (&Sborder_width);
5579 defsubr (&Sright_divider_width);
5580 defsubr (&Sbottom_divider_width);
5581 defsubr (&Stool_bar_pixel_width);
5582 defsubr (&Sset_frame_height);
5583 defsubr (&Sset_frame_width);
5584 defsubr (&Sset_frame_size);
5585 defsubr (&Sframe_position);
5586 defsubr (&Sset_frame_position);
5587 defsubr (&Sframe_pointer_visible_p);
5589 #ifdef HAVE_WINDOW_SYSTEM
5590 defsubr (&Sx_get_resource);
5591 defsubr (&Sx_parse_geometry);
5592 #endif