Avoid crashes due to invalid error forms from sentinels/filters
[emacs.git] / src / frame.c
blob39e5cc9c85438e563d8fd4bcae017dca28a0da2e
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 <https://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 inner height
332 * (width) of FRAME 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 #ifdef HAVE_WINDOW_SYSTEM
378 * keep_ratio:
380 * Preserve ratios of frame F which usually happens after its parent
381 * frame P got resized. OLD_WIDTH, OLD_HEIGHT specifies the old native
382 * size of F's parent, NEW_WIDTH and NEW_HEIGHT its new size.
384 * Adjust F's width if F's 'keep_ratio' parameter is non-nil and, if
385 * it is a cons, its car is not 'height-only'. Adjust F's height if F's
386 * 'keep_ratio' parameter is non-nil and, if it is a cons, its car
387 * is not 'width-only'.
389 * Adjust F's left position if F's 'keep_ratio' parameter is non-nil
390 * and, if its is a cons, its cdr is non-nil and not 'top-only'. Adjust
391 * F's top position if F's 'keep_ratio' parameter is non-nil and, if
392 * its is a cons, its cdr is non-nil and not 'left-only'.
394 * Note that when positional adjustment is requested but the size of F
395 * should remain unaltered in the corresponding direction, this routine
396 * tries to constrain F to its parent frame - something which usually
397 * happens when the parent frame shrinks. This means, however, that
398 * when the parent frame is re-enlarged later, the child's original
399 * position will not get restored to its pre-shrinking value.
401 * This routine is currently useful for child frames only. It might be
402 * eventually useful when moving non-child frames between monitors with
403 * different resolutions.
405 static void
406 keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
407 int new_width, int new_height)
409 Lisp_Object keep_ratio = get_frame_param (f, Qkeep_ratio);
412 if (!NILP (keep_ratio))
414 double width_factor = (double)new_width / (double)old_width;
415 double height_factor = (double)new_height / (double)old_height;
416 int pixel_width, pixel_height, pos_x, pos_y;
418 if (!CONSP (keep_ratio) || !NILP (Fcdr (keep_ratio)))
420 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qtop_only))
421 pos_x = f->left_pos;
422 else
424 pos_x = (int)(f->left_pos * width_factor + 0.5);
426 if (CONSP (keep_ratio)
427 && (NILP (Fcar (keep_ratio))
428 || EQ (Fcar (keep_ratio), Qheight_only))
429 && p->pixel_width - f->pixel_width < pos_x)
431 int p_f_width = p->pixel_width - f->pixel_width;
433 if (p_f_width <= 0)
434 pos_x = 0;
435 else
436 pos_x = (int)(p_f_width * width_factor * 0.5 + 0.5);
439 f->left_pos = pos_x;
442 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qleft_only))
443 pos_y = f->top_pos;
444 else
446 pos_y = (int)(f->top_pos * height_factor + 0.5);
448 if (CONSP (keep_ratio)
449 && (NILP (Fcar (keep_ratio))
450 || EQ (Fcar (keep_ratio), Qwidth_only))
451 && p->pixel_height - f->pixel_height < pos_y)
452 /* When positional adjustment was requested and the
453 width of F should remain unaltered, try to constrain
454 F to its parent. This means that when the parent
455 frame is enlarged later the child's original position
456 won't get restored. */
458 int p_f_height = p->pixel_height - f->pixel_height;
460 if (p_f_height <= 0)
461 pos_y = 0;
462 else
463 pos_y = (int)(p_f_height * height_factor * 0.5 + 0.5);
466 f->top_pos = pos_y;
469 x_set_offset (f, pos_x, pos_y, -1);
472 if (!CONSP (keep_ratio) || !NILP (Fcar (keep_ratio)))
474 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qheight_only))
475 pixel_width = -1;
476 else
478 pixel_width = (int)(f->pixel_width * width_factor + 0.5);
479 pixel_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixel_width);
482 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qwidth_only))
483 pixel_height = -1;
484 else
486 pixel_height = (int)(f->pixel_height * height_factor + 0.5);
487 pixel_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixel_height);
490 adjust_frame_size (f, pixel_width, pixel_height, 1, 0,
491 Qkeep_ratio);
495 #endif
499 * adjust_frame_size:
501 * Adjust size of frame F. NEW_WIDTH and NEW_HEIGHT specify the new
502 * text size of F in pixels. A value of -1 means no change is requested
503 * for that direction (but the frame may still have to be resized to
504 * accommodate windows with their minimum sizes). This can either issue
505 * a request to resize the frame externally (via x_set_window_size), to
506 * resize the frame internally (via resize_frame_windows) or do nothing
507 * at all.
509 * The argument INHIBIT can assume the following values:
511 * 0 means to unconditionally call x_set_window_size even if sizes
512 * apparently do not change. Fx_create_frame uses this to pass the
513 * initial size to the window manager.
515 * 1 means to call x_set_window_size if the native frame size really
516 * changes. Fset_frame_size, Fset_frame_height, ... use this.
518 * 2 means to call x_set_window_size provided frame_inhibit_resize
519 * allows it. The menu and tool bar code use this ("3" won't work
520 * here in general because menu and tool bar are often not counted in
521 * the frame's text height).
523 * 3 means call x_set_window_size if window minimum sizes must be
524 * preserved or frame_inhibit_resize allows it. x_set_left_fringe,
525 * x_set_scroll_bar_width, x_new_font ... use (or should use) this.
527 * 4 means call x_set_window_size only if window minimum sizes must be
528 * preserved. x_set_right_divider_width, x_set_border_width and the
529 * code responsible for wrapping the tool bar use this.
531 * 5 means to never call x_set_window_size. change_frame_size uses
532 * this.
534 * Note that even when x_set_window_size is not called, individual
535 * windows may have to be resized (via `window--sanitize-window-sizes')
536 * in order to support minimum size constraints.
538 * PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
539 * symbol of the parameter changed (like `menu-bar-lines', `font', ...).
540 * This is passed on to frame_inhibit_resize to let the latter decide on
541 * a case-by-case basis whether the frame may be resized externally.
543 void
544 adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
545 bool pretend, Lisp_Object parameter)
547 int unit_width = FRAME_COLUMN_WIDTH (f);
548 int unit_height = FRAME_LINE_HEIGHT (f);
549 int old_pixel_width = FRAME_PIXEL_WIDTH (f);
550 int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
551 int old_cols = FRAME_COLS (f);
552 int old_lines = FRAME_LINES (f);
553 int new_pixel_width, new_pixel_height;
554 /* The following two values are calculated from the old frame pixel
555 sizes and any "new" settings for tool bar, menu bar and internal
556 borders. We do it this way to detect whether we have to call
557 x_set_window_size as consequence of the new settings. */
558 int windows_width = FRAME_WINDOWS_WIDTH (f);
559 int windows_height = FRAME_WINDOWS_HEIGHT (f);
560 int min_windows_width, min_windows_height;
561 /* These are a bit tedious, maybe we should use a macro. */
562 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
563 int old_windows_width = WINDOW_PIXEL_WIDTH (r);
564 int old_windows_height
565 = (WINDOW_PIXEL_HEIGHT (r)
566 + ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
567 ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
568 : 0));
569 int new_windows_width, new_windows_height;
570 int old_text_width = FRAME_TEXT_WIDTH (f);
571 int old_text_height = FRAME_TEXT_HEIGHT (f);
572 /* If a size is < 0 use the old value. */
573 int new_text_width = (new_width >= 0) ? new_width : old_text_width;
574 int new_text_height = (new_height >= 0) ? new_height : old_text_height;
575 int new_cols, new_lines;
576 bool inhibit_horizontal, inhibit_vertical;
577 Lisp_Object frame;
579 XSETFRAME (frame, f);
581 frame_size_history_add
582 (f, Qadjust_frame_size_1, new_text_width, new_text_height,
583 list2 (parameter, make_number (inhibit)));
585 /* The following two values are calculated from the old window body
586 sizes and any "new" settings for scroll bars, dividers, fringes and
587 margins (though the latter should have been processed already). */
588 min_windows_width
589 = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
590 min_windows_height
591 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
593 if (inhibit >= 2 && inhibit <= 4)
594 /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
595 within the limits and either resizing is inhibited or INHIBIT
596 equals 4. */
598 inhibit_horizontal = (windows_width >= min_windows_width
599 && (inhibit == 4
600 || frame_inhibit_resize (f, true, parameter)));
601 inhibit_vertical = (windows_height >= min_windows_height
602 && (inhibit == 4
603 || frame_inhibit_resize (f, false, parameter)));
605 else
606 /* Otherwise inhibit if INHIBIT equals 5. */
607 inhibit_horizontal = inhibit_vertical = inhibit == 5;
609 new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
610 ? old_pixel_width
611 : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
612 min_windows_width
613 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
614 new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
615 new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
616 new_cols = new_text_width / unit_width;
618 new_pixel_height = ((inhibit_vertical && (inhibit < 5))
619 ? old_pixel_height
620 : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
621 min_windows_height
622 + FRAME_TOP_MARGIN_HEIGHT (f)
623 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
624 new_windows_height = (new_pixel_height
625 - FRAME_TOP_MARGIN_HEIGHT (f)
626 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
627 new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
628 new_lines = new_text_height / unit_height;
630 #ifdef HAVE_WINDOW_SYSTEM
631 if (FRAME_WINDOW_P (f)
632 && f->can_x_set_window_size
633 && ((!inhibit_horizontal
634 && (new_pixel_width != old_pixel_width
635 || inhibit == 0 || inhibit == 2))
636 || (!inhibit_vertical
637 && (new_pixel_height != old_pixel_height
638 || inhibit == 0 || inhibit == 2))))
639 /* We are either allowed to change the frame size or the minimum
640 sizes request such a change. Do not care for fixing minimum
641 sizes here, we do that eventually when we're called from
642 change_frame_size. */
644 /* Make sure we respect fullheight and fullwidth. */
645 if (inhibit_horizontal)
646 new_text_width = old_text_width;
647 else if (inhibit_vertical)
648 new_text_height = old_text_height;
650 frame_size_history_add
651 (f, Qadjust_frame_size_2, new_text_width, new_text_height,
652 list2 (inhibit_horizontal ? Qt : Qnil,
653 inhibit_vertical ? Qt : Qnil));
655 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
656 f->resized_p = true;
658 return;
660 #endif
662 if (new_text_width == old_text_width
663 && new_text_height == old_text_height
664 && new_windows_width == old_windows_width
665 && new_windows_height == old_windows_height
666 && new_pixel_width == old_pixel_width
667 && new_pixel_height == old_pixel_height
668 && new_cols == old_cols
669 && new_lines == old_lines)
670 /* No change. Sanitize window sizes and return. */
672 sanitize_window_sizes (Qt);
673 sanitize_window_sizes (Qnil);
675 return;
678 block_input ();
680 #ifdef MSDOS
681 /* We only can set screen dimensions to certain values supported by
682 our video hardware. Try to find the smallest size greater or
683 equal to the requested dimensions, while accounting for the fact
684 that the menu-bar lines are not counted in the frame height. */
685 int dos_new_lines = new_lines + FRAME_TOP_MARGIN (f);
686 dos_set_window_size (&dos_new_lines, &new_cols);
687 new_lines = dos_new_lines - FRAME_TOP_MARGIN (f);
688 #endif
690 if (new_windows_width != old_windows_width)
692 resize_frame_windows (f, new_windows_width, 1, 1);
694 /* MSDOS frames cannot PRETEND, as they change frame size by
695 manipulating video hardware. */
696 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
697 FrameCols (FRAME_TTY (f)) = new_cols;
699 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
700 if (WINDOWP (f->tool_bar_window))
702 XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
703 XWINDOW (f->tool_bar_window)->total_cols
704 = new_windows_width / unit_width;
706 #endif
708 else if (new_cols != old_cols)
709 call2 (Qwindow__pixel_to_total, frame, Qt);
711 if (new_windows_height != old_windows_height
712 /* When the top margin has changed we have to recalculate the top
713 edges of all windows. No such calculation is necessary for the
714 left edges. */
715 || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
717 resize_frame_windows (f, new_windows_height, 0, 1);
719 /* MSDOS frames cannot PRETEND, as they change frame size by
720 manipulating video hardware. */
721 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
722 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
724 else if (new_lines != old_lines)
725 call2 (Qwindow__pixel_to_total, frame, Qnil);
727 frame_size_history_add
728 (f, Qadjust_frame_size_3, new_text_width, new_text_height,
729 list4 (make_number (old_pixel_width), make_number (old_pixel_height),
730 make_number (new_pixel_width), make_number (new_pixel_height)));
732 /* Assign new sizes. */
733 FRAME_TEXT_WIDTH (f) = new_text_width;
734 FRAME_TEXT_HEIGHT (f) = new_text_height;
735 FRAME_PIXEL_WIDTH (f) = new_pixel_width;
736 FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
737 SET_FRAME_COLS (f, new_cols);
738 SET_FRAME_LINES (f, new_lines);
741 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
742 int text_area_x, text_area_y, text_area_width, text_area_height;
744 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
745 &text_area_height);
746 if (w->cursor.x >= text_area_x + text_area_width)
747 w->cursor.hpos = w->cursor.x = 0;
748 if (w->cursor.y >= text_area_y + text_area_height)
749 w->cursor.vpos = w->cursor.y = 0;
752 /* Sanitize window sizes. */
753 sanitize_window_sizes (Qt);
754 sanitize_window_sizes (Qnil);
756 adjust_frame_glyphs (f);
757 calculate_costs (f);
758 SET_FRAME_GARBAGED (f);
760 /* A frame was "resized" if one of its pixelsizes changed, even if its
761 X window wasn't resized at all. */
762 f->resized_p = (new_pixel_width != old_pixel_width
763 || new_pixel_height != old_pixel_height);
765 unblock_input ();
767 #ifdef HAVE_WINDOW_SYSTEM
769 /* Adjust size of F's child frames. */
770 Lisp_Object frames, frame1;
772 FOR_EACH_FRAME (frames, frame1)
773 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f)
774 keep_ratio (XFRAME (frame1), f, old_pixel_width, old_pixel_height,
775 new_pixel_width, new_pixel_height);
777 #endif
780 /* Allocate basically initialized frame. */
782 static struct frame *
783 allocate_frame (void)
785 return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
788 struct frame *
789 make_frame (bool mini_p)
791 Lisp_Object frame;
792 struct frame *f;
793 struct window *rw, *mw UNINIT;
794 Lisp_Object root_window;
795 Lisp_Object mini_window;
797 f = allocate_frame ();
798 XSETFRAME (frame, f);
800 #ifdef USE_GTK
801 /* Initialize Lisp data. Note that allocate_frame initializes all
802 Lisp data to nil, so do it only for slots which should not be nil. */
803 fset_tool_bar_position (f, Qtop);
804 #endif
806 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
807 non-Lisp data, so do it only for slots which should not be zero.
808 To avoid subtle bugs and for the sake of readability, it's better to
809 initialize enum members explicitly even if their values are zero. */
810 f->wants_modeline = true;
811 f->redisplay = true;
812 f->garbaged = true;
813 f->can_x_set_window_size = false;
814 f->after_make_frame = false;
815 f->inhibit_horizontal_resize = false;
816 f->inhibit_vertical_resize = false;
817 f->tool_bar_redisplayed = false;
818 f->tool_bar_resized = false;
819 f->column_width = 1; /* !FRAME_WINDOW_P value. */
820 f->line_height = 1; /* !FRAME_WINDOW_P value. */
821 #ifdef HAVE_WINDOW_SYSTEM
822 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
823 f->horizontal_scroll_bars = false;
824 f->want_fullscreen = FULLSCREEN_NONE;
825 f->undecorated = false;
826 f->no_special_glyphs = false;
827 #ifndef HAVE_NTGUI
828 f->override_redirect = false;
829 #endif
830 f->skip_taskbar = false;
831 f->no_focus_on_map = false;
832 f->no_accept_focus = false;
833 f->z_group = z_group_none;
834 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
835 f->last_tool_bar_item = -1;
836 #endif
837 #ifdef NS_IMPL_COCOA
838 f->ns_appearance = ns_appearance_aqua;
839 f->ns_transparent_titlebar = false;
840 #endif
841 #endif
843 root_window = make_window ();
844 rw = XWINDOW (root_window);
845 if (mini_p)
847 mini_window = make_window ();
848 mw = XWINDOW (mini_window);
849 wset_next (rw, mini_window);
850 wset_prev (mw, root_window);
851 mw->mini = 1;
852 wset_frame (mw, frame);
853 fset_minibuffer_window (f, mini_window);
854 store_frame_param (f, Qminibuffer, Qt);
856 else
858 mini_window = Qnil;
859 wset_next (rw, Qnil);
860 fset_minibuffer_window (f, Qnil);
863 wset_frame (rw, frame);
865 /* 10 is arbitrary,
866 just so that there is "something there."
867 Correct size will be set up later with adjust_frame_size. */
869 SET_FRAME_COLS (f, 10);
870 SET_FRAME_LINES (f, 10);
871 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
872 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
874 rw->total_cols = 10;
875 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
876 rw->total_lines = mini_p ? 9 : 10;
877 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
879 if (mini_p)
881 mw->top_line = rw->total_lines;
882 mw->pixel_top = rw->pixel_height;
883 mw->total_cols = rw->total_cols;
884 mw->pixel_width = rw->pixel_width;
885 mw->total_lines = 1;
886 mw->pixel_height = FRAME_LINE_HEIGHT (f);
889 /* Choose a buffer for the frame's root window. */
891 Lisp_Object buf = Fcurrent_buffer ();
893 /* If current buffer is hidden, try to find another one. */
894 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
895 buf = other_buffer_safely (buf);
897 /* Use set_window_buffer, not Fset_window_buffer, and don't let
898 hooks be run by it. The reason is that the whole frame/window
899 arrangement is not yet fully initialized at this point. Windows
900 don't have the right size, glyph matrices aren't initialized
901 etc. Running Lisp functions at this point surely ends in a
902 SEGV. */
903 set_window_buffer (root_window, buf, 0, 0);
904 fset_buffer_list (f, list1 (buf));
907 if (mini_p)
909 set_window_buffer (mini_window,
910 (NILP (Vminibuffer_list)
911 ? get_minibuffer (0)
912 : Fcar (Vminibuffer_list)),
913 0, 0);
914 /* No horizontal scroll bars in minibuffers. */
915 wset_horizontal_scroll_bar (mw, Qnil);
918 fset_root_window (f, root_window);
919 fset_selected_window (f, root_window);
920 /* Make sure this window seems more recently used than
921 a newly-created, never-selected window. */
922 XWINDOW (f->selected_window)->use_time = ++window_select_count;
924 return f;
927 #ifdef HAVE_WINDOW_SYSTEM
928 /* Make a frame using a separate minibuffer window on another frame.
929 MINI_WINDOW is the minibuffer window to use. nil means use the
930 default (the global minibuffer). */
932 struct frame *
933 make_frame_without_minibuffer (Lisp_Object mini_window, KBOARD *kb,
934 Lisp_Object display)
936 struct frame *f;
938 if (!NILP (mini_window))
939 CHECK_LIVE_WINDOW (mini_window);
941 if (!NILP (mini_window)
942 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
943 error ("Frame and minibuffer must be on the same terminal");
945 /* Make a frame containing just a root window. */
946 f = make_frame (0);
948 if (NILP (mini_window))
950 /* Use default-minibuffer-frame if possible. */
951 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
952 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
954 Lisp_Object frame_dummy;
956 XSETFRAME (frame_dummy, f);
957 /* If there's no minibuffer frame to use, create one. */
958 kset_default_minibuffer_frame
959 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
962 mini_window
963 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
966 fset_minibuffer_window (f, mini_window);
967 store_frame_param (f, Qminibuffer, mini_window);
969 /* Make the chosen minibuffer window display the proper minibuffer,
970 unless it is already showing a minibuffer. */
971 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
972 /* Use set_window_buffer instead of Fset_window_buffer (see
973 discussion of bug#11984, bug#12025, bug#12026). */
974 set_window_buffer (mini_window,
975 (NILP (Vminibuffer_list)
976 ? get_minibuffer (0)
977 : Fcar (Vminibuffer_list)), 0, 0);
978 return f;
981 /* Make a frame containing only a minibuffer window. */
983 struct frame *
984 make_minibuffer_frame (void)
986 /* First make a frame containing just a root window, no minibuffer. */
988 register struct frame *f = make_frame (0);
989 register Lisp_Object mini_window;
990 register Lisp_Object frame;
992 XSETFRAME (frame, f);
994 f->auto_raise = 0;
995 f->auto_lower = 0;
996 f->no_split = 1;
997 f->wants_modeline = 0;
999 /* Now label the root window as also being the minibuffer.
1000 Avoid infinite looping on the window chain by marking next pointer
1001 as nil. */
1003 mini_window = f->root_window;
1004 fset_minibuffer_window (f, mini_window);
1005 store_frame_param (f, Qminibuffer, Qonly);
1006 XWINDOW (mini_window)->mini = 1;
1007 wset_next (XWINDOW (mini_window), Qnil);
1008 wset_prev (XWINDOW (mini_window), Qnil);
1009 wset_frame (XWINDOW (mini_window), frame);
1011 /* Put the proper buffer in that window. */
1013 /* Use set_window_buffer instead of Fset_window_buffer (see
1014 discussion of bug#11984, bug#12025, bug#12026). */
1015 set_window_buffer (mini_window,
1016 (NILP (Vminibuffer_list)
1017 ? get_minibuffer (0)
1018 : Fcar (Vminibuffer_list)), 0, 0);
1019 return f;
1021 #endif /* HAVE_WINDOW_SYSTEM */
1023 /* Construct a frame that refers to a terminal. */
1025 static printmax_t tty_frame_count;
1027 struct frame *
1028 make_initial_frame (void)
1030 struct frame *f;
1031 struct terminal *terminal;
1032 Lisp_Object frame;
1034 eassert (initial_kboard);
1036 /* The first call must initialize Vframe_list. */
1037 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
1038 Vframe_list = Qnil;
1040 terminal = init_initial_terminal ();
1042 f = make_frame (1);
1043 XSETFRAME (frame, f);
1045 Vframe_list = Fcons (frame, Vframe_list);
1047 tty_frame_count = 1;
1048 fset_name (f, build_pure_c_string ("F1"));
1050 SET_FRAME_VISIBLE (f, 1);
1052 f->output_method = terminal->type;
1053 f->terminal = terminal;
1054 f->terminal->reference_count++;
1055 f->output_data.nothing = 0;
1057 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1058 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1060 #ifdef HAVE_WINDOW_SYSTEM
1061 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1062 f->horizontal_scroll_bars = false;
1063 #endif
1065 /* The default value of menu-bar-mode is t. */
1066 set_menu_bar_lines (f, make_number (1), Qnil);
1068 /* Allocate glyph matrices. */
1069 adjust_frame_glyphs (f);
1071 if (!noninteractive)
1072 init_frame_faces (f);
1074 last_nonminibuf_frame = f;
1076 f->can_x_set_window_size = true;
1077 f->after_make_frame = true;
1079 return f;
1083 static struct frame *
1084 make_terminal_frame (struct terminal *terminal)
1086 register struct frame *f;
1087 Lisp_Object frame;
1088 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
1090 if (!terminal->name)
1091 error ("Terminal is not live, can't create new frames on it");
1093 f = make_frame (1);
1095 XSETFRAME (frame, f);
1096 Vframe_list = Fcons (frame, Vframe_list);
1098 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
1100 SET_FRAME_VISIBLE (f, 1);
1102 f->terminal = terminal;
1103 f->terminal->reference_count++;
1104 #ifdef MSDOS
1105 f->output_data.tty->display_info = &the_only_display_info;
1106 if (!inhibit_window_system
1107 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
1108 || XFRAME (selected_frame)->output_method == output_msdos_raw))
1109 f->output_method = output_msdos_raw;
1110 else
1111 f->output_method = output_termcap;
1112 #else /* not MSDOS */
1113 f->output_method = output_termcap;
1114 create_tty_output (f);
1115 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1116 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1117 #endif /* not MSDOS */
1119 #ifdef HAVE_WINDOW_SYSTEM
1120 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1121 f->horizontal_scroll_bars = false;
1122 #endif
1124 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
1125 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
1126 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
1127 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
1129 /* Set the top frame to the newly created frame. */
1130 if (FRAMEP (FRAME_TTY (f)->top_frame)
1131 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
1132 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
1134 FRAME_TTY (f)->top_frame = frame;
1136 if (!noninteractive)
1137 init_frame_faces (f);
1139 return f;
1142 /* Get a suitable value for frame parameter PARAMETER for a newly
1143 created frame, based on (1) the user-supplied frame parameter
1144 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
1146 static Lisp_Object
1147 get_future_frame_param (Lisp_Object parameter,
1148 Lisp_Object supplied_parms,
1149 char *current_value)
1151 Lisp_Object result;
1153 result = Fassq (parameter, supplied_parms);
1154 if (NILP (result))
1155 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
1156 if (NILP (result) && current_value != NULL)
1157 result = build_string (current_value);
1158 if (!NILP (result) && !STRINGP (result))
1159 result = XCDR (result);
1160 if (NILP (result) || !STRINGP (result))
1161 result = Qnil;
1163 return result;
1166 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1167 1, 1, 0,
1168 doc: /* Create an additional terminal frame, possibly on another terminal.
1169 This function takes one argument, an alist specifying frame parameters.
1171 You can create multiple frames on a single text terminal, but only one
1172 of them (the selected terminal frame) is actually displayed.
1174 In practice, generally you don't need to specify any parameters,
1175 except when you want to create a new frame on another terminal.
1176 In that case, the `tty' parameter specifies the device file to open,
1177 and the `tty-type' parameter specifies the terminal type. Example:
1179 (make-terminal-frame \\='((tty . "/dev/pts/5") (tty-type . "xterm")))
1181 Note that changing the size of one terminal frame automatically
1182 affects all frames on the same terminal device. */)
1183 (Lisp_Object parms)
1185 struct frame *f;
1186 struct terminal *t = NULL;
1187 Lisp_Object frame, tem;
1188 struct frame *sf = SELECTED_FRAME ();
1190 #ifdef MSDOS
1191 if (sf->output_method != output_msdos_raw
1192 && sf->output_method != output_termcap)
1193 emacs_abort ();
1194 #else /* not MSDOS */
1196 #ifdef WINDOWSNT /* This should work now! */
1197 if (sf->output_method != output_termcap)
1198 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
1199 #endif
1200 #endif /* not MSDOS */
1203 Lisp_Object terminal;
1205 terminal = Fassq (Qterminal, parms);
1206 if (CONSP (terminal))
1208 terminal = XCDR (terminal);
1209 t = decode_live_terminal (terminal);
1211 #ifdef MSDOS
1212 if (t && t != the_only_display_info.terminal)
1213 /* msdos.c assumes a single tty_display_info object. */
1214 error ("Multiple terminals are not supported on this platform");
1215 if (!t)
1216 t = the_only_display_info.terminal;
1217 #endif
1220 if (!t)
1222 char *name = 0, *type = 0;
1223 Lisp_Object tty, tty_type;
1224 USE_SAFE_ALLOCA;
1226 tty = get_future_frame_param
1227 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1228 ? FRAME_TTY (XFRAME (selected_frame))->name
1229 : NULL));
1230 if (!NILP (tty))
1231 SAFE_ALLOCA_STRING (name, tty);
1233 tty_type = get_future_frame_param
1234 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1235 ? FRAME_TTY (XFRAME (selected_frame))->type
1236 : NULL));
1237 if (!NILP (tty_type))
1238 SAFE_ALLOCA_STRING (type, tty_type);
1240 t = init_tty (name, type, 0); /* Errors are not fatal. */
1241 SAFE_FREE ();
1244 f = make_terminal_frame (t);
1247 int width, height;
1248 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1249 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
1250 5, 0, Qterminal_frame);
1253 adjust_frame_glyphs (f);
1254 calculate_costs (f);
1255 XSETFRAME (frame, f);
1257 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
1258 store_in_alist (&parms, Qtty,
1259 (t->display_info.tty->name
1260 ? build_string (t->display_info.tty->name)
1261 : Qnil));
1262 /* On terminal frames the `minibuffer' frame parameter is always
1263 virtually t. Avoid that a different value in parms causes
1264 complaints, see Bug#24758. */
1265 store_in_alist (&parms, Qminibuffer, Qt);
1266 Fmodify_frame_parameters (frame, parms);
1268 /* Make the frame face alist be frame-specific, so that each
1269 frame could change its face definitions independently. */
1270 fset_face_alist (f, Fcopy_alist (sf->face_alist));
1271 /* Simple Fcopy_alist isn't enough, because we need the contents of
1272 the vectors which are the CDRs of associations in face_alist to
1273 be copied as well. */
1274 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
1275 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
1277 f->can_x_set_window_size = true;
1278 f->after_make_frame = true;
1280 return frame;
1284 /* Perform the switch to frame FRAME.
1286 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
1287 FRAME1 as frame.
1289 If TRACK is non-zero and the frame that currently has the focus
1290 redirects its focus to the selected frame, redirect that focused
1291 frame's focus to FRAME instead.
1293 FOR_DELETION non-zero means that the selected frame is being
1294 deleted, which includes the possibility that the frame's terminal
1295 is dead.
1297 The value of NORECORD is passed as argument to Fselect_window. */
1299 Lisp_Object
1300 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1302 struct frame *sf = SELECTED_FRAME (), *f;
1304 /* If FRAME is a switch-frame event, extract the frame we should
1305 switch to. */
1306 if (CONSP (frame)
1307 && EQ (XCAR (frame), Qswitch_frame)
1308 && CONSP (XCDR (frame)))
1309 frame = XCAR (XCDR (frame));
1311 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1312 a switch-frame event to arrive after a frame is no longer live,
1313 especially when deleting the initial frame during startup. */
1314 CHECK_FRAME (frame);
1315 f = XFRAME (frame);
1316 if (!FRAME_LIVE_P (f))
1317 return Qnil;
1318 else if (f == sf)
1319 return frame;
1321 /* If a frame's focus has been redirected toward the currently
1322 selected frame, we should change the redirection to point to the
1323 newly selected frame. This means that if the focus is redirected
1324 from a minibufferless frame to a surrogate minibuffer frame, we
1325 can use `other-window' to switch between all the frames using
1326 that minibuffer frame, and the focus redirection will follow us
1327 around. */
1328 #if 0
1329 /* This is too greedy; it causes inappropriate focus redirection
1330 that's hard to get rid of. */
1331 if (track)
1333 Lisp_Object tail;
1335 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1337 Lisp_Object focus;
1339 if (!FRAMEP (XCAR (tail)))
1340 emacs_abort ();
1342 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1344 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1345 Fredirect_frame_focus (XCAR (tail), frame);
1348 #else /* ! 0 */
1349 /* Instead, apply it only to the frame we're pointing to. */
1350 #ifdef HAVE_WINDOW_SYSTEM
1351 if (track && FRAME_WINDOW_P (f))
1353 Lisp_Object focus, xfocus;
1355 xfocus = x_get_focus_frame (f);
1356 if (FRAMEP (xfocus))
1358 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1359 if ((FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1360 /* Redirect frame focus also when FRAME has its minibuffer
1361 window on the selected frame (see Bug#24500). */
1362 || (NILP (focus)
1363 && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))
1364 Fredirect_frame_focus (xfocus, frame);
1367 #endif /* HAVE_X_WINDOWS */
1368 #endif /* ! 0 */
1370 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1371 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1373 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
1375 struct tty_display_info *tty = FRAME_TTY (f);
1376 Lisp_Object top_frame = tty->top_frame;
1378 /* Don't mark the frame garbaged and/or obscured if we are
1379 switching to the frame that is already the top frame of that
1380 TTY. */
1381 if (!EQ (frame, top_frame))
1383 if (FRAMEP (top_frame))
1384 /* Mark previously displayed frame as now obscured. */
1385 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1386 SET_FRAME_VISIBLE (f, 1);
1387 /* If the new TTY frame changed dimensions, we need to
1388 resync term.c's idea of the frame size with the new
1389 frame's data. */
1390 if (FRAME_COLS (f) != FrameCols (tty))
1391 FrameCols (tty) = FRAME_COLS (f);
1392 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1393 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1395 tty->top_frame = frame;
1398 selected_frame = frame;
1399 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1400 last_nonminibuf_frame = XFRAME (selected_frame);
1402 Fselect_window (f->selected_window, norecord);
1404 /* We want to make sure that the next event generates a frame-switch
1405 event to the appropriate frame. This seems kludgy to me, but
1406 before you take it out, make sure that evaluating something like
1407 (select-window (frame-root-window (new-frame))) doesn't end up
1408 with your typing being interpreted in the new frame instead of
1409 the one you're actually typing in. */
1410 #ifdef HAVE_WINDOW_SYSTEM
1411 if (!frame_ancestor_p (f, sf))
1412 #endif
1413 internal_last_event_frame = Qnil;
1415 return frame;
1418 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1419 doc: /* Select FRAME.
1420 Subsequent editing commands apply to its selected window.
1421 Optional argument NORECORD means to neither change the order of
1422 recently selected windows nor the buffer list.
1424 The selection of FRAME lasts until the next time the user does
1425 something to select a different frame, or until the next time
1426 this function is called. If you are using a window system, the
1427 previously selected frame may be restored as the selected frame
1428 when returning to the command loop, because it still may have
1429 the window system's input focus. On a text terminal, the next
1430 redisplay will display FRAME.
1432 This function returns FRAME, or nil if FRAME has been deleted. */)
1433 (Lisp_Object frame, Lisp_Object norecord)
1435 return do_switch_frame (frame, 1, 0, norecord);
1438 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1439 doc: /* Handle a switch-frame event EVENT.
1440 Switch-frame events are usually bound to this function.
1441 A switch-frame event tells Emacs that the window manager has requested
1442 that the user's events be directed to the frame mentioned in the event.
1443 This function selects the selected window of the frame of EVENT.
1445 If EVENT is frame object, handle it as if it were a switch-frame event
1446 to that frame. */)
1447 (Lisp_Object event)
1449 Lisp_Object value;
1451 /* Preserve prefix arg that the command loop just cleared. */
1452 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1453 run_hook (Qmouse_leave_buffer_hook);
1454 /* `switch-frame' implies a focus in. */
1455 value = do_switch_frame (event, 0, 0, Qnil);
1456 call1 (intern ("handle-focus-in"), event);
1457 return value;
1460 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1461 doc: /* Return the frame that is now selected. */)
1462 (void)
1464 return selected_frame;
1467 DEFUN ("frame-list", Fframe_list, Sframe_list,
1468 0, 0, 0,
1469 doc: /* Return a list of all live frames. */)
1470 (void)
1472 Lisp_Object frames;
1473 frames = Fcopy_sequence (Vframe_list);
1474 #ifdef HAVE_WINDOW_SYSTEM
1475 if (FRAMEP (tip_frame))
1476 frames = Fdelq (tip_frame, frames);
1477 #endif
1478 return frames;
1481 DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
1482 0, 1, 0,
1483 doc: /* Return the parent frame of FRAME.
1484 The parent frame of FRAME is the Emacs frame whose window-system window
1485 is the parent window of FRAME's window-system window. When such a frame
1486 exists, FRAME is considered a child frame of that frame.
1488 Return nil if FRAME has no parent frame. This means that FRAME's
1489 window-system window is either a "top-level" window (a window whose
1490 parent window is the window-system's root window) or an embedded window
1491 \(a window whose parent window is owned by some other application). */)
1492 (Lisp_Object frame)
1494 struct frame *f = decode_live_frame (frame);
1495 struct frame *p = FRAME_PARENT_FRAME (f);
1496 Lisp_Object parent;
1498 /* Can't return f->parent_frame directly since it might not be defined
1499 for this platform. */
1500 if (p)
1502 XSETFRAME (parent, p);
1504 return parent;
1506 else
1507 return Qnil;
1510 #ifdef HAVE_WINDOW_SYSTEM
1511 bool
1512 frame_ancestor_p (struct frame *af, struct frame *df)
1514 struct frame *pf = FRAME_PARENT_FRAME (df);
1516 while (pf)
1518 if (pf == af)
1519 return true;
1520 else
1521 pf = FRAME_PARENT_FRAME (pf);
1524 return false;
1526 #endif
1528 DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1529 2, 2, 0,
1530 doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
1531 ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
1532 parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
1533 ANCESTOR and DESCENDANT must be live frames and default to the selected
1534 frame. */)
1535 (Lisp_Object ancestor, Lisp_Object descendant)
1537 #ifdef HAVE_WINDOW_SYSTEM
1538 struct frame *af = decode_live_frame (ancestor);
1539 struct frame *df = decode_live_frame (descendant);
1541 return frame_ancestor_p (af, df) ? Qt : Qnil;
1542 #else
1543 return Qnil;
1544 #endif
1547 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1548 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1549 If MINIBUF is nil, do not consider minibuffer-only candidate.
1550 If MINIBUF is `visible', do not consider an invisible candidate.
1551 If MINIBUF is a window, consider only its own frame and candidate now
1552 using that window as the minibuffer.
1553 If MINIBUF is 0, consider candidate if it is visible or iconified.
1554 Otherwise consider any candidate and return nil if CANDIDATE is not
1555 acceptable. */
1557 static Lisp_Object
1558 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1560 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1562 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1563 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1564 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1565 && FRAME_TTY (c) == FRAME_TTY (f)))
1567 if (!NILP (get_frame_param (c, Qno_other_frame)))
1568 return Qnil;
1569 else if (NILP (minibuf))
1571 if (!FRAME_MINIBUF_ONLY_P (c))
1572 return candidate;
1574 else if (EQ (minibuf, Qvisible))
1576 if (FRAME_VISIBLE_P (c))
1577 return candidate;
1579 else if (WINDOWP (minibuf))
1581 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1582 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1583 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1584 FRAME_FOCUS_FRAME (c)))
1585 return candidate;
1587 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
1589 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1590 return candidate;
1592 else
1593 return candidate;
1595 return Qnil;
1598 /* Return the next frame in the frame list after FRAME. */
1600 static Lisp_Object
1601 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1603 Lisp_Object f, tail;
1604 int passed = 0;
1606 while (passed < 2)
1607 FOR_EACH_FRAME (tail, f)
1609 if (passed)
1611 f = candidate_frame (f, frame, minibuf);
1612 if (!NILP (f))
1613 return f;
1615 if (EQ (frame, f))
1616 passed++;
1618 return frame;
1621 /* Return the previous frame in the frame list before FRAME. */
1623 static Lisp_Object
1624 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1626 Lisp_Object f, tail, prev = Qnil;
1628 FOR_EACH_FRAME (tail, f)
1630 if (EQ (frame, f) && !NILP (prev))
1631 return prev;
1632 f = candidate_frame (f, frame, minibuf);
1633 if (!NILP (f))
1634 prev = f;
1637 /* We've scanned the entire list. */
1638 if (NILP (prev))
1639 /* We went through the whole frame list without finding a single
1640 acceptable frame. Return the original frame. */
1641 return frame;
1642 else
1643 /* There were no acceptable frames in the list before FRAME; otherwise,
1644 we would have returned directly from the loop. Since PREV is the last
1645 acceptable frame in the list, return it. */
1646 return prev;
1650 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1651 doc: /* Return the next frame in the frame list after FRAME.
1652 It considers only frames on the same terminal as FRAME.
1653 By default, skip minibuffer-only frames.
1654 If omitted, FRAME defaults to the selected frame.
1655 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1656 If MINIFRAME is a window, include only its own frame
1657 and any frame now using that window as the minibuffer.
1658 If MINIFRAME is `visible', include all visible frames.
1659 If MINIFRAME is 0, include all visible and iconified frames.
1660 Otherwise, include all frames. */)
1661 (Lisp_Object frame, Lisp_Object miniframe)
1663 if (NILP (frame))
1664 frame = selected_frame;
1665 CHECK_LIVE_FRAME (frame);
1666 return next_frame (frame, miniframe);
1669 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1670 doc: /* Return the previous frame in the frame list before FRAME.
1671 It considers only frames on the same terminal as FRAME.
1672 By default, skip minibuffer-only frames.
1673 If omitted, FRAME defaults to the selected frame.
1674 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1675 If MINIFRAME is a window, include only its own frame
1676 and any frame now using that window as the minibuffer.
1677 If MINIFRAME is `visible', include all visible frames.
1678 If MINIFRAME is 0, include all visible and iconified frames.
1679 Otherwise, include all frames. */)
1680 (Lisp_Object frame, Lisp_Object miniframe)
1682 if (NILP (frame))
1683 frame = selected_frame;
1684 CHECK_LIVE_FRAME (frame);
1685 return prev_frame (frame, miniframe);
1688 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1689 Slast_nonminibuf_frame, 0, 0, 0,
1690 doc: /* Return last non-minibuffer frame selected. */)
1691 (void)
1693 Lisp_Object frame = Qnil;
1695 if (last_nonminibuf_frame)
1696 XSETFRAME (frame, last_nonminibuf_frame);
1698 return frame;
1702 * other_frames:
1704 * Return true if there exists at least one visible or iconified frame
1705 * but F. Return false otherwise.
1707 * INVISIBLE true means we are called from make_frame_invisible where
1708 * such a frame must be visible or iconified. INVISIBLE nil means we
1709 * are called from delete_frame. In that case FORCE true means that the
1710 * visibility status of such a frame can be ignored.
1712 * If F is the terminal frame and we are using X, return true if at
1713 * least one X frame exists.
1715 static bool
1716 other_frames (struct frame *f, bool invisible, bool force)
1718 Lisp_Object frames, frame, frame1;
1719 struct frame *f1;
1720 Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
1722 XSETFRAME (frame, f);
1723 if (WINDOWP (minibuffer_window)
1724 && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
1725 minibuffer_window = Qnil;
1727 FOR_EACH_FRAME (frames, frame1)
1729 f1 = XFRAME (frame1);
1730 if (f != f1)
1732 /* Verify that we can still talk to the frame's X window, and
1733 note any recent change in visibility. */
1734 #ifdef HAVE_X_WINDOWS
1735 if (FRAME_WINDOW_P (f1))
1736 x_sync (f1);
1737 #endif
1738 if (NILP (Fframe_parameter (frame1, Qtooltip))
1739 /* Tooltips and child frames count neither for
1740 invisibility nor for deletions. */
1741 && !FRAME_PARENT_FRAME (f1)
1742 /* Frames with a non-nil `delete-before' parameter don't
1743 count for deletions. */
1744 && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
1745 /* For invisibility and normal deletions, at least one
1746 visible or iconified frame must remain (Bug#26682). */
1747 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
1748 || (!invisible
1749 && (force
1750 /* Allow deleting the terminal frame when at
1751 least one X frame exists. */
1752 || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))))
1753 return true;
1757 return false;
1760 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1761 window. Preferably use the selected frame's minibuffer window
1762 instead. If the selected frame doesn't have one, get some other
1763 frame's minibuffer window. SELECT non-zero means select the new
1764 minibuffer window. */
1765 static void
1766 check_minibuf_window (Lisp_Object frame, int select)
1768 struct frame *f = decode_live_frame (frame);
1770 XSETFRAME (frame, f);
1772 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1774 Lisp_Object frames, this, window = make_number (0);
1776 if (!EQ (frame, selected_frame)
1777 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1778 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1779 else
1780 FOR_EACH_FRAME (frames, this)
1782 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1784 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1785 break;
1789 /* Don't abort if no window was found (Bug#15247). */
1790 if (WINDOWP (window))
1792 /* Use set_window_buffer instead of Fset_window_buffer (see
1793 discussion of bug#11984, bug#12025, bug#12026). */
1794 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1795 minibuf_window = window;
1797 /* SELECT non-zero usually means that FRAME's minibuffer
1798 window was selected; select the new one. */
1799 if (select)
1800 Fselect_window (minibuf_window, Qnil);
1807 * delete_frame:
1809 * Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1810 * unconditionally. x_connection_closed and delete_terminal use this.
1811 * Any other value of FORCE implements the semantics described for
1812 * Fdelete_frame. */
1813 Lisp_Object
1814 delete_frame (Lisp_Object frame, Lisp_Object force)
1816 struct frame *f = decode_any_frame (frame);
1817 struct frame *sf;
1818 struct kboard *kb;
1819 Lisp_Object frames, frame1;
1820 int minibuffer_selected, is_tooltip_frame;
1821 bool nochild = !FRAME_PARENT_FRAME (f);
1823 if (!FRAME_LIVE_P (f))
1824 return Qnil;
1825 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1827 if (NILP (force))
1828 error ("Attempt to delete the sole visible or iconified frame");
1829 else
1830 error ("Attempt to delete the only frame");
1833 XSETFRAME (frame, f);
1835 /* Softly delete all frames with this frame as their parent frame or
1836 as their `delete-before' frame parameter value. */
1837 FOR_EACH_FRAME (frames, frame1)
1838 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
1839 /* Process `delete-before' parameter iff FRAME is not a child
1840 frame. This avoids that we enter an infinite chain of mixed
1841 dependencies. */
1842 || (nochild
1843 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
1844 delete_frame (frame1, Qnil);
1846 /* Does this frame have a minibuffer, and is it the surrogate
1847 minibuffer for any other frame? */
1848 if (FRAME_HAS_MINIBUF_P (f))
1850 FOR_EACH_FRAME (frames, frame1)
1852 Lisp_Object fminiw;
1854 if (EQ (frame1, frame))
1855 continue;
1857 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
1859 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1861 /* If we MUST delete this frame, delete the other first.
1862 But do this only if FORCE equals `noelisp'. */
1863 if (EQ (force, Qnoelisp))
1864 delete_frame (frame1, Qnoelisp);
1865 else
1866 error ("Attempt to delete a surrogate minibuffer frame");
1871 is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
1873 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1874 frame is a tooltip. FORCE is set to `noelisp' when handling
1875 a disconnect from the terminal, so we don't dare call Lisp
1876 code. */
1877 if (NILP (Vrun_hooks) || is_tooltip_frame)
1879 else if (EQ (force, Qnoelisp))
1880 pending_funcalls
1881 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1882 pending_funcalls);
1883 else
1885 #ifdef HAVE_X_WINDOWS
1886 /* Also, save clipboard to the clipboard manager. */
1887 x_clipboard_manager_save_frame (frame);
1888 #endif
1890 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1893 /* delete_frame_functions may have deleted any frame, including this
1894 one. */
1895 if (!FRAME_LIVE_P (f))
1896 return Qnil;
1897 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1899 if (NILP (force))
1900 error ("Attempt to delete the sole visible or iconified frame");
1901 else
1902 error ("Attempt to delete the only frame");
1905 /* At this point, we are committed to deleting the frame.
1906 There is no more chance for errors to prevent it. */
1907 minibuffer_selected = EQ (minibuf_window, selected_window);
1908 sf = SELECTED_FRAME ();
1909 /* Don't let the frame remain selected. */
1910 if (f == sf)
1912 Lisp_Object tail;
1914 /* Look for another visible frame on the same terminal.
1915 Do not call next_frame here because it may loop forever.
1916 See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1917 FOR_EACH_FRAME (tail, frame1)
1918 if (!EQ (frame, frame1)
1919 && (FRAME_TERMINAL (XFRAME (frame))
1920 == FRAME_TERMINAL (XFRAME (frame1)))
1921 && FRAME_VISIBLE_P (XFRAME (frame1)))
1922 break;
1924 /* If there is none, find *some* other frame. */
1925 if (NILP (frame1) || EQ (frame1, frame))
1927 FOR_EACH_FRAME (tail, frame1)
1929 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
1931 /* Do not change a text terminal's top-frame. */
1932 struct frame *f1 = XFRAME (frame1);
1933 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1935 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1936 if (!EQ (top_frame, frame))
1937 frame1 = top_frame;
1939 break;
1943 #ifdef NS_IMPL_COCOA
1944 else
1945 /* Under NS, there is no system mechanism for choosing a new
1946 window to get focus -- it is left to application code.
1947 So the portion of THIS application interfacing with NS
1948 needs to know about it. We call Fraise_frame, but the
1949 purpose is really to transfer focus. */
1950 Fraise_frame (frame1);
1951 #endif
1953 do_switch_frame (frame1, 0, 1, Qnil);
1954 sf = SELECTED_FRAME ();
1957 /* Don't allow minibuf_window to remain on a deleted frame. */
1958 check_minibuf_window (frame, minibuffer_selected);
1960 /* Don't let echo_area_window to remain on a deleted frame. */
1961 if (EQ (f->minibuffer_window, echo_area_window))
1962 echo_area_window = sf->minibuffer_window;
1964 /* Clear any X selections for this frame. */
1965 #ifdef HAVE_X_WINDOWS
1966 if (FRAME_X_P (f))
1967 x_clear_frame_selections (f);
1968 #endif
1970 /* Free glyphs.
1971 This function must be called before the window tree of the
1972 frame is deleted because windows contain dynamically allocated
1973 memory. */
1974 free_glyphs (f);
1976 #ifdef HAVE_WINDOW_SYSTEM
1977 /* Give chance to each font driver to free a frame specific data. */
1978 font_update_drivers (f, Qnil);
1979 #endif
1981 /* Mark all the windows that used to be on FRAME as deleted, and then
1982 remove the reference to them. */
1983 delete_all_child_windows (f->root_window);
1984 fset_root_window (f, Qnil);
1986 Vframe_list = Fdelq (frame, Vframe_list);
1987 SET_FRAME_VISIBLE (f, 0);
1989 /* Allow the vector of menu bar contents to be freed in the next
1990 garbage collection. The frame object itself may not be garbage
1991 collected until much later, because recent_keys and other data
1992 structures can still refer to it. */
1993 fset_menu_bar_vector (f, Qnil);
1995 /* If FRAME's buffer lists contains killed
1996 buffers, this helps GC to reclaim them. */
1997 fset_buffer_list (f, Qnil);
1998 fset_buried_buffer_list (f, Qnil);
2000 free_font_driver_list (f);
2001 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
2002 xfree (f->namebuf);
2003 #endif
2004 xfree (f->decode_mode_spec_buffer);
2005 xfree (FRAME_INSERT_COST (f));
2006 xfree (FRAME_DELETEN_COST (f));
2007 xfree (FRAME_INSERTN_COST (f));
2008 xfree (FRAME_DELETE_COST (f));
2010 /* Since some events are handled at the interrupt level, we may get
2011 an event for f at any time; if we zero out the frame's terminal
2012 now, then we may trip up the event-handling code. Instead, we'll
2013 promise that the terminal of the frame must be valid until we
2014 have called the window-system-dependent frame destruction
2015 routine. */
2017 struct terminal *terminal;
2018 block_input ();
2019 if (FRAME_TERMINAL (f)->delete_frame_hook)
2020 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
2021 terminal = FRAME_TERMINAL (f);
2022 f->output_data.nothing = 0;
2023 f->terminal = 0; /* Now the frame is dead. */
2024 unblock_input ();
2026 /* If needed, delete the terminal that this frame was on.
2027 (This must be done after the frame is killed.) */
2028 terminal->reference_count--;
2029 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
2030 /* FIXME: Deleting the terminal crashes emacs because of a GTK
2031 bug.
2032 http://lists.gnu.org/archive/html/emacs-devel/2011-10/msg00363.html */
2034 /* Since a similar behavior was observed on the Lucid and Motif
2035 builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now
2036 don't delete the terminal for these builds either. */
2037 if (terminal->reference_count == 0 && terminal->type == output_x_window)
2038 terminal->reference_count = 1;
2039 #endif /* USE_X_TOOLKIT || USE_GTK */
2040 if (terminal->reference_count == 0)
2042 Lisp_Object tmp;
2043 XSETTERMINAL (tmp, terminal);
2045 kb = NULL;
2046 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
2048 else
2049 kb = terminal->kboard;
2052 /* If we've deleted the last_nonminibuf_frame, then try to find
2053 another one. */
2054 if (f == last_nonminibuf_frame)
2056 last_nonminibuf_frame = 0;
2058 FOR_EACH_FRAME (frames, frame1)
2060 struct frame *f1 = XFRAME (frame1);
2062 if (!FRAME_MINIBUF_ONLY_P (f1))
2064 last_nonminibuf_frame = f1;
2065 break;
2070 /* If there's no other frame on the same kboard, get out of
2071 single-kboard state if we're in it for this kboard. */
2072 if (kb != NULL)
2074 /* Some frame we found on the same kboard, or nil if there are none. */
2075 Lisp_Object frame_on_same_kboard = Qnil;
2077 FOR_EACH_FRAME (frames, frame1)
2078 if (kb == FRAME_KBOARD (XFRAME (frame1)))
2079 frame_on_same_kboard = frame1;
2081 if (NILP (frame_on_same_kboard))
2082 not_single_kboard_state (kb);
2086 /* If we've deleted this keyboard's default_minibuffer_frame, try to
2087 find another one. Prefer minibuffer-only frames, but also notice
2088 frames with other windows. */
2089 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
2091 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
2092 Lisp_Object frame_with_minibuf = Qnil;
2093 /* Some frame we found on the same kboard, or nil if there are none. */
2094 Lisp_Object frame_on_same_kboard = Qnil;
2096 FOR_EACH_FRAME (frames, frame1)
2098 struct frame *f1 = XFRAME (frame1);
2100 /* Consider only frames on the same kboard
2101 and only those with minibuffers. */
2102 if (kb == FRAME_KBOARD (f1)
2103 && FRAME_HAS_MINIBUF_P (f1))
2105 frame_with_minibuf = frame1;
2106 if (FRAME_MINIBUF_ONLY_P (f1))
2107 break;
2110 if (kb == FRAME_KBOARD (f1))
2111 frame_on_same_kboard = frame1;
2114 if (!NILP (frame_on_same_kboard))
2116 /* We know that there must be some frame with a minibuffer out
2117 there. If this were not true, all of the frames present
2118 would have to be minibufferless, which implies that at some
2119 point their minibuffer frames must have been deleted, but
2120 that is prohibited at the top; you can't delete surrogate
2121 minibuffer frames. */
2122 if (NILP (frame_with_minibuf))
2123 emacs_abort ();
2125 kset_default_minibuffer_frame (kb, frame_with_minibuf);
2127 else
2128 /* No frames left on this kboard--say no minibuffer either. */
2129 kset_default_minibuffer_frame (kb, Qnil);
2132 /* Cause frame titles to update--necessary if we now have just one frame. */
2133 if (!is_tooltip_frame)
2134 update_mode_lines = 15;
2136 return Qnil;
2139 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
2140 doc: /* Delete FRAME, permanently eliminating it from use.
2141 FRAME must be a live frame and defaults to the selected one.
2143 A frame may not be deleted if its minibuffer serves as surrogate
2144 minibuffer for another frame. Normally, you may not delete a frame if
2145 all other frames are invisible, but if the second optional argument
2146 FORCE is non-nil, you may do so.
2148 This function runs `delete-frame-functions' before actually
2149 deleting the frame, unless the frame is a tooltip.
2150 The functions are run with one argument, the frame to be deleted. */)
2151 (Lisp_Object frame, Lisp_Object force)
2153 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
2156 #ifdef HAVE_WINDOW_SYSTEM
2158 * frame_internal_border_part:
2160 * Return part of internal border the coordinates X and Y relative to
2161 * frame F are on. Return nil if the coordinates are not on the
2162 * internal border of F.
2164 * Return one of INTERNAL_BORDER_LEFT_EDGE, INTERNAL_BORDER_TOP_EDGE,
2165 * INTERNAL_BORDER_RIGHT_EDGE or INTERNAL_BORDER_BOTTOM_EDGE when the
2166 * mouse cursor is on the corresponding border with an offset of at
2167 * least one canonical character height from that border's edges.
2169 * If no border part could be found this way, return one of
2170 * INTERNAL_BORDER_TOP_LEFT_CORNER, INTERNAL_BORDER_TOP_RIGHT_CORNER,
2171 * INTERNAL_BORDER_BOTTOM_LEFT_CORNER or
2172 * INTERNAL_BORDER_BOTTOM_RIGHT_CORNER to indicate that the mouse is in
2173 * one of the corresponding corners. This means that for very small
2174 * frames an `edge' return value is preferred.
2176 enum internal_border_part
2177 frame_internal_border_part (struct frame *f, int x, int y)
2179 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
2180 int offset = FRAME_LINE_HEIGHT (f);
2181 int width = FRAME_PIXEL_WIDTH (f);
2182 int height = FRAME_PIXEL_HEIGHT (f);
2183 enum internal_border_part part = INTERNAL_BORDER_NONE;
2185 if (offset < border)
2186 /* For very wide borders make offset at least as large as
2187 border. */
2188 offset = border;
2190 if (offset < x && x < width - offset)
2191 /* Top or bottom border. */
2193 if (0 <= y && y <= border)
2194 part = INTERNAL_BORDER_TOP_EDGE;
2195 else if (height - border <= y && y <= height)
2196 part = INTERNAL_BORDER_BOTTOM_EDGE;
2198 else if (offset < y && y < height - offset)
2199 /* Left or right border. */
2201 if (0 <= x && x <= border)
2202 part = INTERNAL_BORDER_LEFT_EDGE;
2203 else if (width - border <= x && x <= width)
2204 part = INTERNAL_BORDER_RIGHT_EDGE;
2206 else
2208 /* An edge. */
2209 int half_width = width / 2;
2210 int half_height = height / 2;
2212 if (0 <= x && x <= border)
2214 /* A left edge. */
2215 if (0 <= y && y <= half_height)
2216 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2217 else if (half_height < y && y <= height)
2218 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2220 else if (width - border <= x && x <= width)
2222 /* A right edge. */
2223 if (0 <= y && y <= half_height)
2224 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2225 else if (half_height < y && y <= height)
2226 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2228 else if (0 <= y && y <= border)
2230 /* A top edge. */
2231 if (0 <= x && x <= half_width)
2232 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2233 else if (half_width < x && x <= width)
2234 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2236 else if (height - border <= y && y <= height)
2238 /* A bottom edge. */
2239 if (0 <= x && x <= half_width)
2240 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2241 else if (half_width < x && x <= width)
2242 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2246 return part;
2248 #endif
2250 /* Return mouse position in character cell units. */
2252 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
2253 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2254 The position is given in canonical character cells, where (0, 0) is the
2255 upper-left corner of the frame, X is the horizontal offset, and Y is the
2256 vertical offset, measured in units of the frame's default character size.
2257 If Emacs is running on a mouseless terminal or hasn't been programmed
2258 to read the mouse position, it returns the selected frame for FRAME
2259 and nil for X and Y.
2260 If `mouse-position-function' is non-nil, `mouse-position' calls it,
2261 passing the normal return value to that function as an argument,
2262 and returns whatever that function returns. */)
2263 (void)
2265 struct frame *f;
2266 Lisp_Object lispy_dummy;
2267 Lisp_Object x, y, retval;
2269 f = SELECTED_FRAME ();
2270 x = y = Qnil;
2272 /* It's okay for the hook to refrain from storing anything. */
2273 if (FRAME_TERMINAL (f)->mouse_position_hook)
2275 enum scroll_bar_part party_dummy;
2276 Time time_dummy;
2277 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2278 &lispy_dummy, &party_dummy,
2279 &x, &y,
2280 &time_dummy);
2283 if (! NILP (x))
2285 int col = XINT (x);
2286 int row = XINT (y);
2287 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
2288 XSETINT (x, col);
2289 XSETINT (y, row);
2291 XSETFRAME (lispy_dummy, f);
2292 retval = Fcons (lispy_dummy, Fcons (x, y));
2293 if (!NILP (Vmouse_position_function))
2294 retval = call1 (Vmouse_position_function, retval);
2295 return retval;
2298 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
2299 Smouse_pixel_position, 0, 0, 0,
2300 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2301 The position is given in pixel units, where (0, 0) is the
2302 upper-left corner of the frame, X is the horizontal offset, and Y is
2303 the vertical offset.
2304 If Emacs is running on a mouseless terminal or hasn't been programmed
2305 to read the mouse position, it returns the selected frame for FRAME
2306 and nil for X and Y. */)
2307 (void)
2309 struct frame *f;
2310 Lisp_Object lispy_dummy;
2311 Lisp_Object x, y, retval;
2313 f = SELECTED_FRAME ();
2314 x = y = Qnil;
2316 /* It's okay for the hook to refrain from storing anything. */
2317 if (FRAME_TERMINAL (f)->mouse_position_hook)
2319 enum scroll_bar_part party_dummy;
2320 Time time_dummy;
2321 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2322 &lispy_dummy, &party_dummy,
2323 &x, &y,
2324 &time_dummy);
2327 XSETFRAME (lispy_dummy, f);
2328 retval = Fcons (lispy_dummy, Fcons (x, y));
2329 if (!NILP (Vmouse_position_function))
2330 retval = call1 (Vmouse_position_function, retval);
2331 return retval;
2334 #ifdef HAVE_WINDOW_SYSTEM
2336 /* On frame F, convert character coordinates X and Y to pixel
2337 coordinates *PIX_X and *PIX_Y. */
2339 static void
2340 frame_char_to_pixel_position (struct frame *f, int x, int y,
2341 int *pix_x, int *pix_y)
2343 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
2344 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
2346 if (*pix_x < 0)
2347 *pix_x = 0;
2348 if (*pix_x > FRAME_PIXEL_WIDTH (f))
2349 *pix_x = FRAME_PIXEL_WIDTH (f);
2351 if (*pix_y < 0)
2352 *pix_y = 0;
2353 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
2354 *pix_y = FRAME_PIXEL_HEIGHT (f);
2357 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
2359 static void
2360 frame_set_mouse_position (struct frame *f, int x, int y)
2362 int pix_x, pix_y;
2364 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
2365 frame_set_mouse_pixel_position (f, pix_x, pix_y);
2368 #endif /* HAVE_WINDOW_SYSTEM */
2370 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
2371 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
2372 Coordinates are relative to the frame, not a window,
2373 so the coordinates of the top left character in the frame
2374 may be nonzero due to left-hand scroll bars or the menu bar.
2376 The position is given in canonical character cells, where (0, 0) is
2377 the upper-left corner of the frame, X is the horizontal offset, and
2378 Y is the vertical offset, measured in units of the frame's default
2379 character size.
2381 This function is a no-op for an X frame that is not visible.
2382 If you have just created a frame, you must wait for it to become visible
2383 before calling this function on it, like this.
2384 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2385 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2387 CHECK_LIVE_FRAME (frame);
2388 CHECK_TYPE_RANGED_INTEGER (int, x);
2389 CHECK_TYPE_RANGED_INTEGER (int, y);
2391 /* I think this should be done with a hook. */
2392 #ifdef HAVE_WINDOW_SYSTEM
2393 if (FRAME_WINDOW_P (XFRAME (frame)))
2394 /* Warping the mouse will cause enternotify and focus events. */
2395 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
2396 #else
2397 #if defined (MSDOS)
2398 if (FRAME_MSDOS_P (XFRAME (frame)))
2400 Fselect_frame (frame, Qnil);
2401 mouse_moveto (XINT (x), XINT (y));
2403 #else
2404 #ifdef HAVE_GPM
2406 Fselect_frame (frame, Qnil);
2407 term_mouse_moveto (XINT (x), XINT (y));
2409 #endif
2410 #endif
2411 #endif
2413 return Qnil;
2416 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
2417 Sset_mouse_pixel_position, 3, 3, 0,
2418 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
2419 The position is given in pixels, where (0, 0) is the upper-left corner
2420 of the frame, X is the horizontal offset, and Y is the vertical offset.
2422 Note, this is a no-op for an X frame that is not visible.
2423 If you have just created a frame, you must wait for it to become visible
2424 before calling this function on it, like this.
2425 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2426 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2428 CHECK_LIVE_FRAME (frame);
2429 CHECK_TYPE_RANGED_INTEGER (int, x);
2430 CHECK_TYPE_RANGED_INTEGER (int, y);
2432 /* I think this should be done with a hook. */
2433 #ifdef HAVE_WINDOW_SYSTEM
2434 if (FRAME_WINDOW_P (XFRAME (frame)))
2435 /* Warping the mouse will cause enternotify and focus events. */
2436 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
2437 #else
2438 #if defined (MSDOS)
2439 if (FRAME_MSDOS_P (XFRAME (frame)))
2441 Fselect_frame (frame, Qnil);
2442 mouse_moveto (XINT (x), XINT (y));
2444 #else
2445 #ifdef HAVE_GPM
2447 Fselect_frame (frame, Qnil);
2448 term_mouse_moveto (XINT (x), XINT (y));
2450 #endif
2451 #endif
2452 #endif
2454 return Qnil;
2457 static void make_frame_visible_1 (Lisp_Object);
2459 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
2460 0, 1, "",
2461 doc: /* Make the frame FRAME visible (assuming it is an X window).
2462 If omitted, FRAME defaults to the currently selected frame. */)
2463 (Lisp_Object frame)
2465 struct frame *f = decode_live_frame (frame);
2467 /* I think this should be done with a hook. */
2468 #ifdef HAVE_WINDOW_SYSTEM
2469 if (FRAME_WINDOW_P (f))
2470 x_make_frame_visible (f);
2471 #endif
2473 make_frame_visible_1 (f->root_window);
2475 /* Make menu bar update for the Buffers and Frames menus. */
2476 /* windows_or_buffers_changed = 15; FIXME: Why? */
2478 XSETFRAME (frame, f);
2479 return frame;
2482 /* Update the display_time slot of the buffers shown in WINDOW
2483 and all its descendants. */
2485 static void
2486 make_frame_visible_1 (Lisp_Object window)
2488 struct window *w;
2490 for (; !NILP (window); window = w->next)
2492 w = XWINDOW (window);
2493 if (WINDOWP (w->contents))
2494 make_frame_visible_1 (w->contents);
2495 else
2496 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2500 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2501 0, 2, "",
2502 doc: /* Make the frame FRAME invisible.
2503 If omitted, FRAME defaults to the currently selected frame.
2504 On graphical displays, invisible frames are not updated and are
2505 usually not displayed at all, even in a window system's \"taskbar\".
2507 Normally you may not make FRAME invisible if all other frames are invisible,
2508 but if the second optional argument FORCE is non-nil, you may do so.
2510 This function has no effect on text terminal frames. Such frames are
2511 always considered visible, whether or not they are currently being
2512 displayed in the terminal. */)
2513 (Lisp_Object frame, Lisp_Object force)
2515 struct frame *f = decode_live_frame (frame);
2517 if (NILP (force) && !other_frames (f, true, false))
2518 error ("Attempt to make invisible the sole visible or iconified frame");
2520 /* Don't allow minibuf_window to remain on an invisible frame. */
2521 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2523 /* I think this should be done with a hook. */
2524 #ifdef HAVE_WINDOW_SYSTEM
2525 if (FRAME_WINDOW_P (f))
2526 x_make_frame_invisible (f);
2527 #endif
2529 /* Make menu bar update for the Buffers and Frames menus. */
2530 windows_or_buffers_changed = 16;
2532 return Qnil;
2535 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2536 0, 1, "",
2537 doc: /* Make the frame FRAME into an icon.
2538 If omitted, FRAME defaults to the currently selected frame. */)
2539 (Lisp_Object frame)
2541 struct frame *f = decode_live_frame (frame);
2543 /* Don't allow minibuf_window to remain on an iconified frame. */
2544 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2546 /* I think this should be done with a hook. */
2547 if (FRAME_WINDOW_P (f))
2549 #ifdef HAVE_WINDOW_SYSTEM
2550 x_iconify_frame (f);
2551 #endif
2554 return Qnil;
2557 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2558 1, 1, 0,
2559 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2560 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2561 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2562 On graphical displays, invisible frames are not updated and are
2563 usually not displayed at all, even in a window system's \"taskbar\".
2565 If FRAME is a text terminal frame, this always returns t.
2566 Such frames are always considered visible, whether or not they are
2567 currently being displayed on the terminal. */)
2568 (Lisp_Object frame)
2570 CHECK_LIVE_FRAME (frame);
2572 if (FRAME_VISIBLE_P (XFRAME (frame)))
2573 return Qt;
2574 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2575 return Qicon;
2576 return Qnil;
2579 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2580 0, 0, 0,
2581 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2582 (void)
2584 Lisp_Object tail, frame, value = Qnil;
2586 FOR_EACH_FRAME (tail, frame)
2587 if (FRAME_VISIBLE_P (XFRAME (frame)))
2588 value = Fcons (frame, value);
2590 return value;
2594 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2595 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2596 If FRAME is invisible or iconified, make it visible.
2597 If you don't specify a frame, the selected frame is used.
2598 If Emacs is displaying on an ordinary terminal or some other device which
2599 doesn't support multiple overlapping frames, this function selects FRAME. */)
2600 (Lisp_Object frame)
2602 struct frame *f = decode_live_frame (frame);
2604 XSETFRAME (frame, f);
2606 if (FRAME_TERMCAP_P (f))
2607 /* On a text terminal select FRAME. */
2608 Fselect_frame (frame, Qnil);
2609 else
2610 /* Do like the documentation says. */
2611 Fmake_frame_visible (frame);
2613 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2614 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2616 return Qnil;
2619 /* Should we have a corresponding function called Flower_Power? */
2620 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2621 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2622 If you don't specify a frame, the selected frame is used.
2623 If Emacs is displaying on an ordinary terminal or some other device which
2624 doesn't support multiple overlapping frames, this function does nothing. */)
2625 (Lisp_Object frame)
2627 struct frame *f = decode_live_frame (frame);
2629 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2630 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2632 return Qnil;
2636 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2637 1, 2, 0,
2638 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2639 In other words, switch-frame events caused by events in FRAME will
2640 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2641 FOCUS-FRAME after reading an event typed at FRAME.
2643 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2644 frame again receives its own keystrokes.
2646 Focus redirection is useful for temporarily redirecting keystrokes to
2647 a surrogate minibuffer frame when a frame doesn't have its own
2648 minibuffer window.
2650 A frame's focus redirection can be changed by `select-frame'. If frame
2651 FOO is selected, and then a different frame BAR is selected, any
2652 frames redirecting their focus to FOO are shifted to redirect their
2653 focus to BAR. This allows focus redirection to work properly when the
2654 user switches from one frame to another using `select-window'.
2656 This means that a frame whose focus is redirected to itself is treated
2657 differently from a frame whose focus is redirected to nil; the former
2658 is affected by `select-frame', while the latter is not.
2660 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2661 (Lisp_Object frame, Lisp_Object focus_frame)
2663 /* Note that we don't check for a live frame here. It's reasonable
2664 to redirect the focus of a frame you're about to delete, if you
2665 know what other frame should receive those keystrokes. */
2666 struct frame *f = decode_any_frame (frame);
2668 if (! NILP (focus_frame))
2669 CHECK_LIVE_FRAME (focus_frame);
2671 fset_focus_frame (f, focus_frame);
2673 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2674 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2676 return Qnil;
2680 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2681 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2682 If FRAME is omitted or nil, the selected frame is used.
2683 Return nil if FRAME's focus is not redirected.
2684 See `redirect-frame-focus'. */)
2685 (Lisp_Object frame)
2687 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2690 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 2, 0,
2691 doc: /* Set the input focus to FRAME.
2692 FRAME nil means use the selected frame. Optional argument NOACTIVATE
2693 means do not activate FRAME.
2695 If there is no window system support, this function does nothing. */)
2696 (Lisp_Object frame, Lisp_Object noactivate)
2698 #ifdef HAVE_WINDOW_SYSTEM
2699 x_focus_frame (decode_window_system_frame (frame), !NILP (noactivate));
2700 #endif
2701 return Qnil;
2704 DEFUN ("frame-after-make-frame",
2705 Fframe_after_make_frame,
2706 Sframe_after_make_frame, 2, 2, 0,
2707 doc: /* Mark FRAME as made.
2708 FRAME nil means use the selected frame. Second argument MADE non-nil
2709 means functions on `window-configuration-change-hook' are called
2710 whenever the window configuration of FRAME changes. MADE nil means
2711 these functions are not called.
2713 This function is currently called by `make-frame' only and should be
2714 otherwise used with utter care to avoid that running functions on
2715 `window-configuration-change-hook' is impeded forever. */)
2716 (Lisp_Object frame, Lisp_Object made)
2718 struct frame *f = decode_live_frame (frame);
2719 f->after_make_frame = !NILP (made);
2720 f->inhibit_horizontal_resize = false;
2721 f->inhibit_vertical_resize = false;
2722 return made;
2726 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2728 void
2729 frames_discard_buffer (Lisp_Object buffer)
2731 Lisp_Object frame, tail;
2733 FOR_EACH_FRAME (tail, frame)
2735 fset_buffer_list
2736 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2737 fset_buried_buffer_list
2738 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2742 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2743 If the alist already has an element for PROP, we change it. */
2745 void
2746 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2748 register Lisp_Object tem;
2750 tem = Fassq (prop, *alistptr);
2751 if (EQ (tem, Qnil))
2752 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2753 else
2754 Fsetcdr (tem, val);
2757 static int
2758 frame_name_fnn_p (char *str, ptrdiff_t len)
2760 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2762 char *p = str + 2;
2763 while ('0' <= *p && *p <= '9')
2764 p++;
2765 if (p == str + len)
2766 return 1;
2768 return 0;
2771 /* Set the name of the terminal frame. Also used by MSDOS frames.
2772 Modeled after x_set_name which is used for WINDOW frames. */
2774 static void
2775 set_term_frame_name (struct frame *f, Lisp_Object name)
2777 f->explicit_name = ! NILP (name);
2779 /* If NAME is nil, set the name to F<num>. */
2780 if (NILP (name))
2782 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2784 /* Check for no change needed in this very common case
2785 before we do any consing. */
2786 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2787 return;
2789 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2791 else
2793 CHECK_STRING (name);
2795 /* Don't change the name if it's already NAME. */
2796 if (! NILP (Fstring_equal (name, f->name)))
2797 return;
2799 /* Don't allow the user to set the frame name to F<num>, so it
2800 doesn't clash with the names we generate for terminal frames. */
2801 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2802 error ("Frame names of the form F<num> are usurped by Emacs");
2805 fset_name (f, name);
2806 update_mode_lines = 16;
2809 void
2810 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2812 register Lisp_Object old_alist_elt;
2814 if (EQ (prop, Qminibuffer))
2816 if (WINDOWP (val))
2818 if (!MINI_WINDOW_P (XWINDOW (val)))
2819 error ("The `minibuffer' parameter does not specify a valid minibuffer window");
2820 else if (FRAME_MINIBUF_ONLY_P (f))
2822 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2823 val = Qonly;
2824 else
2825 error ("Can't change the minibuffer window of a minibuffer-only frame");
2827 else if (FRAME_HAS_MINIBUF_P (f))
2829 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2830 val = Qt;
2831 else
2832 error ("Can't change the minibuffer window of a frame with its own minibuffer");
2834 else
2835 /* Store the chosen minibuffer window. */
2836 fset_minibuffer_window (f, val);
2838 else
2840 Lisp_Object old_val = Fcdr (Fassq (Qminibuffer, f->param_alist));
2842 if (!NILP (old_val))
2844 if (WINDOWP (old_val) && NILP (val))
2845 /* Don't change the value for a minibuffer-less frame if
2846 only nil was specified as new value. */
2847 val = old_val;
2848 else if (!EQ (old_val, val))
2849 error ("Can't change the `minibuffer' parameter of this frame");
2854 /* Check each parent-frame and delete-before parameter for a
2855 circular dependency. Do not check between parameters, so you can
2856 still create circular dependencies with different properties, for
2857 example a chain of frames F1->F2->...Fn such that F1 is an ancestor
2858 frame of Fn and thus cannot be deleted before Fn and a second chain
2859 Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
2860 else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
2862 Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
2864 if (!EQ (oldval, val) && !NILP (val))
2866 Lisp_Object frame;
2867 Lisp_Object frame1 = val;
2869 if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
2870 error ("Invalid `%s' frame parameter",
2871 SSDATA (SYMBOL_NAME (prop)));
2873 XSETFRAME (frame, f);
2875 while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
2876 if (EQ (frame1, frame))
2877 error ("Circular specification of `%s' frame parameter",
2878 SSDATA (SYMBOL_NAME (prop)));
2879 else
2880 frame1 = get_frame_param (XFRAME (frame1), prop);
2884 /* The buffer-list parameters are stored in a special place and not
2885 in the alist. All buffers must be live. */
2886 else if (EQ (prop, Qbuffer_list))
2888 Lisp_Object list = Qnil;
2889 for (; CONSP (val); val = XCDR (val))
2890 if (!NILP (Fbuffer_live_p (XCAR (val))))
2891 list = Fcons (XCAR (val), list);
2892 fset_buffer_list (f, Fnreverse (list));
2893 return;
2895 else if (EQ (prop, Qburied_buffer_list))
2897 Lisp_Object list = Qnil;
2898 for (; CONSP (val); val = XCDR (val))
2899 if (!NILP (Fbuffer_live_p (XCAR (val))))
2900 list = Fcons (XCAR (val), list);
2901 fset_buried_buffer_list (f, Fnreverse (list));
2902 return;
2905 /* The tty color needed to be set before the frame's parameter
2906 alist was updated with the new value. This is not true any more,
2907 but we still do this test early on. */
2908 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2909 && f == FRAME_TTY (f)->previous_frame)
2910 /* Force redisplay of this tty. */
2911 FRAME_TTY (f)->previous_frame = NULL;
2913 /* Update the frame parameter alist. */
2914 old_alist_elt = Fassq (prop, f->param_alist);
2915 if (EQ (old_alist_elt, Qnil))
2916 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2917 else
2918 Fsetcdr (old_alist_elt, val);
2920 /* Update some other special parameters in their special places
2921 in addition to the alist. */
2923 if (EQ (prop, Qbuffer_predicate))
2924 fset_buffer_predicate (f, val);
2926 if (! FRAME_WINDOW_P (f))
2928 if (EQ (prop, Qmenu_bar_lines))
2929 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2930 else if (EQ (prop, Qname))
2931 set_term_frame_name (f, val);
2935 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2936 is not an unspecified foreground or background color. */
2938 static Lisp_Object
2939 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
2941 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
2942 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
2943 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
2944 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
2947 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
2948 doc: /* Return the parameters-alist of frame FRAME.
2949 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2950 The meaningful PARMs depend on the kind of frame.
2951 If FRAME is omitted or nil, return information on the currently selected frame. */)
2952 (Lisp_Object frame)
2954 Lisp_Object alist;
2955 struct frame *f = decode_any_frame (frame);
2956 int height, width;
2958 if (!FRAME_LIVE_P (f))
2959 return Qnil;
2961 alist = Fcopy_alist (f->param_alist);
2963 if (!FRAME_WINDOW_P (f))
2965 Lisp_Object elt;
2967 /* If the frame's parameter alist says the colors are
2968 unspecified and reversed, take the frame's background pixel
2969 for foreground and vice versa. */
2970 elt = Fassq (Qforeground_color, alist);
2971 if (CONSP (elt) && STRINGP (XCDR (elt)))
2973 elt = frame_unspecified_color (f, XCDR (elt));
2974 if (!NILP (elt))
2975 store_in_alist (&alist, Qforeground_color, elt);
2977 else
2978 store_in_alist (&alist, Qforeground_color,
2979 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
2980 elt = Fassq (Qbackground_color, alist);
2981 if (CONSP (elt) && STRINGP (XCDR (elt)))
2983 elt = frame_unspecified_color (f, XCDR (elt));
2984 if (!NILP (elt))
2985 store_in_alist (&alist, Qbackground_color, elt);
2987 else
2988 store_in_alist (&alist, Qbackground_color,
2989 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
2990 store_in_alist (&alist, Qfont,
2991 build_string (FRAME_MSDOS_P (f)
2992 ? "ms-dos"
2993 : FRAME_W32_P (f) ? "w32term"
2994 :"tty"));
2996 store_in_alist (&alist, Qname, f->name);
2997 height = (f->new_height
2998 ? (f->new_pixelwise
2999 ? (f->new_height / FRAME_LINE_HEIGHT (f))
3000 : f->new_height)
3001 : FRAME_LINES (f));
3002 store_in_alist (&alist, Qheight, make_number (height));
3003 width = (f->new_width
3004 ? (f->new_pixelwise
3005 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
3006 : f->new_width)
3007 : FRAME_COLS (f));
3008 store_in_alist (&alist, Qwidth, make_number (width));
3009 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
3010 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
3011 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
3012 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
3014 /* I think this should be done with a hook. */
3015 #ifdef HAVE_WINDOW_SYSTEM
3016 if (FRAME_WINDOW_P (f))
3017 x_report_frame_params (f, &alist);
3018 else
3019 #endif
3021 /* This ought to be correct in f->param_alist for an X frame. */
3022 Lisp_Object lines;
3023 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
3024 store_in_alist (&alist, Qmenu_bar_lines, lines);
3027 return alist;
3031 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
3032 doc: /* Return FRAME's value for parameter PARAMETER.
3033 If FRAME is nil, describe the currently selected frame. */)
3034 (Lisp_Object frame, Lisp_Object parameter)
3036 struct frame *f = decode_any_frame (frame);
3037 Lisp_Object value = Qnil;
3039 CHECK_SYMBOL (parameter);
3041 XSETFRAME (frame, f);
3043 if (FRAME_LIVE_P (f))
3045 /* Avoid consing in frequent cases. */
3046 if (EQ (parameter, Qname))
3047 value = f->name;
3048 #ifdef HAVE_WINDOW_SYSTEM
3049 /* These are used by vertical motion commands. */
3050 else if (EQ (parameter, Qvertical_scroll_bars))
3051 value = (f->vertical_scroll_bar_type == vertical_scroll_bar_none
3052 ? Qnil
3053 : (f->vertical_scroll_bar_type == vertical_scroll_bar_left
3054 ? Qleft : Qright));
3055 else if (EQ (parameter, Qhorizontal_scroll_bars))
3056 value = f->horizontal_scroll_bars ? Qt : Qnil;
3057 else if (EQ (parameter, Qline_spacing) && f->extra_line_spacing == 0)
3058 /* If this is non-zero, we can't determine whether the user specified
3059 an integer or float value without looking through 'param_alist'. */
3060 value = make_number (0);
3061 else if (EQ (parameter, Qfont) && FRAME_X_P (f))
3062 value = FRAME_FONT (f)->props[FONT_NAME_INDEX];
3063 #endif /* HAVE_WINDOW_SYSTEM */
3064 #ifdef HAVE_X_WINDOWS
3065 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
3066 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
3067 #endif /* HAVE_X_WINDOWS */
3068 else if (EQ (parameter, Qbackground_color)
3069 || EQ (parameter, Qforeground_color))
3071 value = Fassq (parameter, f->param_alist);
3072 if (CONSP (value))
3074 value = XCDR (value);
3075 /* Fframe_parameters puts the actual fg/bg color names,
3076 even if f->param_alist says otherwise. This is
3077 important when param_alist's notion of colors is
3078 "unspecified". We need to do the same here. */
3079 if (STRINGP (value) && !FRAME_WINDOW_P (f))
3081 Lisp_Object tem = frame_unspecified_color (f, value);
3083 if (!NILP (tem))
3084 value = tem;
3087 else
3088 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3090 else if (EQ (parameter, Qdisplay_type)
3091 || EQ (parameter, Qbackground_mode))
3092 value = Fcdr (Fassq (parameter, f->param_alist));
3093 else
3094 /* FIXME: Avoid this code path at all (as well as code duplication)
3095 by sharing more code with Fframe_parameters. */
3096 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3099 return value;
3103 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
3104 Smodify_frame_parameters, 2, 2, 0,
3105 doc: /* Modify FRAME according to new values of its parameters in ALIST.
3106 If FRAME is nil, it defaults to the selected frame.
3107 ALIST is an alist of parameters to change and their new values.
3108 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
3109 Which PARMs are meaningful depends on the kind of frame.
3110 The meaningful parameters are acted upon, i.e. the frame is changed
3111 according to their new values, and are also stored in the frame's
3112 parameter list so that `frame-parameters' will return them.
3113 PARMs that are not meaningful are still stored in the frame's parameter
3114 list, but are otherwise ignored. */)
3115 (Lisp_Object frame, Lisp_Object alist)
3117 struct frame *f = decode_live_frame (frame);
3118 Lisp_Object prop, val;
3120 /* I think this should be done with a hook. */
3121 #ifdef HAVE_WINDOW_SYSTEM
3122 if (FRAME_WINDOW_P (f))
3123 x_set_frame_parameters (f, alist);
3124 else
3125 #endif
3126 #ifdef MSDOS
3127 if (FRAME_MSDOS_P (f))
3128 IT_set_frame_parameters (f, alist);
3129 else
3130 #endif
3133 EMACS_INT length = XFASTINT (Flength (alist));
3134 ptrdiff_t i;
3135 Lisp_Object *parms;
3136 Lisp_Object *values;
3137 USE_SAFE_ALLOCA;
3138 SAFE_ALLOCA_LISP (parms, 2 * length);
3139 values = parms + length;
3141 /* Extract parm names and values into those vectors. */
3143 for (i = 0; CONSP (alist); alist = XCDR (alist))
3145 Lisp_Object elt;
3147 elt = XCAR (alist);
3148 parms[i] = Fcar (elt);
3149 values[i] = Fcdr (elt);
3150 i++;
3153 /* Now process them in reverse of specified order. */
3154 while (--i >= 0)
3156 prop = parms[i];
3157 val = values[i];
3158 store_frame_param (f, prop, val);
3160 if (EQ (prop, Qforeground_color)
3161 || EQ (prop, Qbackground_color))
3162 update_face_from_frame_parameter (f, prop, val);
3165 SAFE_FREE ();
3167 return Qnil;
3170 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
3171 0, 1, 0,
3172 doc: /* Height in pixels of a line in the font in frame FRAME.
3173 If FRAME is omitted or nil, the selected frame is used.
3174 For a terminal frame, the value is always 1. */)
3175 (Lisp_Object frame)
3177 #ifdef HAVE_WINDOW_SYSTEM
3178 struct frame *f = decode_any_frame (frame);
3180 if (FRAME_WINDOW_P (f))
3181 return make_number (FRAME_LINE_HEIGHT (f));
3182 else
3183 #endif
3184 return make_number (1);
3188 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
3189 0, 1, 0,
3190 doc: /* Width in pixels of characters in the font in frame FRAME.
3191 If FRAME is omitted or nil, the selected frame is used.
3192 On a graphical screen, the width is the standard width of the default font.
3193 For a terminal screen, the value is always 1. */)
3194 (Lisp_Object frame)
3196 #ifdef HAVE_WINDOW_SYSTEM
3197 struct frame *f = decode_any_frame (frame);
3199 if (FRAME_WINDOW_P (f))
3200 return make_number (FRAME_COLUMN_WIDTH (f));
3201 else
3202 #endif
3203 return make_number (1);
3206 DEFUN ("frame-native-width", Fframe_native_width,
3207 Sframe_native_width, 0, 1, 0,
3208 doc: /* Return FRAME's native width in pixels.
3209 For a terminal frame, the result really gives the width in characters.
3210 If FRAME is omitted or nil, the selected frame is used. */)
3211 (Lisp_Object frame)
3213 struct frame *f = decode_any_frame (frame);
3215 #ifdef HAVE_WINDOW_SYSTEM
3216 if (FRAME_WINDOW_P (f))
3217 return make_number (FRAME_PIXEL_WIDTH (f));
3218 else
3219 #endif
3220 return make_number (FRAME_TOTAL_COLS (f));
3223 DEFUN ("frame-native-height", Fframe_native_height,
3224 Sframe_native_height, 0, 1, 0,
3225 doc: /* Return FRAME's native height in pixels.
3226 If FRAME is omitted or nil, the selected frame is used. The exact value
3227 of the result depends on the window-system and toolkit in use:
3229 In the Gtk+ and NS versions, it includes only any window (including the
3230 minibuffer or echo area), mode line, and header line. It does not
3231 include the tool bar or menu bar. With other graphical versions, it may
3232 also include the tool bar and the menu bar.
3234 For a text terminal, it includes the menu bar. In this case, the
3235 result is really in characters rather than pixels (i.e., is identical
3236 to `frame-height'). */)
3237 (Lisp_Object frame)
3239 struct frame *f = decode_any_frame (frame);
3241 #ifdef HAVE_WINDOW_SYSTEM
3242 if (FRAME_WINDOW_P (f))
3243 return make_number (FRAME_PIXEL_HEIGHT (f));
3244 else
3245 #endif
3246 return make_number (FRAME_TOTAL_LINES (f));
3249 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
3250 Stool_bar_pixel_width, 0, 1, 0,
3251 doc: /* Return width in pixels of FRAME's tool bar.
3252 The result is greater than zero only when the tool bar is on the left
3253 or right side of FRAME. If FRAME is omitted or nil, the selected frame
3254 is used. */)
3255 (Lisp_Object frame)
3257 #ifdef FRAME_TOOLBAR_WIDTH
3258 struct frame *f = decode_any_frame (frame);
3260 if (FRAME_WINDOW_P (f))
3261 return make_number (FRAME_TOOLBAR_WIDTH (f));
3262 #endif
3263 return make_number (0);
3266 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
3267 doc: /* Return width in columns of FRAME's text area. */)
3268 (Lisp_Object frame)
3270 return make_number (FRAME_COLS (decode_any_frame (frame)));
3273 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
3274 doc: /* Return height in lines of FRAME's text area. */)
3275 (Lisp_Object frame)
3277 return make_number (FRAME_LINES (decode_any_frame (frame)));
3280 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
3281 doc: /* Return number of total columns of FRAME. */)
3282 (Lisp_Object frame)
3284 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
3287 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
3288 doc: /* Return number of total lines of FRAME. */)
3289 (Lisp_Object frame)
3291 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
3294 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
3295 doc: /* Return text area width of FRAME in pixels. */)
3296 (Lisp_Object frame)
3298 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
3301 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
3302 doc: /* Return text area height of FRAME in pixels. */)
3303 (Lisp_Object frame)
3305 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
3308 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
3309 doc: /* Return scroll bar width of FRAME in pixels. */)
3310 (Lisp_Object frame)
3312 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
3315 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
3316 doc: /* Return scroll bar height of FRAME in pixels. */)
3317 (Lisp_Object frame)
3319 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
3322 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
3323 doc: /* Return fringe width of FRAME in pixels. */)
3324 (Lisp_Object frame)
3326 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
3329 DEFUN ("frame-internal-border-width", Fframe_internal_border_width, Sframe_internal_border_width, 0, 1, 0,
3330 doc: /* Return width of FRAME's internal border in pixels. */)
3331 (Lisp_Object frame)
3333 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
3336 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
3337 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
3338 (Lisp_Object frame)
3340 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
3343 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
3344 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
3345 (Lisp_Object frame)
3347 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
3350 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
3351 doc: /* Set text height of frame FRAME to HEIGHT lines.
3352 Optional third arg PRETEND non-nil means that redisplay should use
3353 HEIGHT lines but that the idea of the actual height of the frame should
3354 not be changed.
3356 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3357 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
3358 window managers may refuse to honor a HEIGHT that is not an integer
3359 multiple of the default frame font height. */)
3360 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
3362 struct frame *f = decode_live_frame (frame);
3363 int pixel_height;
3365 CHECK_TYPE_RANGED_INTEGER (int, height);
3367 pixel_height = (!NILP (pixelwise)
3368 ? XINT (height)
3369 : XINT (height) * FRAME_LINE_HEIGHT (f));
3370 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
3372 return Qnil;
3375 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
3376 doc: /* Set text width of frame FRAME to WIDTH columns.
3377 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
3378 columns but that the idea of the actual width of the frame should not
3379 be changed.
3381 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3382 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
3383 window managers may refuse to honor a WIDTH that is not an integer
3384 multiple of the default frame font width. */)
3385 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
3387 struct frame *f = decode_live_frame (frame);
3388 int pixel_width;
3390 CHECK_TYPE_RANGED_INTEGER (int, width);
3392 pixel_width = (!NILP (pixelwise)
3393 ? XINT (width)
3394 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3395 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
3397 return Qnil;
3400 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
3401 doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
3402 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
3403 When `frame-resize-pixelwise' is nil, some window managers may refuse to
3404 honor a WIDTH that is not an integer multiple of the default frame font
3405 width or a HEIGHT that is not an integer multiple of the default frame
3406 font height. */)
3407 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
3409 struct frame *f = decode_live_frame (frame);
3410 int pixel_width, pixel_height;
3412 CHECK_TYPE_RANGED_INTEGER (int, width);
3413 CHECK_TYPE_RANGED_INTEGER (int, height);
3415 pixel_width = (!NILP (pixelwise)
3416 ? XINT (width)
3417 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3418 pixel_height = (!NILP (pixelwise)
3419 ? XINT (height)
3420 : XINT (height) * FRAME_LINE_HEIGHT (f));
3421 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
3423 return Qnil;
3426 DEFUN ("frame-position", Fframe_position,
3427 Sframe_position, 0, 1, 0,
3428 doc: /* Return top left corner of FRAME in pixels.
3429 FRAME must be a live frame and defaults to the selected one. The return
3430 value is a cons (x, y) of the coordinates of the top left corner of
3431 FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
3432 display. */)
3433 (Lisp_Object frame)
3435 register struct frame *f = decode_live_frame (frame);
3437 return Fcons (make_number (f->left_pos), make_number (f->top_pos));
3440 DEFUN ("set-frame-position", Fset_frame_position,
3441 Sset_frame_position, 3, 3, 0,
3442 doc: /* Set position of FRAME to (X, Y).
3443 FRAME must be a live frame and defaults to the selected one. X and Y,
3444 if positive, specify the coordinate of the left and top edge of FRAME's
3445 outer frame in pixels relative to an origin (0, 0) of FRAME's display.
3446 If any of X or Y is negative, it specifies the coordinates of the right
3447 or bottom edge of the outer frame of FRAME relative to the right or
3448 bottom edge of FRAME's display. */)
3449 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
3451 struct frame *f = decode_live_frame (frame);
3453 CHECK_TYPE_RANGED_INTEGER (int, x);
3454 CHECK_TYPE_RANGED_INTEGER (int, y);
3456 /* I think this should be done with a hook. */
3457 if (FRAME_WINDOW_P (f))
3459 #ifdef HAVE_WINDOW_SYSTEM
3460 x_set_offset (f, XINT (x), XINT (y), 1);
3461 #endif
3464 return Qt;
3467 /***********************************************************************
3468 Frame Parameters
3469 ***********************************************************************/
3471 /* Connect the frame-parameter names for X frames
3472 to the ways of passing the parameter values to the window system.
3474 The name of a parameter, as a Lisp symbol,
3475 has an `x-frame-parameter' property which is an integer in Lisp
3476 that is an index in this table. */
3478 struct frame_parm_table {
3479 const char *name;
3480 int sym;
3483 static const struct frame_parm_table frame_parms[] =
3485 {"auto-raise", SYMBOL_INDEX (Qauto_raise)},
3486 {"auto-lower", SYMBOL_INDEX (Qauto_lower)},
3487 {"background-color", -1},
3488 {"border-color", SYMBOL_INDEX (Qborder_color)},
3489 {"border-width", SYMBOL_INDEX (Qborder_width)},
3490 {"cursor-color", SYMBOL_INDEX (Qcursor_color)},
3491 {"cursor-type", SYMBOL_INDEX (Qcursor_type)},
3492 {"font", -1},
3493 {"foreground-color", -1},
3494 {"icon-name", SYMBOL_INDEX (Qicon_name)},
3495 {"icon-type", SYMBOL_INDEX (Qicon_type)},
3496 {"internal-border-width", SYMBOL_INDEX (Qinternal_border_width)},
3497 {"right-divider-width", SYMBOL_INDEX (Qright_divider_width)},
3498 {"bottom-divider-width", SYMBOL_INDEX (Qbottom_divider_width)},
3499 {"menu-bar-lines", SYMBOL_INDEX (Qmenu_bar_lines)},
3500 {"mouse-color", SYMBOL_INDEX (Qmouse_color)},
3501 {"name", SYMBOL_INDEX (Qname)},
3502 {"scroll-bar-width", SYMBOL_INDEX (Qscroll_bar_width)},
3503 {"scroll-bar-height", SYMBOL_INDEX (Qscroll_bar_height)},
3504 {"title", SYMBOL_INDEX (Qtitle)},
3505 {"unsplittable", SYMBOL_INDEX (Qunsplittable)},
3506 {"vertical-scroll-bars", SYMBOL_INDEX (Qvertical_scroll_bars)},
3507 {"horizontal-scroll-bars", SYMBOL_INDEX (Qhorizontal_scroll_bars)},
3508 {"visibility", SYMBOL_INDEX (Qvisibility)},
3509 {"tool-bar-lines", SYMBOL_INDEX (Qtool_bar_lines)},
3510 {"scroll-bar-foreground", SYMBOL_INDEX (Qscroll_bar_foreground)},
3511 {"scroll-bar-background", SYMBOL_INDEX (Qscroll_bar_background)},
3512 {"screen-gamma", SYMBOL_INDEX (Qscreen_gamma)},
3513 {"line-spacing", SYMBOL_INDEX (Qline_spacing)},
3514 {"left-fringe", SYMBOL_INDEX (Qleft_fringe)},
3515 {"right-fringe", SYMBOL_INDEX (Qright_fringe)},
3516 {"wait-for-wm", SYMBOL_INDEX (Qwait_for_wm)},
3517 {"fullscreen", SYMBOL_INDEX (Qfullscreen)},
3518 {"font-backend", SYMBOL_INDEX (Qfont_backend)},
3519 {"alpha", SYMBOL_INDEX (Qalpha)},
3520 {"sticky", SYMBOL_INDEX (Qsticky)},
3521 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3522 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3523 {"undecorated", SYMBOL_INDEX (Qundecorated)},
3524 {"parent-frame", SYMBOL_INDEX (Qparent_frame)},
3525 {"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
3526 {"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
3527 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3528 {"z-group", SYMBOL_INDEX (Qz_group)},
3529 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3530 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
3531 #ifdef NS_IMPL_COCOA
3532 {"ns-appearance", SYMBOL_INDEX (Qns_appearance)},
3533 {"ns-transparent-titlebar", SYMBOL_INDEX (Qns_transparent_titlebar)},
3534 #endif
3537 #ifdef HAVE_WINDOW_SYSTEM
3539 /* Enumeration type for switch in frame_float. */
3540 enum frame_float_type
3542 FRAME_FLOAT_WIDTH,
3543 FRAME_FLOAT_HEIGHT,
3544 FRAME_FLOAT_LEFT,
3545 FRAME_FLOAT_TOP
3549 * frame_float:
3551 * Process the value VAL of the float type frame parameter 'width',
3552 * 'height', 'left', or 'top' specified via a frame_float_type
3553 * enumeration type WHAT for frame F. Such parameters relate the outer
3554 * size or position of F to the size of the F's display or parent frame
3555 * which have to be both available in some way.
3557 * The return value is a size or position value in pixels. VAL must be
3558 * in the range 0.0 to 1.0 where a width/height of 0.0 means to return 0
3559 * and 1.0 means to return the full width/height of the display/parent.
3560 * For positions, 0.0 means position in the left/top corner of the
3561 * display/parent while 1.0 means to position at the right/bottom corner
3562 * of the display/parent frame.
3564 * Set PARENT_DONE and OUTER_DONE to avoid recalculation of the outer
3565 * size or parent or display attributes when more float parameters are
3566 * calculated in a row: -1 means not processed yet, 0 means processing
3567 * failed, 1 means processing succeeded.
3569 * Return DEFAULT_VALUE when processing fails for whatever reason with
3570 * one exception: When calculating F's outer edges fails (probably
3571 * because F has not been created yet) return the difference between F's
3572 * native and text size.
3574 static int
3575 frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
3576 int *parent_done, int *outer_done, int default_value)
3578 double d_val = XFLOAT_DATA (val);
3580 if (d_val < 0.0 || d_val > 1.0)
3581 /* Invalid VAL. */
3582 return default_value;
3583 else
3585 static unsigned parent_width, parent_height;
3586 static int parent_left, parent_top;
3587 static unsigned outer_minus_text_width, outer_minus_text_height;
3588 struct frame *p = FRAME_PARENT_FRAME (f);
3590 if (*parent_done == 1)
3592 else if (p)
3594 parent_width = FRAME_PIXEL_WIDTH (p);
3595 parent_height = FRAME_PIXEL_HEIGHT (p);
3596 *parent_done = 1;
3598 else
3600 if (*parent_done == 0)
3601 /* No workarea available. */
3602 return default_value;
3603 else if (*parent_done == -1)
3605 Lisp_Object monitor_attributes;
3606 Lisp_Object workarea;
3607 Lisp_Object frame;
3609 XSETFRAME (frame, f);
3610 monitor_attributes = Fcar (call1 (Qdisplay_monitor_attributes_list, frame));
3611 if (NILP (monitor_attributes))
3613 /* No monitor attributes available. */
3614 *parent_done = 0;
3616 return default_value;
3619 workarea = Fcdr (Fassq (Qworkarea, monitor_attributes));
3620 if (NILP (workarea))
3622 /* No workarea available. */
3623 *parent_done = 0;
3625 return default_value;
3628 /* Workarea available. */
3629 parent_left = XINT (Fnth (make_number (0), workarea));
3630 parent_top = XINT (Fnth (make_number (1), workarea));
3631 parent_width = XINT (Fnth (make_number (2), workarea));
3632 parent_height = XINT (Fnth (make_number (3), workarea));
3633 *parent_done = 1;
3637 if (*outer_done == 1)
3639 else if (FRAME_UNDECORATED (f))
3641 outer_minus_text_width
3642 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3643 outer_minus_text_height
3644 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3645 *outer_done = 1;
3647 else if (*outer_done == 0)
3648 /* No outer size available. */
3649 return default_value;
3650 else if (*outer_done == -1)
3652 Lisp_Object frame, outer_edges;
3654 XSETFRAME (frame, f);
3655 outer_edges = call2 (Qframe_edges, frame, Qouter_edges);
3657 if (!NILP (outer_edges))
3659 outer_minus_text_width
3660 = (XINT (Fnth (make_number (2), outer_edges))
3661 - XINT (Fnth (make_number (0), outer_edges))
3662 - FRAME_TEXT_WIDTH (f));
3663 outer_minus_text_height
3664 = (XINT (Fnth (make_number (3), outer_edges))
3665 - XINT (Fnth (make_number (1), outer_edges))
3666 - FRAME_TEXT_HEIGHT (f));
3668 else
3670 /* If we can't get any outer edges, proceed as if the frame
3671 were undecorated. */
3672 outer_minus_text_width
3673 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3674 outer_minus_text_height
3675 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3678 *outer_done = 1;
3681 switch (what)
3683 case FRAME_FLOAT_WIDTH:
3684 return parent_width * d_val - outer_minus_text_width;
3686 case FRAME_FLOAT_HEIGHT:
3687 return parent_height * d_val - outer_minus_text_height;
3689 case FRAME_FLOAT_LEFT:
3691 int rest_width = (parent_width
3692 - FRAME_TEXT_WIDTH (f)
3693 - outer_minus_text_width);
3695 if (p)
3696 return (rest_width <= 0 ? 0 : d_val * rest_width);
3697 else
3698 return (rest_width <= 0
3699 ? parent_left
3700 : parent_left + d_val * rest_width);
3702 case FRAME_FLOAT_TOP:
3704 int rest_height = (parent_height
3705 - FRAME_TEXT_HEIGHT (f)
3706 - outer_minus_text_height);
3708 if (p)
3709 return (rest_height <= 0 ? 0 : d_val * rest_height);
3710 else
3711 return (rest_height <= 0
3712 ? parent_top
3713 : parent_top + d_val * rest_height);
3715 default:
3716 emacs_abort ();
3721 /* Change the parameters of frame F as specified by ALIST.
3722 If a parameter is not specially recognized, do nothing special;
3723 otherwise call the `x_set_...' function for that parameter.
3724 Except for certain geometry properties, always call store_frame_param
3725 to store the new value in the parameter alist. */
3727 void
3728 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3730 Lisp_Object tail, frame;
3733 /* If both of these parameters are present, it's more efficient to
3734 set them both at once. So we wait until we've looked at the
3735 entire list before we set them. */
3736 int width = -1, height = -1; /* -1 denotes they were not changed. */
3738 /* Same here. */
3739 Lisp_Object left, top;
3741 /* Same with these. */
3742 Lisp_Object icon_left, icon_top;
3744 /* And with this. */
3745 Lisp_Object fullscreen;
3746 bool fullscreen_change = false;
3748 /* Record in these vectors all the parms specified. */
3749 Lisp_Object *parms;
3750 Lisp_Object *values;
3751 ptrdiff_t i, j, size;
3752 bool left_no_change = 0, top_no_change = 0;
3753 #ifdef HAVE_X_WINDOWS
3754 bool icon_left_no_change = 0, icon_top_no_change = 0;
3755 #endif
3756 int parent_done = -1, outer_done = -1;
3758 XSETFRAME (frame, f);
3759 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
3760 size++;
3761 CHECK_LIST_END (tail, alist);
3763 USE_SAFE_ALLOCA;
3764 SAFE_ALLOCA_LISP (parms, 2 * size);
3765 values = parms + size;
3767 /* Extract parm names and values into those vectors. */
3769 i = 0, j = size - 1;
3770 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3772 Lisp_Object elt = XCAR (tail), prop = Fcar (elt), val = Fcdr (elt);
3774 /* Some properties are independent of other properties, but other
3775 properties are dependent upon them. These special properties
3776 are foreground_color, background_color (affects cursor_color)
3777 and font (affects fringe widths); they're recorded starting
3778 from the end of PARMS and VALUES to process them first by using
3779 reverse iteration. */
3781 if (EQ (prop, Qforeground_color)
3782 || EQ (prop, Qbackground_color)
3783 || EQ (prop, Qfont))
3785 parms[j] = prop;
3786 values[j] = val;
3787 j--;
3789 else
3791 parms[i] = prop;
3792 values[i] = val;
3793 i++;
3797 /* TAIL and ALIST are not used again below here. */
3798 alist = tail = Qnil;
3800 top = left = Qunbound;
3801 icon_left = icon_top = Qunbound;
3803 /* Reverse order is used to make sure that special
3804 properties noticed above are processed first. */
3805 for (i = size - 1; i >= 0; i--)
3807 Lisp_Object prop, val;
3809 prop = parms[i];
3810 val = values[i];
3812 if (EQ (prop, Qwidth))
3814 if (RANGED_INTEGERP (0, val, INT_MAX))
3815 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3816 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3817 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3818 width = XFASTINT (XCDR (val));
3819 else if (FLOATP (val))
3820 width = frame_float (f, val, FRAME_FLOAT_WIDTH, &parent_done,
3821 &outer_done, -1);
3823 else if (EQ (prop, Qheight))
3825 if (RANGED_INTEGERP (0, val, INT_MAX))
3826 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3827 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3828 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3829 height = XFASTINT (XCDR (val));
3830 else if (FLOATP (val))
3831 height = frame_float (f, val, FRAME_FLOAT_HEIGHT, &parent_done,
3832 &outer_done, -1);
3834 else if (EQ (prop, Qtop))
3835 top = val;
3836 else if (EQ (prop, Qleft))
3837 left = val;
3838 else if (EQ (prop, Qicon_top))
3839 icon_top = val;
3840 else if (EQ (prop, Qicon_left))
3841 icon_left = val;
3842 else if (EQ (prop, Qfullscreen))
3844 fullscreen = val;
3845 fullscreen_change = true;
3847 else
3849 register Lisp_Object param_index, old_value;
3851 old_value = get_frame_param (f, prop);
3853 store_frame_param (f, prop, val);
3855 param_index = Fget (prop, Qx_frame_parameter);
3856 if (NATNUMP (param_index)
3857 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3858 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3859 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3863 /* Don't die if just one of these was set. */
3864 if (EQ (left, Qunbound))
3866 left_no_change = 1;
3867 if (f->left_pos < 0)
3868 left = list2 (Qplus, make_number (f->left_pos));
3869 else
3870 XSETINT (left, f->left_pos);
3872 if (EQ (top, Qunbound))
3874 top_no_change = 1;
3875 if (f->top_pos < 0)
3876 top = list2 (Qplus, make_number (f->top_pos));
3877 else
3878 XSETINT (top, f->top_pos);
3881 /* If one of the icon positions was not set, preserve or default it. */
3882 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3884 #ifdef HAVE_X_WINDOWS
3885 icon_left_no_change = 1;
3886 #endif
3887 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3888 if (NILP (icon_left))
3889 XSETINT (icon_left, 0);
3891 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3893 #ifdef HAVE_X_WINDOWS
3894 icon_top_no_change = 1;
3895 #endif
3896 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3897 if (NILP (icon_top))
3898 XSETINT (icon_top, 0);
3901 /* Don't set these parameters unless they've been explicitly
3902 specified. The window might be mapped or resized while we're in
3903 this function, and we don't want to override that unless the lisp
3904 code has asked for it.
3906 Don't set these parameters unless they actually differ from the
3907 window's current parameters; the window may not actually exist
3908 yet. */
3909 if ((width != -1 && width != FRAME_TEXT_WIDTH (f))
3910 || (height != -1 && height != FRAME_TEXT_HEIGHT (f)))
3911 /* We could consider checking f->after_make_frame here, but I
3912 don't have the faintest idea why the following is needed at
3913 all. With the old setting it can get a Heisenbug when
3914 EmacsFrameResize intermittently provokes a delayed
3915 change_frame_size in the middle of adjust_frame_size. */
3916 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
3917 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters);
3919 if ((!NILP (left) || !NILP (top))
3920 && ! (left_no_change && top_no_change)
3921 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3922 && NUMBERP (top) && XINT (top) == f->top_pos))
3924 int leftpos = 0;
3925 int toppos = 0;
3927 /* Record the signs. */
3928 f->size_hint_flags &= ~ (XNegative | YNegative);
3929 if (EQ (left, Qminus))
3930 f->size_hint_flags |= XNegative;
3931 else if (TYPE_RANGED_INTEGERP (int, left))
3933 leftpos = XINT (left);
3934 if (leftpos < 0)
3935 f->size_hint_flags |= XNegative;
3937 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3938 && CONSP (XCDR (left))
3939 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3941 leftpos = - XINT (XCAR (XCDR (left)));
3942 f->size_hint_flags |= XNegative;
3944 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3945 && CONSP (XCDR (left))
3946 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3947 leftpos = XINT (XCAR (XCDR (left)));
3948 else if (FLOATP (left))
3949 leftpos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
3950 &outer_done, 0);
3952 if (EQ (top, Qminus))
3953 f->size_hint_flags |= YNegative;
3954 else if (TYPE_RANGED_INTEGERP (int, top))
3956 toppos = XINT (top);
3957 if (toppos < 0)
3958 f->size_hint_flags |= YNegative;
3960 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3961 && CONSP (XCDR (top))
3962 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3964 toppos = - XINT (XCAR (XCDR (top)));
3965 f->size_hint_flags |= YNegative;
3967 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3968 && CONSP (XCDR (top))
3969 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
3970 toppos = XINT (XCAR (XCDR (top)));
3971 else if (FLOATP (top))
3972 toppos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
3973 &outer_done, 0);
3975 /* Store the numeric value of the position. */
3976 f->top_pos = toppos;
3977 f->left_pos = leftpos;
3979 f->win_gravity = NorthWestGravity;
3981 /* Actually set that position, and convert to absolute. */
3982 x_set_offset (f, leftpos, toppos, -1);
3985 if (fullscreen_change)
3987 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
3989 frame_size_history_add
3990 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
3992 store_frame_param (f, Qfullscreen, fullscreen);
3993 if (!EQ (fullscreen, old_value))
3994 x_set_fullscreen (f, fullscreen, old_value);
3998 #ifdef HAVE_X_WINDOWS
3999 if ((!NILP (icon_left) || !NILP (icon_top))
4000 && ! (icon_left_no_change && icon_top_no_change))
4001 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
4002 #endif /* HAVE_X_WINDOWS */
4004 SAFE_FREE ();
4008 /* Insert a description of internally-recorded parameters of frame X
4009 into the parameter alist *ALISTPTR that is to be given to the user.
4010 Only parameters that are specific to the X window system
4011 and whose values are not correctly recorded in the frame's
4012 param_alist need to be considered here. */
4014 void
4015 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
4017 Lisp_Object tem;
4018 uprintmax_t w;
4019 char buf[INT_BUFSIZE_BOUND (w)];
4021 /* Represent negative positions (off the top or left screen edge)
4022 in a way that Fmodify_frame_parameters will understand correctly. */
4023 XSETINT (tem, f->left_pos);
4024 if (f->left_pos >= 0)
4025 store_in_alist (alistptr, Qleft, tem);
4026 else
4027 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
4029 XSETINT (tem, f->top_pos);
4030 if (f->top_pos >= 0)
4031 store_in_alist (alistptr, Qtop, tem);
4032 else
4033 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
4035 store_in_alist (alistptr, Qborder_width,
4036 make_number (f->border_width));
4037 store_in_alist (alistptr, Qinternal_border_width,
4038 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
4039 store_in_alist (alistptr, Qright_divider_width,
4040 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
4041 store_in_alist (alistptr, Qbottom_divider_width,
4042 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
4043 store_in_alist (alistptr, Qleft_fringe,
4044 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
4045 store_in_alist (alistptr, Qright_fringe,
4046 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
4047 store_in_alist (alistptr, Qscroll_bar_width,
4048 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4049 ? make_number (0)
4050 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
4051 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4052 /* nil means "use default width"
4053 for non-toolkit scroll bar.
4054 ruler-mode.el depends on this. */
4055 : Qnil));
4056 store_in_alist (alistptr, Qscroll_bar_height,
4057 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
4058 ? make_number (0)
4059 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
4060 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4061 /* nil means "use default height"
4062 for non-toolkit scroll bar. */
4063 : Qnil));
4064 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
4065 MS-Windows it returns a value whose type is HANDLE, which is
4066 actually a pointer. Explicit casting avoids compiler
4067 warnings. */
4068 w = (uintptr_t) FRAME_X_WINDOW (f);
4069 store_in_alist (alistptr, Qwindow_id,
4070 make_formatted_string (buf, "%"pMu, w));
4071 #ifdef HAVE_X_WINDOWS
4072 #ifdef USE_X_TOOLKIT
4073 /* Tooltip frame may not have this widget. */
4074 if (FRAME_X_OUTPUT (f)->widget)
4075 #endif
4076 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
4077 store_in_alist (alistptr, Qouter_window_id,
4078 make_formatted_string (buf, "%"pMu, w));
4079 #endif
4080 store_in_alist (alistptr, Qicon_name, f->icon_name);
4081 store_in_alist (alistptr, Qvisibility,
4082 (FRAME_VISIBLE_P (f) ? Qt
4083 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
4084 store_in_alist (alistptr, Qdisplay,
4085 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
4087 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
4088 tem = Qnil;
4089 else
4090 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
4091 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
4092 store_in_alist (alistptr, Qparent_id, tem);
4093 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
4097 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
4098 the previous value of that parameter, NEW_VALUE is the new value. */
4100 void
4101 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4103 if (NILP (new_value))
4104 f->want_fullscreen = FULLSCREEN_NONE;
4105 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
4106 f->want_fullscreen = FULLSCREEN_BOTH;
4107 else if (EQ (new_value, Qfullwidth))
4108 f->want_fullscreen = FULLSCREEN_WIDTH;
4109 else if (EQ (new_value, Qfullheight))
4110 f->want_fullscreen = FULLSCREEN_HEIGHT;
4111 else if (EQ (new_value, Qmaximized))
4112 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
4114 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
4115 FRAME_TERMINAL (f)->fullscreen_hook (f);
4119 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
4120 the previous value of that parameter, NEW_VALUE is the new value. */
4122 void
4123 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4125 if (NILP (new_value))
4126 f->extra_line_spacing = 0;
4127 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
4128 f->extra_line_spacing = XFASTINT (new_value);
4129 else if (FLOATP (new_value))
4131 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
4133 if (new_spacing >= 0)
4134 f->extra_line_spacing = new_spacing;
4135 else
4136 signal_error ("Invalid line-spacing", new_value);
4138 else
4139 signal_error ("Invalid line-spacing", new_value);
4140 if (FRAME_VISIBLE_P (f))
4141 redraw_frame (f);
4145 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
4146 the previous value of that parameter, NEW_VALUE is the new value. */
4148 void
4149 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4151 Lisp_Object bgcolor;
4153 if (NILP (new_value))
4154 f->gamma = 0;
4155 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
4156 /* The value 0.4545 is the normal viewing gamma. */
4157 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
4158 else
4159 signal_error ("Invalid screen-gamma", new_value);
4161 /* Apply the new gamma value to the frame background. */
4162 bgcolor = Fassq (Qbackground_color, f->param_alist);
4163 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
4165 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
4166 if (NATNUMP (parm_index)
4167 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
4168 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4169 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4170 (f, bgcolor, Qnil);
4173 clear_face_cache (true); /* FIXME: Why of all frames? */
4174 fset_redisplay (f);
4178 void
4179 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4181 Lisp_Object font_object;
4182 int fontset = -1;
4183 #ifdef HAVE_X_WINDOWS
4184 Lisp_Object font_param = arg;
4185 #endif
4187 /* Set the frame parameter back to the old value because we may
4188 fail to use ARG as the new parameter value. */
4189 store_frame_param (f, Qfont, oldval);
4191 /* ARG is a fontset name, a font name, a cons of fontset name and a
4192 font object, or a font object. In the last case, this function
4193 never fail. */
4194 if (STRINGP (arg))
4196 fontset = fs_query_fontset (arg, 0);
4197 if (fontset < 0)
4199 font_object = font_open_by_name (f, arg);
4200 if (NILP (font_object))
4201 error ("Font `%s' is not defined", SSDATA (arg));
4202 arg = AREF (font_object, FONT_NAME_INDEX);
4204 else if (fontset > 0)
4206 font_object = font_open_by_name (f, fontset_ascii (fontset));
4207 if (NILP (font_object))
4208 error ("Font `%s' is not defined", SDATA (arg));
4209 arg = AREF (font_object, FONT_NAME_INDEX);
4211 else
4212 error ("The default fontset can't be used for a frame font");
4214 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
4216 /* This is the case that the ASCII font of F's fontset XCAR
4217 (arg) is changed to the font XCDR (arg) by
4218 `set-fontset-font'. */
4219 fontset = fs_query_fontset (XCAR (arg), 0);
4220 if (fontset < 0)
4221 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
4222 font_object = XCDR (arg);
4223 arg = AREF (font_object, FONT_NAME_INDEX);
4224 #ifdef HAVE_X_WINDOWS
4225 font_param = Ffont_get (font_object, QCname);
4226 #endif
4228 else if (FONT_OBJECT_P (arg))
4230 font_object = arg;
4231 #ifdef HAVE_X_WINDOWS
4232 font_param = Ffont_get (font_object, QCname);
4233 #endif
4234 /* This is to store the XLFD font name in the frame parameter for
4235 backward compatibility. We should store the font-object
4236 itself in the future. */
4237 arg = AREF (font_object, FONT_NAME_INDEX);
4238 fontset = FRAME_FONTSET (f);
4239 /* Check if we can use the current fontset. If not, set FONTSET
4240 to -1 to generate a new fontset from FONT-OBJECT. */
4241 if (fontset >= 0)
4243 Lisp_Object ascii_font = fontset_ascii (fontset);
4244 Lisp_Object spec = font_spec_from_name (ascii_font);
4246 /* SPEC might be nil because ASCII_FONT's name doesn't parse
4247 according to stupid XLFD rules, which, for example,
4248 disallow font names that include a dash followed by a
4249 number. So in those cases we simply request x_new_font
4250 below to generate a new fontset. */
4251 if (NILP (spec) || ! font_match_p (spec, font_object))
4252 fontset = -1;
4255 else
4256 signal_error ("Invalid font", arg);
4258 if (! NILP (Fequal (font_object, oldval)))
4259 return;
4261 x_new_font (f, font_object, fontset);
4262 store_frame_param (f, Qfont, arg);
4263 #ifdef HAVE_X_WINDOWS
4264 store_frame_param (f, Qfont_parameter, font_param);
4265 #endif
4266 /* Recalculate toolbar height. */
4267 f->n_tool_bar_rows = 0;
4269 /* Ensure we redraw it. */
4270 clear_current_matrices (f);
4272 /* Attempt to hunt down bug#16028. */
4273 SET_FRAME_GARBAGED (f);
4275 /* This is important if we are called by some Lisp as part of
4276 redisplaying the frame, see redisplay_internal. */
4277 f->fonts_changed = true;
4279 recompute_basic_faces (f);
4281 do_pending_window_change (0);
4283 /* We used to call face-set-after-frame-default here, but it leads to
4284 recursive calls (since that function can set the `default' face's
4285 font which in turns changes the frame's `font' parameter).
4286 Also I don't know what this call is meant to do, but it seems the
4287 wrong way to do it anyway (it does a lot more work than what seems
4288 reasonable in response to a change to `font'). */
4292 void
4293 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4295 if (! NILP (new_value)
4296 && !CONSP (new_value))
4298 char *p0, *p1;
4300 CHECK_STRING (new_value);
4301 p0 = p1 = SSDATA (new_value);
4302 new_value = Qnil;
4303 while (*p0)
4305 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
4306 if (p0 < p1)
4307 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
4308 new_value);
4309 if (*p1)
4311 int c;
4313 while ((c = *++p1) && c_isspace (c));
4315 p0 = p1;
4317 new_value = Fnreverse (new_value);
4320 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
4321 return;
4323 if (FRAME_FONT (f))
4324 free_all_realized_faces (Qnil);
4326 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
4327 if (NILP (new_value))
4329 if (NILP (old_value))
4330 error ("No font backend available");
4331 font_update_drivers (f, old_value);
4332 error ("None of specified font backends are available");
4334 store_frame_param (f, Qfont_backend, new_value);
4336 if (FRAME_FONT (f))
4338 Lisp_Object frame;
4340 XSETFRAME (frame, f);
4341 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
4342 face_change = true;
4343 windows_or_buffers_changed = 18;
4347 void
4348 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4350 int unit = FRAME_COLUMN_WIDTH (f);
4351 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
4352 int new_width;
4354 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4355 ? eabs (XINT (new_value)) : 8);
4357 if (new_width != old_width)
4359 f->left_fringe_width = new_width;
4360 f->fringe_cols /* Round up. */
4361 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
4363 if (FRAME_X_WINDOW (f) != 0)
4364 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
4366 SET_FRAME_GARBAGED (f);
4371 void
4372 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4374 int unit = FRAME_COLUMN_WIDTH (f);
4375 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
4376 int new_width;
4378 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4379 ? eabs (XINT (new_value)) : 8);
4381 if (new_width != old_width)
4383 f->right_fringe_width = new_width;
4384 f->fringe_cols /* Round up. */
4385 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
4387 if (FRAME_X_WINDOW (f) != 0)
4388 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
4390 SET_FRAME_GARBAGED (f);
4395 void
4396 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4398 CHECK_TYPE_RANGED_INTEGER (int, arg);
4400 if (XINT (arg) == f->border_width)
4401 return;
4403 if (FRAME_X_WINDOW (f) != 0)
4404 error ("Cannot change the border width of a frame");
4406 f->border_width = XINT (arg);
4409 void
4410 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4412 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
4413 CHECK_TYPE_RANGED_INTEGER (int, arg);
4414 int new = max (0, XINT (arg));
4415 if (new != old)
4417 f->right_divider_width = new;
4418 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
4419 adjust_frame_glyphs (f);
4420 SET_FRAME_GARBAGED (f);
4424 void
4425 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4427 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
4428 CHECK_TYPE_RANGED_INTEGER (int, arg);
4429 int new = max (0, XINT (arg));
4430 if (new != old)
4432 f->bottom_divider_width = new;
4433 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
4434 adjust_frame_glyphs (f);
4435 SET_FRAME_GARBAGED (f);
4439 void
4440 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
4442 Lisp_Object frame;
4443 XSETFRAME (frame, f);
4445 if (NILP (value))
4446 Fmake_frame_invisible (frame, Qt);
4447 else if (EQ (value, Qicon))
4448 Ficonify_frame (frame);
4449 else
4450 Fmake_frame_visible (frame);
4453 void
4454 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4456 f->auto_raise = !EQ (Qnil, arg);
4459 void
4460 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4462 f->auto_lower = !EQ (Qnil, arg);
4465 void
4466 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4468 f->no_split = !NILP (arg);
4471 void
4472 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4474 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4475 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
4476 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4477 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
4479 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
4480 = (NILP (arg)
4481 ? vertical_scroll_bar_none
4482 : EQ (Qleft, arg)
4483 ? vertical_scroll_bar_left
4484 : EQ (Qright, arg)
4485 ? vertical_scroll_bar_right
4486 : EQ (Qleft, Vdefault_frame_scroll_bars)
4487 ? vertical_scroll_bar_left
4488 : EQ (Qright, Vdefault_frame_scroll_bars)
4489 ? vertical_scroll_bar_right
4490 : vertical_scroll_bar_none);
4492 /* We set this parameter before creating the X window for the
4493 frame, so we can get the geometry right from the start.
4494 However, if the window hasn't been created yet, we shouldn't
4495 call x_set_window_size. */
4496 if (FRAME_X_WINDOW (f))
4497 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
4499 SET_FRAME_GARBAGED (f);
4503 void
4504 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4506 #if USE_HORIZONTAL_SCROLL_BARS
4507 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
4508 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
4510 f->horizontal_scroll_bars = NILP (arg) ? false : true;
4512 /* We set this parameter before creating the X window for the
4513 frame, so we can get the geometry right from the start.
4514 However, if the window hasn't been created yet, we shouldn't
4515 call x_set_window_size. */
4516 if (FRAME_X_WINDOW (f))
4517 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
4519 SET_FRAME_GARBAGED (f);
4521 #endif
4524 void
4525 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4527 int unit = FRAME_COLUMN_WIDTH (f);
4529 if (NILP (arg))
4531 x_set_scroll_bar_default_width (f);
4533 if (FRAME_X_WINDOW (f))
4534 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4536 SET_FRAME_GARBAGED (f);
4538 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4539 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4541 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
4542 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
4543 if (FRAME_X_WINDOW (f))
4544 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4546 SET_FRAME_GARBAGED (f);
4549 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
4550 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
4553 void
4554 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4556 #if USE_HORIZONTAL_SCROLL_BARS
4557 int unit = FRAME_LINE_HEIGHT (f);
4559 if (NILP (arg))
4561 x_set_scroll_bar_default_height (f);
4563 if (FRAME_X_WINDOW (f))
4564 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4566 SET_FRAME_GARBAGED (f);
4568 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4569 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4571 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
4572 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
4573 if (FRAME_X_WINDOW (f))
4574 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4576 SET_FRAME_GARBAGED (f);
4579 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
4580 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
4581 #endif
4584 void
4585 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4587 double alpha = 1.0;
4588 double newval[2];
4589 int i;
4590 Lisp_Object item;
4592 for (i = 0; i < 2; i++)
4594 newval[i] = 1.0;
4595 if (CONSP (arg))
4597 item = CAR (arg);
4598 arg = CDR (arg);
4600 else
4601 item = arg;
4603 if (NILP (item))
4604 alpha = - 1.0;
4605 else if (FLOATP (item))
4607 alpha = XFLOAT_DATA (item);
4608 if (! (0 <= alpha && alpha <= 1.0))
4609 args_out_of_range (make_float (0.0), make_float (1.0));
4611 else if (INTEGERP (item))
4613 EMACS_INT ialpha = XINT (item);
4614 if (! (0 <= ialpha && ialpha <= 100))
4615 args_out_of_range (make_number (0), make_number (100));
4616 alpha = ialpha / 100.0;
4618 else
4619 wrong_type_argument (Qnumberp, item);
4620 newval[i] = alpha;
4623 for (i = 0; i < 2; i++)
4624 f->alpha[i] = newval[i];
4626 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
4627 block_input ();
4628 x_set_frame_alpha (f);
4629 unblock_input ();
4630 #endif
4632 return;
4637 * x_set_no_special_glyphs:
4639 * Set frame F's `no-special-glyphs' parameter which, if non-nil,
4640 * suppresses the display of truncation and continuation glyphs
4641 * outside fringes.
4643 void
4644 x_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4646 if (!EQ (new_value, old_value))
4647 FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (new_value);
4651 #ifndef HAVE_NS
4653 /* Non-zero if mouse is grabbed on DPYINFO
4654 and we know the frame where it is. */
4656 bool x_mouse_grabbed (Display_Info *dpyinfo)
4658 return (dpyinfo->grabbed
4659 && dpyinfo->last_mouse_frame
4660 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
4663 /* Re-highlight something with mouse-face properties
4664 on DPYINFO using saved frame and mouse position. */
4666 void
4667 x_redo_mouse_highlight (Display_Info *dpyinfo)
4669 if (dpyinfo->last_mouse_motion_frame
4670 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
4671 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
4672 dpyinfo->last_mouse_motion_x,
4673 dpyinfo->last_mouse_motion_y);
4676 #endif /* HAVE_NS */
4678 /* Subroutines of creating an X frame. */
4680 /* Make sure that Vx_resource_name is set to a reasonable value.
4681 Fix it up, or set it to `emacs' if it is too hopeless. */
4683 void
4684 validate_x_resource_name (void)
4686 ptrdiff_t len = 0;
4687 /* Number of valid characters in the resource name. */
4688 ptrdiff_t good_count = 0;
4689 /* Number of invalid characters in the resource name. */
4690 ptrdiff_t bad_count = 0;
4691 Lisp_Object new;
4692 ptrdiff_t i;
4694 if (!STRINGP (Vx_resource_class))
4695 Vx_resource_class = build_string (EMACS_CLASS);
4697 if (STRINGP (Vx_resource_name))
4699 unsigned char *p = SDATA (Vx_resource_name);
4701 len = SBYTES (Vx_resource_name);
4703 /* Only letters, digits, - and _ are valid in resource names.
4704 Count the valid characters and count the invalid ones. */
4705 for (i = 0; i < len; i++)
4707 int c = p[i];
4708 if (! ((c >= 'a' && c <= 'z')
4709 || (c >= 'A' && c <= 'Z')
4710 || (c >= '0' && c <= '9')
4711 || c == '-' || c == '_'))
4712 bad_count++;
4713 else
4714 good_count++;
4717 else
4718 /* Not a string => completely invalid. */
4719 bad_count = 5, good_count = 0;
4721 /* If name is valid already, return. */
4722 if (bad_count == 0)
4723 return;
4725 /* If name is entirely invalid, or nearly so, or is so implausibly
4726 large that alloca might not work, use `emacs'. */
4727 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
4729 Vx_resource_name = build_string ("emacs");
4730 return;
4733 /* Name is partly valid. Copy it and replace the invalid characters
4734 with underscores. */
4736 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
4738 for (i = 0; i < len; i++)
4740 int c = SREF (new, i);
4741 if (! ((c >= 'a' && c <= 'z')
4742 || (c >= 'A' && c <= 'Z')
4743 || (c >= '0' && c <= '9')
4744 || c == '-' || c == '_'))
4745 SSET (new, i, '_');
4749 /* Get specified attribute from resource database RDB.
4750 See Fx_get_resource below for other parameters. */
4752 static Lisp_Object
4753 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
4755 CHECK_STRING (attribute);
4756 CHECK_STRING (class);
4758 if (!NILP (component))
4759 CHECK_STRING (component);
4760 if (!NILP (subclass))
4761 CHECK_STRING (subclass);
4762 if (NILP (component) != NILP (subclass))
4763 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
4765 validate_x_resource_name ();
4767 /* Allocate space for the components, the dots which separate them,
4768 and the final '\0'. Make them big enough for the worst case. */
4769 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4770 + (STRINGP (component)
4771 ? SBYTES (component) : 0)
4772 + SBYTES (attribute)
4773 + 3);
4775 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4776 + SBYTES (class)
4777 + (STRINGP (subclass)
4778 ? SBYTES (subclass) : 0)
4779 + 3);
4780 USE_SAFE_ALLOCA;
4781 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4782 char *class_key = name_key + name_keysize;
4784 /* Start with emacs.FRAMENAME for the name (the specific one)
4785 and with `Emacs' for the class key (the general one). */
4786 char *nz = lispstpcpy (name_key, Vx_resource_name);
4787 char *cz = lispstpcpy (class_key, Vx_resource_class);
4789 *cz++ = '.';
4790 cz = lispstpcpy (cz, class);
4792 if (!NILP (component))
4794 *cz++ = '.';
4795 lispstpcpy (cz, subclass);
4797 *nz++ = '.';
4798 nz = lispstpcpy (nz, component);
4801 *nz++ = '.';
4802 lispstpcpy (nz, attribute);
4804 char *value = x_get_string_resource (rdb, name_key, class_key);
4805 SAFE_FREE();
4807 if (value && *value)
4808 return build_string (value);
4809 else
4810 return Qnil;
4814 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4815 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4816 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4817 class, where INSTANCE is the name under which Emacs was invoked, or
4818 the name specified by the `-name' or `-rn' command-line arguments.
4820 The optional arguments COMPONENT and SUBCLASS add to the key and the
4821 class, respectively. You must specify both of them or neither.
4822 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4823 and the class is `Emacs.CLASS.SUBCLASS'. */)
4824 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4825 Lisp_Object subclass)
4827 check_window_system (NULL);
4829 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4830 attribute, class, component, subclass);
4833 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4835 Lisp_Object
4836 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4837 Lisp_Object class, Lisp_Object component,
4838 Lisp_Object subclass)
4840 return xrdb_get_resource (dpyinfo->xrdb,
4841 attribute, class, component, subclass);
4844 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
4845 /* Used when C code wants a resource value. */
4846 /* Called from oldXMenu/Create.c. */
4847 char *
4848 x_get_resource_string (const char *attribute, const char *class)
4850 char *result;
4851 struct frame *sf = SELECTED_FRAME ();
4852 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4853 USE_SAFE_ALLOCA;
4855 /* Allocate space for the components, the dots which separate them,
4856 and the final '\0'. */
4857 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4858 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4859 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4860 char *class_key = name_key + name_keysize;
4862 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4863 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4865 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4866 name_key, class_key);
4867 SAFE_FREE ();
4868 return result;
4870 #endif
4872 /* Return the value of parameter PARAM.
4874 First search ALIST, then Vdefault_frame_alist, then the X defaults
4875 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4877 Convert the resource to the type specified by desired_type.
4879 If no default is specified, return Qunbound. If you call
4880 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4881 and don't let it get stored in any Lisp-visible variables! */
4883 Lisp_Object
4884 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4885 const char *attribute, const char *class, enum resource_types type)
4887 Lisp_Object tem;
4889 tem = Fassq (param, alist);
4891 if (!NILP (tem))
4893 /* If we find this parm in ALIST, clear it out
4894 so that it won't be "left over" at the end. */
4895 Lisp_Object tail;
4896 XSETCAR (tem, Qnil);
4897 /* In case the parameter appears more than once in the alist,
4898 clear it out. */
4899 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4900 if (CONSP (XCAR (tail))
4901 && EQ (XCAR (XCAR (tail)), param))
4902 XSETCAR (XCAR (tail), Qnil);
4904 else
4905 tem = Fassq (param, Vdefault_frame_alist);
4907 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4908 look in the X resources. */
4909 if (EQ (tem, Qnil))
4911 if (attribute && dpyinfo)
4913 AUTO_STRING (at, attribute);
4914 AUTO_STRING (cl, class);
4915 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4917 if (NILP (tem))
4918 return Qunbound;
4920 switch (type)
4922 case RES_TYPE_NUMBER:
4923 return make_number (atoi (SSDATA (tem)));
4925 case RES_TYPE_BOOLEAN_NUMBER:
4926 if (!strcmp (SSDATA (tem), "on")
4927 || !strcmp (SSDATA (tem), "true"))
4928 return make_number (1);
4929 return make_number (atoi (SSDATA (tem)));
4930 break;
4932 case RES_TYPE_FLOAT:
4933 return make_float (atof (SSDATA (tem)));
4935 case RES_TYPE_BOOLEAN:
4936 tem = Fdowncase (tem);
4937 if (!strcmp (SSDATA (tem), "on")
4938 #ifdef HAVE_NS
4939 || !strcmp (SSDATA (tem), "yes")
4940 #endif
4941 || !strcmp (SSDATA (tem), "true"))
4942 return Qt;
4943 else
4944 return Qnil;
4946 case RES_TYPE_STRING:
4947 return tem;
4949 case RES_TYPE_SYMBOL:
4950 /* As a special case, we map the values `true' and `on'
4951 to Qt, and `false' and `off' to Qnil. */
4953 Lisp_Object lower;
4954 lower = Fdowncase (tem);
4955 if (!strcmp (SSDATA (lower), "on")
4956 #ifdef HAVE_NS
4957 || !strcmp (SSDATA (lower), "yes")
4958 #endif
4959 || !strcmp (SSDATA (lower), "true"))
4960 return Qt;
4961 else if (!strcmp (SSDATA (lower), "off")
4962 #ifdef HAVE_NS
4963 || !strcmp (SSDATA (lower), "no")
4964 #endif
4965 || !strcmp (SSDATA (lower), "false"))
4966 return Qnil;
4967 else
4968 return Fintern (tem, Qnil);
4971 default:
4972 emacs_abort ();
4975 else
4976 return Qunbound;
4978 return Fcdr (tem);
4981 static Lisp_Object
4982 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
4983 const char *attribute, const char *class,
4984 enum resource_types type)
4986 return x_get_arg (FRAME_DISPLAY_INFO (f),
4987 alist, param, attribute, class, type);
4990 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
4992 Lisp_Object
4993 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
4994 Lisp_Object param,
4995 const char *attribute, const char *class,
4996 enum resource_types type)
4998 Lisp_Object value;
5000 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
5001 attribute, class, type);
5002 if (! NILP (value) && ! EQ (value, Qunbound))
5003 store_frame_param (f, param, value);
5005 return value;
5009 /* Record in frame F the specified or default value according to ALIST
5010 of the parameter named PROP (a Lisp symbol).
5011 If no value is specified for PROP, look for an X default for XPROP
5012 on the frame named NAME.
5013 If that is not found either, use the value DEFLT. */
5015 Lisp_Object
5016 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
5017 Lisp_Object deflt, const char *xprop, const char *xclass,
5018 enum resource_types type)
5020 Lisp_Object tem;
5022 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
5023 if (EQ (tem, Qunbound))
5024 tem = deflt;
5025 AUTO_FRAME_ARG (arg, prop, tem);
5026 x_set_frame_parameters (f, arg);
5027 return tem;
5031 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
5034 * XParseGeometry parses strings of the form
5035 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5036 * width, height, xoffset, and yoffset are unsigned integers.
5037 * Example: "=80x24+300-49"
5038 * The equal sign is optional.
5039 * It returns a bitmask that indicates which of the four values
5040 * were actually found in the string. For each value found,
5041 * the corresponding argument is updated; for each value
5042 * not found, the corresponding argument is left unchanged.
5045 static int
5046 XParseGeometry (char *string,
5047 int *x, int *y,
5048 unsigned int *width, unsigned int *height)
5050 int mask = NoValue;
5051 char *strind;
5052 unsigned long tempWidth UNINIT, tempHeight UNINIT;
5053 long int tempX UNINIT, tempY UNINIT;
5054 char *nextCharacter;
5056 if (string == NULL || *string == '\0')
5057 return mask;
5058 if (*string == '=')
5059 string++; /* ignore possible '=' at beg of geometry spec */
5061 strind = string;
5062 if (*strind != '+' && *strind != '-' && *strind != 'x')
5064 tempWidth = strtoul (strind, &nextCharacter, 10);
5065 if (strind == nextCharacter)
5066 return 0;
5067 strind = nextCharacter;
5068 mask |= WidthValue;
5071 if (*strind == 'x' || *strind == 'X')
5073 strind++;
5074 tempHeight = strtoul (strind, &nextCharacter, 10);
5075 if (strind == nextCharacter)
5076 return 0;
5077 strind = nextCharacter;
5078 mask |= HeightValue;
5081 if (*strind == '+' || *strind == '-')
5083 if (*strind == '-')
5084 mask |= XNegative;
5085 tempX = strtol (strind, &nextCharacter, 10);
5086 if (strind == nextCharacter)
5087 return 0;
5088 strind = nextCharacter;
5089 mask |= XValue;
5090 if (*strind == '+' || *strind == '-')
5092 if (*strind == '-')
5093 mask |= YNegative;
5094 tempY = strtol (strind, &nextCharacter, 10);
5095 if (strind == nextCharacter)
5096 return 0;
5097 strind = nextCharacter;
5098 mask |= YValue;
5102 /* If strind isn't at the end of the string then it's an invalid
5103 geometry specification. */
5105 if (*strind != '\0')
5106 return 0;
5108 if (mask & XValue)
5109 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
5110 if (mask & YValue)
5111 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
5112 if (mask & WidthValue)
5113 *width = min (tempWidth, UINT_MAX);
5114 if (mask & HeightValue)
5115 *height = min (tempHeight, UINT_MAX);
5116 return mask;
5119 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
5122 /* NS used to define x-parse-geometry in ns-win.el, but that confused
5123 make-docfile: the documentation string in ns-win.el was used for
5124 x-parse-geometry even in non-NS builds.
5126 With two definitions of x-parse-geometry in this file, various
5127 things still get confused (eg M-x apropos documentation), so that
5128 it is best if the two definitions just share the same doc-string.
5130 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
5131 doc: /* Parse a display geometry string STRING.
5132 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
5133 The properties returned may include `top', `left', `height', and `width'.
5134 For X, the value of `left' or `top' may be an integer,
5135 or a list (+ N) meaning N pixels relative to top/left corner,
5136 or a list (- N) meaning -N pixels relative to bottom/right corner.
5137 On Nextstep, this just calls `ns-parse-geometry'. */)
5138 (Lisp_Object string)
5140 int geometry, x, y;
5141 unsigned int width, height;
5142 Lisp_Object result;
5144 CHECK_STRING (string);
5146 #ifdef HAVE_NS
5147 if (strchr (SSDATA (string), ' ') != NULL)
5148 return call1 (Qns_parse_geometry, string);
5149 #endif
5150 geometry = XParseGeometry (SSDATA (string),
5151 &x, &y, &width, &height);
5152 result = Qnil;
5153 if (geometry & XValue)
5155 Lisp_Object element;
5157 if (x >= 0 && (geometry & XNegative))
5158 element = list3 (Qleft, Qminus, make_number (-x));
5159 else if (x < 0 && ! (geometry & XNegative))
5160 element = list3 (Qleft, Qplus, make_number (x));
5161 else
5162 element = Fcons (Qleft, make_number (x));
5163 result = Fcons (element, result);
5166 if (geometry & YValue)
5168 Lisp_Object element;
5170 if (y >= 0 && (geometry & YNegative))
5171 element = list3 (Qtop, Qminus, make_number (-y));
5172 else if (y < 0 && ! (geometry & YNegative))
5173 element = list3 (Qtop, Qplus, make_number (y));
5174 else
5175 element = Fcons (Qtop, make_number (y));
5176 result = Fcons (element, result);
5179 if (geometry & WidthValue)
5180 result = Fcons (Fcons (Qwidth, make_number (width)), result);
5181 if (geometry & HeightValue)
5182 result = Fcons (Fcons (Qheight, make_number (height)), result);
5184 return result;
5188 /* Calculate the desired size and position of frame F.
5189 Return the flags saying which aspects were specified.
5191 Also set the win_gravity and size_hint_flags of F.
5193 Adjust height for toolbar if TOOLBAR_P is 1.
5195 This function does not make the coordinates positive. */
5197 #define DEFAULT_ROWS 36
5198 #define DEFAULT_COLS 80
5200 long
5201 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x_width, int *x_height)
5203 Lisp_Object height, width, user_size, top, left, user_position;
5204 long window_prompting = 0;
5205 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
5206 int parent_done = -1, outer_done = -1;
5208 /* Default values if we fall through.
5209 Actually, if that happens we should get
5210 window manager prompting. */
5211 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
5212 SET_FRAME_COLS (f, DEFAULT_COLS);
5213 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
5214 SET_FRAME_LINES (f, DEFAULT_ROWS);
5216 /* Window managers expect that if program-specified
5217 positions are not (0,0), they're intentional, not defaults. */
5218 f->top_pos = 0;
5219 f->left_pos = 0;
5221 /* Calculate a tool bar height so that the user gets a text display
5222 area of the size he specified with -g or via .Xdefaults. Later
5223 changes of the tool bar height don't change the frame size. This
5224 is done so that users can create tall Emacs frames without having
5225 to guess how tall the tool bar will get. */
5226 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
5228 if (frame_default_tool_bar_height)
5229 FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
5230 else
5232 int margin, relief;
5234 relief = (tool_bar_button_relief >= 0
5235 ? tool_bar_button_relief
5236 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
5238 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
5239 margin = XFASTINT (Vtool_bar_button_margin);
5240 else if (CONSP (Vtool_bar_button_margin)
5241 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
5242 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
5243 else
5244 margin = 0;
5246 FRAME_TOOL_BAR_HEIGHT (f)
5247 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5251 /* Ensure that earlier new_width and new_height settings won't
5252 override what we specify below. */
5253 f->new_width = f->new_height = 0;
5255 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
5256 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
5257 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
5259 if (!EQ (width, Qunbound))
5261 if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
5263 CHECK_NUMBER (XCDR (width));
5264 if ((XINT (XCDR (width)) < 0 || XINT (XCDR (width)) > INT_MAX))
5265 xsignal1 (Qargs_out_of_range, XCDR (width));
5267 SET_FRAME_WIDTH (f, XINT (XCDR (width)));
5268 f->inhibit_horizontal_resize = true;
5269 *x_width = XINT (XCDR (width));
5271 else if (FLOATP (width))
5273 double d_width = XFLOAT_DATA (width);
5275 if (d_width < 0.0 || d_width > 1.0)
5276 xsignal1 (Qargs_out_of_range, width);
5277 else
5279 int new_width = frame_float (f, width, FRAME_FLOAT_WIDTH,
5280 &parent_done, &outer_done, -1);
5282 if (new_width > -1)
5283 SET_FRAME_WIDTH (f, new_width);
5286 else
5288 CHECK_NUMBER (width);
5289 if ((XINT (width) < 0 || XINT (width) > INT_MAX))
5290 xsignal1 (Qargs_out_of_range, width);
5292 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
5296 if (!EQ (height, Qunbound))
5298 if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
5300 CHECK_NUMBER (XCDR (height));
5301 if ((XINT (XCDR (height)) < 0 || XINT (XCDR (height)) > INT_MAX))
5302 xsignal1 (Qargs_out_of_range, XCDR (height));
5304 SET_FRAME_HEIGHT (f, XINT (XCDR (height)));
5305 f->inhibit_vertical_resize = true;
5306 *x_height = XINT (XCDR (height));
5308 else if (FLOATP (height))
5310 double d_height = XFLOAT_DATA (height);
5312 if (d_height < 0.0 || d_height > 1.0)
5313 xsignal1 (Qargs_out_of_range, height);
5314 else
5316 int new_height = frame_float (f, height, FRAME_FLOAT_HEIGHT,
5317 &parent_done, &outer_done, -1);
5319 if (new_height > -1)
5320 SET_FRAME_HEIGHT (f, new_height);
5323 else
5325 CHECK_NUMBER (height);
5326 if ((XINT (height) < 0) || (XINT (height) > INT_MAX))
5327 xsignal1 (Qargs_out_of_range, height);
5329 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
5333 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
5334 if (!NILP (user_size) && !EQ (user_size, Qunbound))
5335 window_prompting |= USSize;
5336 else
5337 window_prompting |= PSize;
5340 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
5341 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
5342 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
5343 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
5345 if (EQ (top, Qminus))
5347 f->top_pos = 0;
5348 window_prompting |= YNegative;
5350 else if (CONSP (top) && EQ (XCAR (top), Qminus)
5351 && CONSP (XCDR (top))
5352 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
5354 f->top_pos = - XINT (XCAR (XCDR (top)));
5355 window_prompting |= YNegative;
5357 else if (CONSP (top) && EQ (XCAR (top), Qplus)
5358 && CONSP (XCDR (top))
5359 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
5361 f->top_pos = XINT (XCAR (XCDR (top)));
5363 else if (FLOATP (top))
5364 f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
5365 &outer_done, 0);
5366 else if (EQ (top, Qunbound))
5367 f->top_pos = 0;
5368 else
5370 CHECK_TYPE_RANGED_INTEGER (int, top);
5371 f->top_pos = XINT (top);
5372 if (f->top_pos < 0)
5373 window_prompting |= YNegative;
5376 if (EQ (left, Qminus))
5378 f->left_pos = 0;
5379 window_prompting |= XNegative;
5381 else if (CONSP (left) && EQ (XCAR (left), Qminus)
5382 && CONSP (XCDR (left))
5383 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
5385 f->left_pos = - XINT (XCAR (XCDR (left)));
5386 window_prompting |= XNegative;
5388 else if (CONSP (left) && EQ (XCAR (left), Qplus)
5389 && CONSP (XCDR (left))
5390 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
5392 f->left_pos = XINT (XCAR (XCDR (left)));
5394 else if (FLOATP (left))
5395 f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
5396 &outer_done, 0);
5397 else if (EQ (left, Qunbound))
5398 f->left_pos = 0;
5399 else
5401 CHECK_TYPE_RANGED_INTEGER (int, left);
5402 f->left_pos = XINT (left);
5403 if (f->left_pos < 0)
5404 window_prompting |= XNegative;
5407 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
5408 window_prompting |= USPosition;
5409 else
5410 window_prompting |= PPosition;
5413 if (window_prompting & XNegative)
5415 if (window_prompting & YNegative)
5416 f->win_gravity = SouthEastGravity;
5417 else
5418 f->win_gravity = NorthEastGravity;
5420 else
5422 if (window_prompting & YNegative)
5423 f->win_gravity = SouthWestGravity;
5424 else
5425 f->win_gravity = NorthWestGravity;
5428 f->size_hint_flags = window_prompting;
5430 return window_prompting;
5435 #endif /* HAVE_WINDOW_SYSTEM */
5437 void
5438 frame_make_pointer_invisible (struct frame *f)
5440 if (! NILP (Vmake_pointer_invisible))
5442 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
5443 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5445 f->mouse_moved = 0;
5446 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
5447 f->pointer_invisible = 1;
5452 void
5453 frame_make_pointer_visible (struct frame *f)
5455 /* We don't check Vmake_pointer_invisible here in case the
5456 pointer was invisible when Vmake_pointer_invisible was set to nil. */
5457 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
5458 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5460 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
5461 f->pointer_invisible = 0;
5465 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
5466 Sframe_pointer_visible_p, 0, 1, 0,
5467 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
5468 Otherwise it returns nil. FRAME omitted or nil means the
5469 selected frame. This is useful when `make-pointer-invisible' is set. */)
5470 (Lisp_Object frame)
5472 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
5477 /***********************************************************************
5478 Multimonitor data
5479 ***********************************************************************/
5481 #ifdef HAVE_WINDOW_SYSTEM
5483 # if (defined HAVE_NS \
5484 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
5485 void
5486 free_monitors (struct MonitorInfo *monitors, int n_monitors)
5488 int i;
5489 for (i = 0; i < n_monitors; ++i)
5490 xfree (monitors[i].name);
5491 xfree (monitors);
5493 # endif
5495 Lisp_Object
5496 make_monitor_attribute_list (struct MonitorInfo *monitors,
5497 int n_monitors,
5498 int primary_monitor,
5499 Lisp_Object monitor_frames,
5500 const char *source)
5502 Lisp_Object attributes_list = Qnil;
5503 Lisp_Object primary_monitor_attributes = Qnil;
5504 int i;
5506 for (i = 0; i < n_monitors; ++i)
5508 Lisp_Object geometry, workarea, attributes = Qnil;
5509 struct MonitorInfo *mi = &monitors[i];
5511 if (mi->geom.width == 0) continue;
5513 workarea = list4i (mi->work.x, mi->work.y,
5514 mi->work.width, mi->work.height);
5515 geometry = list4i (mi->geom.x, mi->geom.y,
5516 mi->geom.width, mi->geom.height);
5517 attributes = Fcons (Fcons (Qsource, build_string (source)),
5518 attributes);
5519 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
5520 attributes);
5521 attributes = Fcons (Fcons (Qmm_size,
5522 list2i (mi->mm_width, mi->mm_height)),
5523 attributes);
5524 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5525 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5526 if (mi->name)
5527 attributes = Fcons (Fcons (Qname, make_string (mi->name,
5528 strlen (mi->name))),
5529 attributes);
5531 if (i == primary_monitor)
5532 primary_monitor_attributes = attributes;
5533 else
5534 attributes_list = Fcons (attributes, attributes_list);
5537 if (!NILP (primary_monitor_attributes))
5538 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
5539 return attributes_list;
5542 #endif /* HAVE_WINDOW_SYSTEM */
5545 /***********************************************************************
5546 Initialization
5547 ***********************************************************************/
5549 void
5550 syms_of_frame (void)
5552 DEFSYM (Qframep, "framep");
5553 DEFSYM (Qframe_live_p, "frame-live-p");
5554 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
5555 DEFSYM (Qdisplay_monitor_attributes_list, "display-monitor-attributes-list");
5556 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
5557 DEFSYM (Qexplicit_name, "explicit-name");
5558 DEFSYM (Qheight, "height");
5559 DEFSYM (Qicon, "icon");
5560 DEFSYM (Qminibuffer, "minibuffer");
5561 DEFSYM (Qundecorated, "undecorated");
5562 DEFSYM (Qno_special_glyphs, "no-special-glyphs");
5563 DEFSYM (Qparent_frame, "parent-frame");
5564 DEFSYM (Qskip_taskbar, "skip-taskbar");
5565 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
5566 DEFSYM (Qno_accept_focus, "no-accept-focus");
5567 DEFSYM (Qz_group, "z-group");
5568 DEFSYM (Qoverride_redirect, "override-redirect");
5569 DEFSYM (Qdelete_before, "delete-before");
5570 DEFSYM (Qmodeline, "modeline");
5571 DEFSYM (Qonly, "only");
5572 DEFSYM (Qnone, "none");
5573 DEFSYM (Qwidth, "width");
5574 DEFSYM (Qtext_pixels, "text-pixels");
5575 DEFSYM (Qgeometry, "geometry");
5576 DEFSYM (Qicon_left, "icon-left");
5577 DEFSYM (Qicon_top, "icon-top");
5578 DEFSYM (Qtooltip, "tooltip");
5579 DEFSYM (Quser_position, "user-position");
5580 DEFSYM (Quser_size, "user-size");
5581 DEFSYM (Qwindow_id, "window-id");
5582 #ifdef HAVE_X_WINDOWS
5583 DEFSYM (Qouter_window_id, "outer-window-id");
5584 #endif
5585 DEFSYM (Qparent_id, "parent-id");
5586 DEFSYM (Qx, "x");
5587 DEFSYM (Qw32, "w32");
5588 DEFSYM (Qpc, "pc");
5589 DEFSYM (Qns, "ns");
5590 DEFSYM (Qvisible, "visible");
5591 DEFSYM (Qbuffer_predicate, "buffer-predicate");
5592 DEFSYM (Qbuffer_list, "buffer-list");
5593 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
5594 DEFSYM (Qdisplay_type, "display-type");
5595 DEFSYM (Qbackground_mode, "background-mode");
5596 DEFSYM (Qnoelisp, "noelisp");
5597 DEFSYM (Qtty_color_mode, "tty-color-mode");
5598 DEFSYM (Qtty, "tty");
5599 DEFSYM (Qtty_type, "tty-type");
5601 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
5603 DEFSYM (Qfullwidth, "fullwidth");
5604 DEFSYM (Qfullheight, "fullheight");
5605 DEFSYM (Qfullboth, "fullboth");
5606 DEFSYM (Qmaximized, "maximized");
5607 DEFSYM (Qx_resource_name, "x-resource-name");
5608 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
5610 DEFSYM (Qworkarea, "workarea");
5611 DEFSYM (Qmm_size, "mm-size");
5612 DEFSYM (Qframes, "frames");
5613 DEFSYM (Qsource, "source");
5615 DEFSYM (Qframe_edges, "frame-edges");
5616 DEFSYM (Qouter_edges, "outer-edges");
5617 DEFSYM (Qouter_position, "outer-position");
5618 DEFSYM (Qouter_size, "outer-size");
5619 DEFSYM (Qnative_edges, "native-edges");
5620 DEFSYM (Qinner_edges, "inner-edges");
5621 DEFSYM (Qexternal_border_size, "external-border-size");
5622 DEFSYM (Qtitle_bar_size, "title-bar-size");
5623 DEFSYM (Qmenu_bar_external, "menu-bar-external");
5624 DEFSYM (Qmenu_bar_size, "menu-bar-size");
5625 DEFSYM (Qtool_bar_external, "tool-bar-external");
5626 DEFSYM (Qtool_bar_size, "tool-bar-size");
5627 /* The following are used for frame_size_history. */
5628 DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
5629 DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
5630 DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
5631 DEFSYM (Qx_set_frame_parameters, "x-set-frame-parameters");
5632 DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
5633 DEFSYM (Qset_frame_size, "set-frame-size");
5634 DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
5635 DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
5636 DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
5637 DEFSYM (Qxg_frame_resized, "xg-frame-resized");
5638 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
5639 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
5640 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
5641 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
5642 DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
5643 DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
5644 DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
5645 DEFSYM (Qx_net_wm_state, "x-net-wm-state");
5646 DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
5647 DEFSYM (Qtb_size_cb, "tb-size-cb");
5648 DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
5649 DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
5650 DEFSYM (Qx_set_menu_bar_lines, "x-set-menu-bar-lines");
5651 DEFSYM (Qchange_frame_size, "change-frame-size");
5652 DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
5653 DEFSYM (Qset_window_configuration, "set-window-configuration");
5654 DEFSYM (Qx_create_frame_1, "x-create-frame-1");
5655 DEFSYM (Qx_create_frame_2, "x-create-frame-2");
5656 DEFSYM (Qterminal_frame, "terminal-frame");
5658 #ifdef HAVE_NS
5659 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
5660 #endif
5661 #ifdef NS_IMPL_COCOA
5662 DEFSYM (Qns_appearance, "ns-appearance");
5663 DEFSYM (Qns_transparent_titlebar, "ns-transparent-titlebar");
5664 #endif
5666 DEFSYM (Qalpha, "alpha");
5667 DEFSYM (Qauto_lower, "auto-lower");
5668 DEFSYM (Qauto_raise, "auto-raise");
5669 DEFSYM (Qborder_color, "border-color");
5670 DEFSYM (Qborder_width, "border-width");
5671 DEFSYM (Qouter_border_width, "outer-border-width");
5672 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
5673 DEFSYM (Qcursor_color, "cursor-color");
5674 DEFSYM (Qcursor_type, "cursor-type");
5675 DEFSYM (Qfont_backend, "font-backend");
5676 DEFSYM (Qfullscreen, "fullscreen");
5677 DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
5678 DEFSYM (Qicon_name, "icon-name");
5679 DEFSYM (Qicon_type, "icon-type");
5680 DEFSYM (Qinternal_border_width, "internal-border-width");
5681 DEFSYM (Qleft_fringe, "left-fringe");
5682 DEFSYM (Qline_spacing, "line-spacing");
5683 DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
5684 DEFSYM (Qupdate_frame_menubar, "update-frame-menubar");
5685 DEFSYM (Qfree_frame_menubar_1, "free-frame-menubar-1");
5686 DEFSYM (Qfree_frame_menubar_2, "free-frame-menubar-2");
5687 DEFSYM (Qmouse_color, "mouse-color");
5688 DEFSYM (Qname, "name");
5689 DEFSYM (Qright_divider_width, "right-divider-width");
5690 DEFSYM (Qright_fringe, "right-fringe");
5691 DEFSYM (Qscreen_gamma, "screen-gamma");
5692 DEFSYM (Qscroll_bar_background, "scroll-bar-background");
5693 DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
5694 DEFSYM (Qscroll_bar_height, "scroll-bar-height");
5695 DEFSYM (Qscroll_bar_width, "scroll-bar-width");
5696 DEFSYM (Qsticky, "sticky");
5697 DEFSYM (Qtitle, "title");
5698 DEFSYM (Qtool_bar_lines, "tool-bar-lines");
5699 DEFSYM (Qtool_bar_position, "tool-bar-position");
5700 DEFSYM (Qunsplittable, "unsplittable");
5701 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
5702 DEFSYM (Qvisibility, "visibility");
5703 DEFSYM (Qwait_for_wm, "wait-for-wm");
5704 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5705 DEFSYM (Qno_other_frame, "no-other-frame");
5706 DEFSYM (Qbelow, "below");
5707 DEFSYM (Qabove_suspended, "above-suspended");
5708 DEFSYM (Qmin_width, "min-width");
5709 DEFSYM (Qmin_height, "min-height");
5710 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
5711 DEFSYM (Qkeep_ratio, "keep-ratio");
5712 DEFSYM (Qwidth_only, "width-only");
5713 DEFSYM (Qheight_only, "height-only");
5714 DEFSYM (Qleft_only, "left-only");
5715 DEFSYM (Qtop_only, "top-only");
5718 int i;
5720 for (i = 0; i < ARRAYELTS (frame_parms); i++)
5722 Lisp_Object v = (frame_parms[i].sym < 0
5723 ? intern_c_string (frame_parms[i].name)
5724 : builtin_lisp_symbol (frame_parms[i].sym));
5725 Fput (v, Qx_frame_parameter, make_number (i));
5729 #ifdef HAVE_WINDOW_SYSTEM
5730 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
5731 doc: /* The name Emacs uses to look up X resources.
5732 `x-get-resource' uses this as the first component of the instance name
5733 when requesting resource values.
5734 Emacs initially sets `x-resource-name' to the name under which Emacs
5735 was invoked, or to the value specified with the `-name' or `-rn'
5736 switches, if present.
5738 It may be useful to bind this variable locally around a call
5739 to `x-get-resource'. See also the variable `x-resource-class'. */);
5740 Vx_resource_name = Qnil;
5742 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
5743 doc: /* The class Emacs uses to look up X resources.
5744 `x-get-resource' uses this as the first component of the instance class
5745 when requesting resource values.
5747 Emacs initially sets `x-resource-class' to "Emacs".
5749 Setting this variable permanently is not a reasonable thing to do,
5750 but binding this variable locally around a call to `x-get-resource'
5751 is a reasonable practice. See also the variable `x-resource-name'. */);
5752 Vx_resource_class = build_string (EMACS_CLASS);
5754 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
5755 doc: /* The lower limit of the frame opacity (alpha transparency).
5756 The value should range from 0 (invisible) to 100 (completely opaque).
5757 You can also use a floating number between 0.0 and 1.0. */);
5758 Vframe_alpha_lower_limit = make_number (20);
5759 #endif
5761 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
5762 doc: /* Alist of default values for frame creation.
5763 These may be set in your init file, like this:
5764 (setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
5765 These override values given in window system configuration data,
5766 including X Windows' defaults database.
5767 For values specific to the first Emacs frame, see `initial-frame-alist'.
5768 For window-system specific values, see `window-system-default-frame-alist'.
5769 For values specific to the separate minibuffer frame, see
5770 `minibuffer-frame-alist'.
5771 The `menu-bar-lines' element of the list controls whether new frames
5772 have menu bars; `menu-bar-mode' works by altering this element.
5773 Setting this variable does not affect existing frames, only new ones. */);
5774 Vdefault_frame_alist = Qnil;
5776 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
5777 doc: /* Default position of vertical scroll bars on this window-system. */);
5778 #ifdef HAVE_WINDOW_SYSTEM
5779 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
5780 /* MS-Windows, macOS, and GTK have scroll bars on the right by
5781 default. */
5782 Vdefault_frame_scroll_bars = Qright;
5783 #else
5784 Vdefault_frame_scroll_bars = Qleft;
5785 #endif
5786 #else
5787 Vdefault_frame_scroll_bars = Qnil;
5788 #endif
5790 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
5791 scroll_bar_adjust_thumb_portion_p,
5792 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
5793 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
5794 even if the end of the buffer is shown (i.e. overscrolling).
5795 Set to nil if you want the thumb to be at the bottom when the end of the buffer
5796 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
5797 is visible. In this case you can not overscroll. */);
5798 scroll_bar_adjust_thumb_portion_p = 1;
5800 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
5801 doc: /* The initial frame-object, which represents Emacs's stdout. */);
5803 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
5804 doc: /* If non-nil, function to transform normal value of `mouse-position'.
5805 `mouse-position' and `mouse-pixel-position' call this function, passing their
5806 usual return value as argument, and return whatever this function returns.
5807 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
5808 which need to do mouse handling at the Lisp level. */);
5809 Vmouse_position_function = Qnil;
5811 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
5812 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
5813 If the value is an integer, highlighting is only shown after moving the
5814 mouse, while keyboard input turns off the highlight even when the mouse
5815 is over the clickable text. However, the mouse shape still indicates
5816 when the mouse is over clickable text. */);
5817 Vmouse_highlight = Qt;
5819 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
5820 doc: /* If non-nil, make pointer invisible while typing.
5821 The pointer becomes visible again when the mouse is moved. */);
5822 Vmake_pointer_invisible = Qt;
5824 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
5825 doc: /* Normal hook run when a frame gains input focus.
5826 The frame gaining focus is selected at the time this hook is run. */);
5827 Vfocus_in_hook = Qnil;
5829 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
5830 doc: /* Normal hook run when all frames lost input focus. */);
5831 Vfocus_out_hook = Qnil;
5833 DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
5834 doc: /* Functions run after a frame was moved.
5835 The functions are run with one arg, the frame that moved. */);
5836 Vmove_frame_functions = Qnil;
5838 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
5839 doc: /* Functions run before deleting a frame.
5840 The functions are run with one arg, the frame to be deleted.
5841 See `delete-frame'.
5843 Note that functions in this list may be called just before the frame is
5844 actually deleted, or some time later (or even both when an earlier function
5845 in `delete-frame-functions' (indirectly) calls `delete-frame'
5846 recursively). */);
5847 Vdelete_frame_functions = Qnil;
5848 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
5850 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
5851 doc: /* Non-nil if Menu-Bar mode is enabled.
5852 See the command `menu-bar-mode' for a description of this minor mode.
5853 Setting this variable directly does not take effect;
5854 either customize it (see the info node `Easy Customization')
5855 or call the function `menu-bar-mode'. */);
5856 Vmenu_bar_mode = Qt;
5858 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
5859 doc: /* Non-nil if Tool-Bar mode is enabled.
5860 See the command `tool-bar-mode' for a description of this minor mode.
5861 Setting this variable directly does not take effect;
5862 either customize it (see the info node `Easy Customization')
5863 or call the function `tool-bar-mode'. */);
5864 #ifdef HAVE_WINDOW_SYSTEM
5865 Vtool_bar_mode = Qt;
5866 #else
5867 Vtool_bar_mode = Qnil;
5868 #endif
5870 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
5871 doc: /* Minibufferless frames use this frame's minibuffer.
5872 Emacs cannot create minibufferless frames unless this is set to an
5873 appropriate surrogate.
5875 Emacs consults this variable only when creating minibufferless
5876 frames; once the frame is created, it sticks with its assigned
5877 minibuffer, no matter what this variable is set to. This means that
5878 this variable doesn't necessarily say anything meaningful about the
5879 current set of frames, or where the minibuffer is currently being
5880 displayed.
5882 This variable is local to the current terminal and cannot be buffer-local. */);
5884 DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
5885 doc: /* Non-nil if window system changes focus when you move the mouse.
5886 You should set this variable to tell Emacs how your window manager
5887 handles focus, since there is no way in general for Emacs to find out
5888 automatically.
5890 There are three meaningful values:
5892 - The default nil should be used when your window manager follows a
5893 "click-to-focus" policy where you have to click the mouse inside of a
5894 frame in order for that frame to get focus.
5896 - The value t should be used when your window manager has the focus
5897 automatically follow the position of the mouse pointer but a window
5898 that gains focus is not raised automatically.
5900 - The value `auto-raise' should be used when your window manager has the
5901 focus automatically follow the position of the mouse pointer and a
5902 window that gains focus is raised automatically.
5904 If this option is non-nil, Emacs moves the mouse pointer to the frame
5905 selected by `select-frame-set-input-focus'. This function is used by a
5906 number of commands like, for example, `other-frame' and `pop-to-buffer'.
5907 If this option is nil and your focus follows mouse window manager does
5908 not autonomously move the mouse pointer to the newly selected frame, the
5909 previously selected window manager window might get reselected instead
5910 immediately.
5912 The distinction between the values t and `auto-raise' is not needed for
5913 "normal" frames because the window manager takes care of raising them.
5914 Setting this to `auto-raise' will, however, override the standard
5915 behavior of a window manager that does not automatically raise the frame
5916 that gets focus. Setting this to `auto-raise' is also necessary to
5917 automatically raise child frames which are usually left alone by the
5918 window manager.
5920 Note that this option does not distinguish "sloppy" focus (where the
5921 frame that previously had focus retains focus as long as the mouse
5922 pointer does not move into another window manager window) from "strict"
5923 focus (where a frame immediately loses focus when it's left by the mouse
5924 pointer).
5926 In order to extend a "focus follows mouse" policy to individual Emacs
5927 windows, customize the variable `mouse-autoselect-window'. */);
5928 focus_follows_mouse = Qnil;
5930 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5931 doc: /* Non-nil means resize frames pixelwise.
5932 If this option is nil, resizing a frame rounds its sizes to the frame's
5933 current values of `frame-char-height' and `frame-char-width'. If this
5934 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5935 by one pixel.
5937 With some window managers you may have to set this to non-nil in order
5938 to set the size of a frame in pixels, to maximize frames or to make them
5939 fullscreen. To resize your initial frame pixelwise, set this option to
5940 a non-nil value in your init file. */);
5941 frame_resize_pixelwise = 0;
5943 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
5944 doc: /* Whether frames should be resized implicitly.
5945 If this option is nil, setting font, menu bar, tool bar, internal
5946 borders, fringes or scroll bars of a specific frame may resize the frame
5947 in order to preserve the number of columns or lines it displays. If
5948 this option is t, no such resizing is done. Note that the size of
5949 fullscreen and maximized frames, the height of fullheight frames and the
5950 width of fullwidth frames never change implicitly.
5952 The value of this option can be also be a list of frame parameters. In
5953 this case, resizing is inhibited when changing a parameter that appears
5954 in that list. The parameters currently handled by this option include
5955 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
5956 `tool-bar-lines'.
5958 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
5959 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
5960 `right-fringe' is handled as if the frame contained just one live
5961 window. This means, for example, that removing vertical scroll bars on
5962 a frame containing several side by side windows will shrink the frame
5963 width by the width of one scroll bar provided this option is nil and
5964 keep it unchanged if this option is either t or a list containing
5965 `vertical-scroll-bars'.
5967 The default value is \\='(tool-bar-lines) on Lucid, Motif and Windows
5968 \(which means that adding/removing a tool bar does not change the frame
5969 height), nil on all other window systems including GTK+ (which means
5970 that changing any of the parameters listed above may change the size of
5971 the frame), and t otherwise (which means the frame size never changes
5972 implicitly when there's no window system support).
5974 Note that when a frame is not large enough to accommodate a change of
5975 any of the parameters listed above, Emacs may try to enlarge the frame
5976 even if this option is non-nil. */);
5977 #if defined (HAVE_WINDOW_SYSTEM)
5978 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
5979 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
5980 #else
5981 frame_inhibit_implied_resize = Qnil;
5982 #endif
5983 #else
5984 frame_inhibit_implied_resize = Qt;
5985 #endif
5987 DEFVAR_LISP ("frame-size-history", frame_size_history,
5988 doc: /* History of frame size adjustments.
5989 If non-nil, list recording frame size adjustment. Adjustments are
5990 recorded only if the first element of this list is a positive number.
5991 Adding an adjustment decrements that number by one.
5993 The remaining elements are the adjustments. Each adjustment is a list
5994 of four elements `frame', `function', `sizes' and `more'. `frame' is
5995 the affected frame and `function' the invoking function. `sizes' is
5996 usually a list of four elements `old-width', `old-height', `new-width'
5997 and `new-height' representing the old and new sizes recorded/requested
5998 by `function'. `more' is a list with additional information.
6000 The function `frame--size-history' displays the value of this variable
6001 in a more readable form. */);
6002 frame_size_history = Qnil;
6004 DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame,
6005 doc: /* Non-nil means reuse hidden tooltip frames.
6006 When this is nil, delete a tooltip frame when hiding the associated
6007 tooltip. When this is non-nil, make the tooltip frame invisible only,
6008 so it can be reused when the next tooltip is shown.
6010 Setting this to non-nil may drastically reduce the consing overhead
6011 incurred by creating new tooltip frames. However, a value of non-nil
6012 means also that intermittent changes of faces or `default-frame-alist'
6013 are not applied when showing a tooltip in a reused frame.
6015 This variable is effective only with the X toolkit (and there only when
6016 Gtk+ tooltips are not used) and on Windows. */);
6017 tooltip_reuse_hidden_frame = false;
6019 staticpro (&Vframe_list);
6021 defsubr (&Sframep);
6022 defsubr (&Sframe_live_p);
6023 defsubr (&Swindow_system);
6024 defsubr (&Sframe_windows_min_size);
6025 defsubr (&Smake_terminal_frame);
6026 defsubr (&Shandle_switch_frame);
6027 defsubr (&Sselect_frame);
6028 defsubr (&Sselected_frame);
6029 defsubr (&Sframe_list);
6030 defsubr (&Sframe_parent);
6031 defsubr (&Sframe_ancestor_p);
6032 defsubr (&Snext_frame);
6033 defsubr (&Sprevious_frame);
6034 defsubr (&Slast_nonminibuf_frame);
6035 defsubr (&Sdelete_frame);
6036 defsubr (&Smouse_position);
6037 defsubr (&Smouse_pixel_position);
6038 defsubr (&Sset_mouse_position);
6039 defsubr (&Sset_mouse_pixel_position);
6040 #if 0
6041 defsubr (&Sframe_configuration);
6042 defsubr (&Srestore_frame_configuration);
6043 #endif
6044 defsubr (&Smake_frame_visible);
6045 defsubr (&Smake_frame_invisible);
6046 defsubr (&Siconify_frame);
6047 defsubr (&Sframe_visible_p);
6048 defsubr (&Svisible_frame_list);
6049 defsubr (&Sraise_frame);
6050 defsubr (&Slower_frame);
6051 defsubr (&Sx_focus_frame);
6052 defsubr (&Sframe_after_make_frame);
6053 defsubr (&Sredirect_frame_focus);
6054 defsubr (&Sframe_focus);
6055 defsubr (&Sframe_parameters);
6056 defsubr (&Sframe_parameter);
6057 defsubr (&Smodify_frame_parameters);
6058 defsubr (&Sframe_char_height);
6059 defsubr (&Sframe_char_width);
6060 defsubr (&Sframe_native_height);
6061 defsubr (&Sframe_native_width);
6062 defsubr (&Sframe_text_cols);
6063 defsubr (&Sframe_text_lines);
6064 defsubr (&Sframe_total_cols);
6065 defsubr (&Sframe_total_lines);
6066 defsubr (&Sframe_text_width);
6067 defsubr (&Sframe_text_height);
6068 defsubr (&Sscroll_bar_width);
6069 defsubr (&Sscroll_bar_height);
6070 defsubr (&Sfringe_width);
6071 defsubr (&Sframe_internal_border_width);
6072 defsubr (&Sright_divider_width);
6073 defsubr (&Sbottom_divider_width);
6074 defsubr (&Stool_bar_pixel_width);
6075 defsubr (&Sset_frame_height);
6076 defsubr (&Sset_frame_width);
6077 defsubr (&Sset_frame_size);
6078 defsubr (&Sframe_position);
6079 defsubr (&Sset_frame_position);
6080 defsubr (&Sframe_pointer_visible_p);
6082 #ifdef HAVE_WINDOW_SYSTEM
6083 defsubr (&Sx_get_resource);
6084 defsubr (&Sx_parse_geometry);
6085 #endif