Allow 'browse-url-emacs' to fetch URL in the selected window
[emacs.git] / src / frame.c
blob86caa32615d572193f7651f9f9fa3be8f5e24c24
1 /* Generic frame functions.
3 Copyright (C) 1993-1995, 1997, 1999-2018 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 "ptr-bounds.h"
39 #include "frame.h"
40 #include "blockinput.h"
41 #include "termchar.h"
42 #include "termhooks.h"
43 #include "dispextern.h"
44 #include "window.h"
45 #ifdef HAVE_WINDOW_SYSTEM
46 #include "fontset.h"
47 #endif
48 #include "cm.h"
49 #ifdef MSDOS
50 #include "msdos.h"
51 #include "dosfns.h"
52 #endif
53 #ifdef USE_X_TOOLKIT
54 #include "widget.h"
55 #endif
57 /* The currently selected frame. */
59 Lisp_Object selected_frame;
61 /* A frame which is not just a mini-buffer, or NULL if there are no such
62 frames. This is usually the most recent such frame that was selected. */
64 static struct frame *last_nonminibuf_frame;
66 /* False means there are no visible garbaged frames. */
67 bool frame_garbaged;
69 /* The default tool bar height for future frames. */
70 #if defined USE_GTK || defined HAVE_NS
71 enum { frame_default_tool_bar_height = 0 };
72 #else
73 int frame_default_tool_bar_height;
74 #endif
76 #ifdef HAVE_WINDOW_SYSTEM
77 static void x_report_frame_params (struct frame *, Lisp_Object *);
78 #endif
80 /* These setters are used only in this file, so they can be private. */
81 static void
82 fset_buffer_predicate (struct frame *f, Lisp_Object val)
84 f->buffer_predicate = val;
86 static void
87 fset_minibuffer_window (struct frame *f, Lisp_Object val)
89 f->minibuffer_window = val;
92 struct frame *
93 decode_live_frame (register Lisp_Object frame)
95 if (NILP (frame))
96 frame = selected_frame;
97 CHECK_LIVE_FRAME (frame);
98 return XFRAME (frame);
101 struct frame *
102 decode_any_frame (register Lisp_Object frame)
104 if (NILP (frame))
105 frame = selected_frame;
106 CHECK_FRAME (frame);
107 return XFRAME (frame);
110 #ifdef HAVE_WINDOW_SYSTEM
111 bool
112 display_available (void)
114 return x_display_list != NULL;
116 #endif
118 struct frame *
119 decode_window_system_frame (Lisp_Object frame)
121 struct frame *f = decode_live_frame (frame);
122 check_window_system (f);
123 #ifdef HAVE_WINDOW_SYSTEM
124 return f;
125 #endif
128 void
129 check_window_system (struct frame *f)
131 #ifdef HAVE_WINDOW_SYSTEM
132 if (window_system_available (f))
133 return;
134 #endif
135 error (f ? "Window system frame should be used"
136 : "Window system is not in use or not initialized");
139 /* Return the value of frame parameter PROP in frame FRAME. */
141 Lisp_Object
142 get_frame_param (register struct frame *frame, Lisp_Object prop)
144 register Lisp_Object tem;
146 tem = Fassq (prop, frame->param_alist);
147 if (EQ (tem, Qnil))
148 return tem;
149 return Fcdr (tem);
153 void
154 frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
155 int width, int height, Lisp_Object rest)
157 Lisp_Object frame;
159 XSETFRAME (frame, f);
160 if (CONSP (frame_size_history)
161 && INTEGERP (XCAR (frame_size_history))
162 && 0 < XINT (XCAR (frame_size_history)))
163 frame_size_history =
164 Fcons (make_number (XINT (XCAR (frame_size_history)) - 1),
165 Fcons (list4
166 (frame, fun_symbol,
167 ((width > 0)
168 ? list4 (make_number (FRAME_TEXT_WIDTH (f)),
169 make_number (FRAME_TEXT_HEIGHT (f)),
170 make_number (width),
171 make_number (height))
172 : Qnil),
173 rest),
174 XCDR (frame_size_history)));
178 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
179 state of frame F would be affected by a vertical (horizontal if
180 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
181 parameter that is changed. */
182 bool
183 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
185 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
186 bool inhibit
187 = (f->after_make_frame
188 ? (EQ (frame_inhibit_implied_resize, Qt)
189 || (CONSP (frame_inhibit_implied_resize)
190 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
191 || (horizontal
192 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullheight))
193 || (!horizontal
194 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullwidth))
195 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
196 : ((horizontal && f->inhibit_horizontal_resize)
197 || (!horizontal && f->inhibit_vertical_resize)));
198 if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
199 frame_size_history_add
200 (f, Qframe_inhibit_resize, 0, 0,
201 list5 (horizontal ? Qt : Qnil, parameter,
202 f->after_make_frame ? Qt : Qnil,
203 frame_inhibit_implied_resize,
204 fullscreen));
206 return inhibit;
209 static void
210 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
212 int nlines;
213 int olines = FRAME_MENU_BAR_LINES (f);
215 /* Right now, menu bars don't work properly in minibuf-only frames;
216 most of the commands try to apply themselves to the minibuffer
217 frame itself, and get an error because you can't switch buffers
218 in or split the minibuffer window. */
219 if (FRAME_MINIBUF_ONLY_P (f))
220 return;
222 if (TYPE_RANGED_INTEGERP (int, value))
223 nlines = XINT (value);
224 else
225 nlines = 0;
227 if (nlines != olines)
229 windows_or_buffers_changed = 14;
230 FRAME_MENU_BAR_LINES (f) = nlines;
231 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
232 change_frame_size (f, FRAME_COLS (f),
233 FRAME_LINES (f) + olines - nlines,
234 0, 1, 0, 0);
238 Lisp_Object Vframe_list;
241 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
242 doc: /* Return non-nil if OBJECT is a frame.
243 Value is:
244 t for a termcap frame (a character-only terminal),
245 `x' for an Emacs frame that is really an X window,
246 `w32' for an Emacs frame that is a window on MS-Windows display,
247 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
248 `pc' for a direct-write MS-DOS frame.
249 See also `frame-live-p'. */)
250 (Lisp_Object object)
252 if (!FRAMEP (object))
253 return Qnil;
254 switch (XFRAME (object)->output_method)
256 case output_initial: /* The initial frame is like a termcap frame. */
257 case output_termcap:
258 return Qt;
259 case output_x_window:
260 return Qx;
261 case output_w32:
262 return Qw32;
263 case output_msdos_raw:
264 return Qpc;
265 case output_ns:
266 return Qns;
267 default:
268 emacs_abort ();
272 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
273 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
274 Value is nil if OBJECT is not a live frame. If object is a live
275 frame, the return value indicates what sort of terminal device it is
276 displayed on. See the documentation of `framep' for possible
277 return values. */)
278 (Lisp_Object object)
280 return ((FRAMEP (object)
281 && FRAME_LIVE_P (XFRAME (object)))
282 ? Fframep (object)
283 : Qnil);
286 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
287 doc: /* The name of the window system that FRAME is displaying through.
288 The value is a symbol:
289 nil for a termcap frame (a character-only terminal),
290 `x' for an Emacs frame that is really an X window,
291 `w32' for an Emacs frame that is a window on MS-Windows display,
292 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
293 `pc' for a direct-write MS-DOS frame.
295 FRAME defaults to the currently selected frame.
297 Use of this function as a predicate is deprecated. Instead,
298 use `display-graphic-p' or any of the other `display-*-p'
299 predicates which report frame's specific UI-related capabilities. */)
300 (Lisp_Object frame)
302 Lisp_Object type;
303 if (NILP (frame))
304 frame = selected_frame;
306 type = Fframep (frame);
308 if (NILP (type))
309 wrong_type_argument (Qframep, frame);
311 if (EQ (type, Qt))
312 return Qnil;
313 else
314 return type;
317 /* Placeholder used by temacs -nw before window.el is loaded. */
318 DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
319 Sframe_windows_min_size, 4, 4, 0,
320 doc: /* SKIP: real doc in window.el. */
321 attributes: const)
322 (Lisp_Object frame, Lisp_Object horizontal,
323 Lisp_Object ignore, Lisp_Object pixelwise)
325 return make_number (0);
329 * frame_windows_min_size:
331 * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
332 * of FRAME. If PIXELWISE is non-nil, return the minimum inner height
333 * (width) of FRAME in pixels.
335 * This value is calculated by the function `frame-windows-min-size' in
336 * window.el unless the `min-height' (`min-width' if HORIZONTAL is
337 * non-nil) parameter of FRAME is non-nil thus explicitly specifying the
338 * value to be returned. In that latter case IGNORE is ignored.
340 * If `frame-windows-min-size' is called, it will make sure that the
341 * return value accommodates all windows of FRAME respecting the values
342 * of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil).
343 * With IGNORE non-nil the values of these variables are ignored.
345 * In either case, never return a value less than 1. For TTY frames,
346 * additionally limit the minimum frame height to a value large enough
347 * to support the menu bar, the mode line, and the echo area.
349 static int
350 frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
351 Lisp_Object ignore, Lisp_Object pixelwise)
353 struct frame *f = XFRAME (frame);
354 Lisp_Object par_size;
355 int retval;
357 if ((!NILP (horizontal)
358 && NUMBERP (par_size = get_frame_param (f, Qmin_width)))
359 || (NILP (horizontal)
360 && NUMBERP (par_size = get_frame_param (f, Qmin_height))))
362 int min_size = XINT (par_size);
364 /* Don't allow phantom frames. */
365 if (min_size < 1)
366 min_size = 1;
368 retval = (NILP (pixelwise)
369 ? min_size
370 : min_size * (NILP (horizontal)
371 ? FRAME_LINE_HEIGHT (f)
372 : FRAME_COLUMN_WIDTH (f)));
374 else
375 retval = XINT (call4 (Qframe_windows_min_size, frame, horizontal,
376 ignore, pixelwise));
377 /* Don't allow too small height of text-mode frames, or else cm.c
378 might abort in cmcheckmagic. */
379 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
381 int min_height = (FRAME_MENU_BAR_LINES (f)
382 + FRAME_WANTS_MODELINE_P (f)
383 + 2); /* one text line and one echo-area line */
384 if (retval < min_height)
385 retval = min_height;
388 return retval;
392 #ifdef HAVE_WINDOW_SYSTEM
394 * keep_ratio:
396 * Preserve ratios of frame F which usually happens after its parent
397 * frame P got resized. OLD_WIDTH, OLD_HEIGHT specifies the old native
398 * size of F's parent, NEW_WIDTH and NEW_HEIGHT its new size.
400 * Adjust F's width if F's 'keep_ratio' parameter is non-nil and, if
401 * it is a cons, its car is not 'height-only'. Adjust F's height if F's
402 * 'keep_ratio' parameter is non-nil and, if it is a cons, its car
403 * is not 'width-only'.
405 * Adjust F's left position if F's 'keep_ratio' parameter is non-nil
406 * and, if its is a cons, its cdr is non-nil and not 'top-only'. Adjust
407 * F's top position if F's 'keep_ratio' parameter is non-nil and, if
408 * its is a cons, its cdr is non-nil and not 'left-only'.
410 * Note that when positional adjustment is requested but the size of F
411 * should remain unaltered in the corresponding direction, this routine
412 * tries to constrain F to its parent frame - something which usually
413 * happens when the parent frame shrinks. This means, however, that
414 * when the parent frame is re-enlarged later, the child's original
415 * position will not get restored to its pre-shrinking value.
417 * This routine is currently useful for child frames only. It might be
418 * eventually useful when moving non-child frames between monitors with
419 * different resolutions.
421 static void
422 keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
423 int new_width, int new_height)
425 Lisp_Object keep_ratio = get_frame_param (f, Qkeep_ratio);
428 if (!NILP (keep_ratio))
430 double width_factor = (double)new_width / (double)old_width;
431 double height_factor = (double)new_height / (double)old_height;
432 int pixel_width, pixel_height, pos_x, pos_y;
434 if (!CONSP (keep_ratio) || !NILP (Fcdr (keep_ratio)))
436 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qtop_only))
437 pos_x = f->left_pos;
438 else
440 pos_x = (int)(f->left_pos * width_factor + 0.5);
442 if (CONSP (keep_ratio)
443 && (NILP (Fcar (keep_ratio))
444 || EQ (Fcar (keep_ratio), Qheight_only))
445 && p->pixel_width - f->pixel_width < pos_x)
447 int p_f_width = p->pixel_width - f->pixel_width;
449 if (p_f_width <= 0)
450 pos_x = 0;
451 else
452 pos_x = (int)(p_f_width * width_factor * 0.5 + 0.5);
455 f->left_pos = pos_x;
458 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qleft_only))
459 pos_y = f->top_pos;
460 else
462 pos_y = (int)(f->top_pos * height_factor + 0.5);
464 if (CONSP (keep_ratio)
465 && (NILP (Fcar (keep_ratio))
466 || EQ (Fcar (keep_ratio), Qwidth_only))
467 && p->pixel_height - f->pixel_height < pos_y)
468 /* When positional adjustment was requested and the
469 width of F should remain unaltered, try to constrain
470 F to its parent. This means that when the parent
471 frame is enlarged later the child's original position
472 won't get restored. */
474 int p_f_height = p->pixel_height - f->pixel_height;
476 if (p_f_height <= 0)
477 pos_y = 0;
478 else
479 pos_y = (int)(p_f_height * height_factor * 0.5 + 0.5);
482 f->top_pos = pos_y;
485 x_set_offset (f, pos_x, pos_y, -1);
488 if (!CONSP (keep_ratio) || !NILP (Fcar (keep_ratio)))
490 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qheight_only))
491 pixel_width = -1;
492 else
494 pixel_width = (int)(f->pixel_width * width_factor + 0.5);
495 pixel_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixel_width);
498 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qwidth_only))
499 pixel_height = -1;
500 else
502 pixel_height = (int)(f->pixel_height * height_factor + 0.5);
503 pixel_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixel_height);
506 adjust_frame_size (f, pixel_width, pixel_height, 1, 0,
507 Qkeep_ratio);
511 #endif
515 * adjust_frame_size:
517 * Adjust size of frame F. NEW_WIDTH and NEW_HEIGHT specify the new
518 * text size of F in pixels. A value of -1 means no change is requested
519 * for that direction (but the frame may still have to be resized to
520 * accommodate windows with their minimum sizes). This can either issue
521 * a request to resize the frame externally (via x_set_window_size), to
522 * resize the frame internally (via resize_frame_windows) or do nothing
523 * at all.
525 * The argument INHIBIT can assume the following values:
527 * 0 means to unconditionally call x_set_window_size even if sizes
528 * apparently do not change. Fx_create_frame uses this to pass the
529 * initial size to the window manager.
531 * 1 means to call x_set_window_size if the native frame size really
532 * changes. Fset_frame_size, Fset_frame_height, ... use this.
534 * 2 means to call x_set_window_size provided frame_inhibit_resize
535 * allows it. The menu and tool bar code use this ("3" won't work
536 * here in general because menu and tool bar are often not counted in
537 * the frame's text height).
539 * 3 means call x_set_window_size if window minimum sizes must be
540 * preserved or frame_inhibit_resize allows it. x_set_left_fringe,
541 * x_set_scroll_bar_width, x_new_font ... use (or should use) this.
543 * 4 means call x_set_window_size only if window minimum sizes must be
544 * preserved. x_set_right_divider_width, x_set_border_width and the
545 * code responsible for wrapping the tool bar use this.
547 * 5 means to never call x_set_window_size. change_frame_size uses
548 * this.
550 * Note that even when x_set_window_size is not called, individual
551 * windows may have to be resized (via `window--sanitize-window-sizes')
552 * in order to support minimum size constraints.
554 * PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
555 * symbol of the parameter changed (like `menu-bar-lines', `font', ...).
556 * This is passed on to frame_inhibit_resize to let the latter decide on
557 * a case-by-case basis whether the frame may be resized externally.
559 void
560 adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
561 bool pretend, Lisp_Object parameter)
563 int unit_width = FRAME_COLUMN_WIDTH (f);
564 int unit_height = FRAME_LINE_HEIGHT (f);
565 int old_pixel_width = FRAME_PIXEL_WIDTH (f);
566 int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
567 int old_cols = FRAME_COLS (f);
568 int old_lines = FRAME_LINES (f);
569 int new_pixel_width, new_pixel_height;
570 /* The following two values are calculated from the old frame pixel
571 sizes and any "new" settings for tool bar, menu bar and internal
572 borders. We do it this way to detect whether we have to call
573 x_set_window_size as consequence of the new settings. */
574 int windows_width = FRAME_WINDOWS_WIDTH (f);
575 int windows_height = FRAME_WINDOWS_HEIGHT (f);
576 int min_windows_width, min_windows_height;
577 /* These are a bit tedious, maybe we should use a macro. */
578 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
579 int old_windows_width = WINDOW_PIXEL_WIDTH (r);
580 int old_windows_height
581 = (WINDOW_PIXEL_HEIGHT (r)
582 + ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
583 ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
584 : 0));
585 int new_windows_width, new_windows_height;
586 int old_text_width = FRAME_TEXT_WIDTH (f);
587 int old_text_height = FRAME_TEXT_HEIGHT (f);
588 /* If a size is < 0 use the old value. */
589 int new_text_width = (new_width >= 0) ? new_width : old_text_width;
590 int new_text_height = (new_height >= 0) ? new_height : old_text_height;
591 int new_cols, new_lines;
592 bool inhibit_horizontal, inhibit_vertical;
593 Lisp_Object frame;
595 XSETFRAME (frame, f);
597 frame_size_history_add
598 (f, Qadjust_frame_size_1, new_text_width, new_text_height,
599 list2 (parameter, make_number (inhibit)));
601 /* The following two values are calculated from the old window body
602 sizes and any "new" settings for scroll bars, dividers, fringes and
603 margins (though the latter should have been processed already). */
604 min_windows_width
605 = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
606 min_windows_height
607 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
609 if (inhibit >= 2 && inhibit <= 4)
610 /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
611 within the limits and either resizing is inhibited or INHIBIT
612 equals 4. */
614 inhibit_horizontal = (windows_width >= min_windows_width
615 && (inhibit == 4
616 || frame_inhibit_resize (f, true, parameter)));
617 inhibit_vertical = (windows_height >= min_windows_height
618 && (inhibit == 4
619 || frame_inhibit_resize (f, false, parameter)));
621 else
622 /* Otherwise inhibit if INHIBIT equals 5. */
623 inhibit_horizontal = inhibit_vertical = inhibit == 5;
625 new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
626 ? old_pixel_width
627 : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
628 min_windows_width
629 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
630 new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
631 new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
632 new_cols = new_text_width / unit_width;
634 new_pixel_height = ((inhibit_vertical && (inhibit < 5))
635 ? old_pixel_height
636 : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
637 min_windows_height
638 + FRAME_TOP_MARGIN_HEIGHT (f)
639 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
640 new_windows_height = (new_pixel_height
641 - FRAME_TOP_MARGIN_HEIGHT (f)
642 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
643 new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
644 new_lines = new_text_height / unit_height;
646 #ifdef HAVE_WINDOW_SYSTEM
647 if (FRAME_WINDOW_P (f)
648 && f->can_x_set_window_size
649 && ((!inhibit_horizontal
650 && (new_pixel_width != old_pixel_width
651 || inhibit == 0 || inhibit == 2))
652 || (!inhibit_vertical
653 && (new_pixel_height != old_pixel_height
654 || inhibit == 0 || inhibit == 2))))
655 /* We are either allowed to change the frame size or the minimum
656 sizes request such a change. Do not care for fixing minimum
657 sizes here, we do that eventually when we're called from
658 change_frame_size. */
660 /* Make sure we respect fullheight and fullwidth. */
661 if (inhibit_horizontal)
662 new_text_width = old_text_width;
663 else if (inhibit_vertical)
664 new_text_height = old_text_height;
666 frame_size_history_add
667 (f, Qadjust_frame_size_2, new_text_width, new_text_height,
668 list2 (inhibit_horizontal ? Qt : Qnil,
669 inhibit_vertical ? Qt : Qnil));
671 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
672 f->resized_p = true;
674 return;
676 #endif
678 if (new_text_width == old_text_width
679 && new_text_height == old_text_height
680 && new_windows_width == old_windows_width
681 && new_windows_height == old_windows_height
682 && new_pixel_width == old_pixel_width
683 && new_pixel_height == old_pixel_height
684 && new_cols == old_cols
685 && new_lines == old_lines)
686 /* No change. Sanitize window sizes and return. */
688 sanitize_window_sizes (Qt);
689 sanitize_window_sizes (Qnil);
691 return;
694 block_input ();
696 #ifdef MSDOS
697 /* We only can set screen dimensions to certain values supported by
698 our video hardware. Try to find the smallest size greater or
699 equal to the requested dimensions, while accounting for the fact
700 that the menu-bar lines are not counted in the frame height. */
701 int dos_new_lines = new_lines + FRAME_TOP_MARGIN (f);
702 dos_set_window_size (&dos_new_lines, &new_cols);
703 new_lines = dos_new_lines - FRAME_TOP_MARGIN (f);
704 #endif
706 if (new_windows_width != old_windows_width)
708 resize_frame_windows (f, new_windows_width, 1, 1);
710 /* MSDOS frames cannot PRETEND, as they change frame size by
711 manipulating video hardware. */
712 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
713 FrameCols (FRAME_TTY (f)) = new_cols;
715 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
716 if (WINDOWP (f->tool_bar_window))
718 XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
719 XWINDOW (f->tool_bar_window)->total_cols
720 = new_windows_width / unit_width;
722 #endif
724 else if (new_cols != old_cols)
725 call2 (Qwindow__pixel_to_total, frame, Qt);
727 if (new_windows_height != old_windows_height
728 /* When the top margin has changed we have to recalculate the top
729 edges of all windows. No such calculation is necessary for the
730 left edges. */
731 || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
733 resize_frame_windows (f, new_windows_height, 0, 1);
735 /* MSDOS frames cannot PRETEND, as they change frame size by
736 manipulating video hardware. */
737 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
738 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
740 else if (new_lines != old_lines)
741 call2 (Qwindow__pixel_to_total, frame, Qnil);
743 frame_size_history_add
744 (f, Qadjust_frame_size_3, new_text_width, new_text_height,
745 list4 (make_number (old_pixel_width), make_number (old_pixel_height),
746 make_number (new_pixel_width), make_number (new_pixel_height)));
748 /* Assign new sizes. */
749 FRAME_TEXT_WIDTH (f) = new_text_width;
750 FRAME_TEXT_HEIGHT (f) = new_text_height;
751 FRAME_PIXEL_WIDTH (f) = new_pixel_width;
752 FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
753 SET_FRAME_COLS (f, new_cols);
754 SET_FRAME_LINES (f, new_lines);
757 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
758 int text_area_x, text_area_y, text_area_width, text_area_height;
760 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
761 &text_area_height);
762 if (w->cursor.x >= text_area_x + text_area_width)
763 w->cursor.hpos = w->cursor.x = 0;
764 if (w->cursor.y >= text_area_y + text_area_height)
765 w->cursor.vpos = w->cursor.y = 0;
768 /* Sanitize window sizes. */
769 sanitize_window_sizes (Qt);
770 sanitize_window_sizes (Qnil);
772 adjust_frame_glyphs (f);
773 calculate_costs (f);
774 SET_FRAME_GARBAGED (f);
776 /* A frame was "resized" if one of its pixelsizes changed, even if its
777 X window wasn't resized at all. */
778 f->resized_p = (new_pixel_width != old_pixel_width
779 || new_pixel_height != old_pixel_height);
781 unblock_input ();
783 #ifdef HAVE_WINDOW_SYSTEM
785 /* Adjust size of F's child frames. */
786 Lisp_Object frames, frame1;
788 FOR_EACH_FRAME (frames, frame1)
789 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f)
790 keep_ratio (XFRAME (frame1), f, old_pixel_width, old_pixel_height,
791 new_pixel_width, new_pixel_height);
793 #endif
796 /* Allocate basically initialized frame. */
798 static struct frame *
799 allocate_frame (void)
801 return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
804 struct frame *
805 make_frame (bool mini_p)
807 Lisp_Object frame;
808 struct frame *f;
809 struct window *rw, *mw UNINIT;
810 Lisp_Object root_window;
811 Lisp_Object mini_window;
813 f = allocate_frame ();
814 XSETFRAME (frame, f);
816 #ifdef USE_GTK
817 /* Initialize Lisp data. Note that allocate_frame initializes all
818 Lisp data to nil, so do it only for slots which should not be nil. */
819 fset_tool_bar_position (f, Qtop);
820 #endif
822 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
823 non-Lisp data, so do it only for slots which should not be zero.
824 To avoid subtle bugs and for the sake of readability, it's better to
825 initialize enum members explicitly even if their values are zero. */
826 f->wants_modeline = true;
827 f->redisplay = true;
828 f->garbaged = true;
829 f->can_x_set_window_size = false;
830 f->after_make_frame = false;
831 f->inhibit_horizontal_resize = false;
832 f->inhibit_vertical_resize = false;
833 f->tool_bar_redisplayed = false;
834 f->tool_bar_resized = false;
835 f->column_width = 1; /* !FRAME_WINDOW_P value. */
836 f->line_height = 1; /* !FRAME_WINDOW_P value. */
837 #ifdef HAVE_WINDOW_SYSTEM
838 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
839 f->horizontal_scroll_bars = false;
840 f->want_fullscreen = FULLSCREEN_NONE;
841 f->undecorated = false;
842 f->no_special_glyphs = false;
843 #ifndef HAVE_NTGUI
844 f->override_redirect = false;
845 #endif
846 f->skip_taskbar = false;
847 f->no_focus_on_map = false;
848 f->no_accept_focus = false;
849 f->z_group = z_group_none;
850 f->tooltip = false;
851 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
852 f->last_tool_bar_item = -1;
853 #endif
854 #ifdef NS_IMPL_COCOA
855 f->ns_appearance = ns_appearance_aqua;
856 f->ns_transparent_titlebar = false;
857 #endif
858 #endif
860 root_window = make_window ();
861 rw = XWINDOW (root_window);
862 if (mini_p)
864 mini_window = make_window ();
865 mw = XWINDOW (mini_window);
866 wset_next (rw, mini_window);
867 wset_prev (mw, root_window);
868 mw->mini = 1;
869 wset_frame (mw, frame);
870 fset_minibuffer_window (f, mini_window);
871 store_frame_param (f, Qminibuffer, Qt);
873 else
875 mini_window = Qnil;
876 wset_next (rw, Qnil);
877 fset_minibuffer_window (f, Qnil);
880 wset_frame (rw, frame);
882 /* 10 is arbitrary,
883 just so that there is "something there."
884 Correct size will be set up later with adjust_frame_size. */
886 SET_FRAME_COLS (f, 10);
887 SET_FRAME_LINES (f, 10);
888 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
889 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
891 rw->total_cols = 10;
892 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
893 rw->total_lines = mini_p ? 9 : 10;
894 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
896 if (mini_p)
898 mw->top_line = rw->total_lines;
899 mw->pixel_top = rw->pixel_height;
900 mw->total_cols = rw->total_cols;
901 mw->pixel_width = rw->pixel_width;
902 mw->total_lines = 1;
903 mw->pixel_height = FRAME_LINE_HEIGHT (f);
906 /* Choose a buffer for the frame's root window. */
908 Lisp_Object buf = Fcurrent_buffer ();
910 /* If current buffer is hidden, try to find another one. */
911 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
912 buf = other_buffer_safely (buf);
914 /* Use set_window_buffer, not Fset_window_buffer, and don't let
915 hooks be run by it. The reason is that the whole frame/window
916 arrangement is not yet fully initialized at this point. Windows
917 don't have the right size, glyph matrices aren't initialized
918 etc. Running Lisp functions at this point surely ends in a
919 SEGV. */
920 set_window_buffer (root_window, buf, 0, 0);
921 fset_buffer_list (f, list1 (buf));
924 if (mini_p)
926 set_window_buffer (mini_window,
927 (NILP (Vminibuffer_list)
928 ? get_minibuffer (0)
929 : Fcar (Vminibuffer_list)),
930 0, 0);
931 /* No horizontal scroll bars in minibuffers. */
932 wset_horizontal_scroll_bar (mw, Qnil);
935 fset_root_window (f, root_window);
936 fset_selected_window (f, root_window);
937 /* Make sure this window seems more recently used than
938 a newly-created, never-selected window. */
939 XWINDOW (f->selected_window)->use_time = ++window_select_count;
941 return f;
944 #ifdef HAVE_WINDOW_SYSTEM
945 /* Make a frame using a separate minibuffer window on another frame.
946 MINI_WINDOW is the minibuffer window to use. nil means use the
947 default (the global minibuffer). */
949 struct frame *
950 make_frame_without_minibuffer (Lisp_Object mini_window, KBOARD *kb,
951 Lisp_Object display)
953 struct frame *f;
955 if (!NILP (mini_window))
956 CHECK_LIVE_WINDOW (mini_window);
958 if (!NILP (mini_window)
959 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
960 error ("Frame and minibuffer must be on the same terminal");
962 /* Make a frame containing just a root window. */
963 f = make_frame (0);
965 if (NILP (mini_window))
967 /* Use default-minibuffer-frame if possible. */
968 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
969 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
971 Lisp_Object frame_dummy;
973 XSETFRAME (frame_dummy, f);
974 /* If there's no minibuffer frame to use, create one. */
975 kset_default_minibuffer_frame
976 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
979 mini_window
980 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
983 fset_minibuffer_window (f, mini_window);
984 store_frame_param (f, Qminibuffer, mini_window);
986 /* Make the chosen minibuffer window display the proper minibuffer,
987 unless it is already showing a minibuffer. */
988 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
989 /* Use set_window_buffer instead of Fset_window_buffer (see
990 discussion of bug#11984, bug#12025, bug#12026). */
991 set_window_buffer (mini_window,
992 (NILP (Vminibuffer_list)
993 ? get_minibuffer (0)
994 : Fcar (Vminibuffer_list)), 0, 0);
995 return f;
998 /* Make a frame containing only a minibuffer window. */
1000 struct frame *
1001 make_minibuffer_frame (void)
1003 /* First make a frame containing just a root window, no minibuffer. */
1005 register struct frame *f = make_frame (0);
1006 register Lisp_Object mini_window;
1007 register Lisp_Object frame;
1009 XSETFRAME (frame, f);
1011 f->auto_raise = 0;
1012 f->auto_lower = 0;
1013 f->no_split = 1;
1014 f->wants_modeline = 0;
1016 /* Now label the root window as also being the minibuffer.
1017 Avoid infinite looping on the window chain by marking next pointer
1018 as nil. */
1020 mini_window = f->root_window;
1021 fset_minibuffer_window (f, mini_window);
1022 store_frame_param (f, Qminibuffer, Qonly);
1023 XWINDOW (mini_window)->mini = 1;
1024 wset_next (XWINDOW (mini_window), Qnil);
1025 wset_prev (XWINDOW (mini_window), Qnil);
1026 wset_frame (XWINDOW (mini_window), frame);
1028 /* Put the proper buffer in that window. */
1030 /* Use set_window_buffer instead of Fset_window_buffer (see
1031 discussion of bug#11984, bug#12025, bug#12026). */
1032 set_window_buffer (mini_window,
1033 (NILP (Vminibuffer_list)
1034 ? get_minibuffer (0)
1035 : Fcar (Vminibuffer_list)), 0, 0);
1036 return f;
1038 #endif /* HAVE_WINDOW_SYSTEM */
1040 /* Construct a frame that refers to a terminal. */
1042 static printmax_t tty_frame_count;
1044 struct frame *
1045 make_initial_frame (void)
1047 struct frame *f;
1048 struct terminal *terminal;
1049 Lisp_Object frame;
1051 eassert (initial_kboard);
1053 /* The first call must initialize Vframe_list. */
1054 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
1055 Vframe_list = Qnil;
1057 terminal = init_initial_terminal ();
1059 f = make_frame (1);
1060 XSETFRAME (frame, f);
1062 Vframe_list = Fcons (frame, Vframe_list);
1064 tty_frame_count = 1;
1065 fset_name (f, build_pure_c_string ("F1"));
1067 SET_FRAME_VISIBLE (f, 1);
1069 f->output_method = terminal->type;
1070 f->terminal = terminal;
1071 f->terminal->reference_count++;
1072 f->output_data.nothing = 0;
1074 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1075 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1077 #ifdef HAVE_WINDOW_SYSTEM
1078 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1079 f->horizontal_scroll_bars = false;
1080 #endif
1082 /* The default value of menu-bar-mode is t. */
1083 set_menu_bar_lines (f, make_number (1), Qnil);
1085 /* Allocate glyph matrices. */
1086 adjust_frame_glyphs (f);
1088 if (!noninteractive)
1089 init_frame_faces (f);
1091 last_nonminibuf_frame = f;
1093 f->can_x_set_window_size = true;
1094 f->after_make_frame = true;
1096 return f;
1100 static struct frame *
1101 make_terminal_frame (struct terminal *terminal)
1103 register struct frame *f;
1104 Lisp_Object frame;
1105 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
1107 if (!terminal->name)
1108 error ("Terminal is not live, can't create new frames on it");
1110 f = make_frame (1);
1112 XSETFRAME (frame, f);
1113 Vframe_list = Fcons (frame, Vframe_list);
1115 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
1117 SET_FRAME_VISIBLE (f, 1);
1119 f->terminal = terminal;
1120 f->terminal->reference_count++;
1121 #ifdef MSDOS
1122 f->output_data.tty->display_info = &the_only_display_info;
1123 if (!inhibit_window_system
1124 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
1125 || XFRAME (selected_frame)->output_method == output_msdos_raw))
1126 f->output_method = output_msdos_raw;
1127 else
1128 f->output_method = output_termcap;
1129 #else /* not MSDOS */
1130 f->output_method = output_termcap;
1131 create_tty_output (f);
1132 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1133 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1134 #endif /* not MSDOS */
1136 #ifdef HAVE_WINDOW_SYSTEM
1137 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1138 f->horizontal_scroll_bars = false;
1139 #endif
1141 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
1142 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
1143 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
1144 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
1146 /* Set the top frame to the newly created frame. */
1147 if (FRAMEP (FRAME_TTY (f)->top_frame)
1148 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
1149 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
1151 FRAME_TTY (f)->top_frame = frame;
1153 if (!noninteractive)
1154 init_frame_faces (f);
1156 return f;
1159 /* Get a suitable value for frame parameter PARAMETER for a newly
1160 created frame, based on (1) the user-supplied frame parameter
1161 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
1163 static Lisp_Object
1164 get_future_frame_param (Lisp_Object parameter,
1165 Lisp_Object supplied_parms,
1166 char *current_value)
1168 Lisp_Object result;
1170 result = Fassq (parameter, supplied_parms);
1171 if (NILP (result))
1172 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
1173 if (NILP (result) && current_value != NULL)
1174 result = build_string (current_value);
1175 if (!NILP (result) && !STRINGP (result))
1176 result = XCDR (result);
1177 if (NILP (result) || !STRINGP (result))
1178 result = Qnil;
1180 return result;
1183 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1184 1, 1, 0,
1185 doc: /* Create an additional terminal frame, possibly on another terminal.
1186 This function takes one argument, an alist specifying frame parameters.
1188 You can create multiple frames on a single text terminal, but only one
1189 of them (the selected terminal frame) is actually displayed.
1191 In practice, generally you don't need to specify any parameters,
1192 except when you want to create a new frame on another terminal.
1193 In that case, the `tty' parameter specifies the device file to open,
1194 and the `tty-type' parameter specifies the terminal type. Example:
1196 (make-terminal-frame \\='((tty . "/dev/pts/5") (tty-type . "xterm")))
1198 Note that changing the size of one terminal frame automatically
1199 affects all frames on the same terminal device. */)
1200 (Lisp_Object parms)
1202 struct frame *f;
1203 struct terminal *t = NULL;
1204 Lisp_Object frame, tem;
1205 struct frame *sf = SELECTED_FRAME ();
1207 #ifdef MSDOS
1208 if (sf->output_method != output_msdos_raw
1209 && sf->output_method != output_termcap)
1210 emacs_abort ();
1211 #else /* not MSDOS */
1213 #ifdef WINDOWSNT /* This should work now! */
1214 if (sf->output_method != output_termcap)
1215 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
1216 #endif
1217 #endif /* not MSDOS */
1220 Lisp_Object terminal;
1222 terminal = Fassq (Qterminal, parms);
1223 if (CONSP (terminal))
1225 terminal = XCDR (terminal);
1226 t = decode_live_terminal (terminal);
1228 #ifdef MSDOS
1229 if (t && t != the_only_display_info.terminal)
1230 /* msdos.c assumes a single tty_display_info object. */
1231 error ("Multiple terminals are not supported on this platform");
1232 if (!t)
1233 t = the_only_display_info.terminal;
1234 #endif
1237 if (!t)
1239 char *name = 0, *type = 0;
1240 Lisp_Object tty, tty_type;
1241 USE_SAFE_ALLOCA;
1243 tty = get_future_frame_param
1244 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1245 ? FRAME_TTY (XFRAME (selected_frame))->name
1246 : NULL));
1247 if (!NILP (tty))
1248 SAFE_ALLOCA_STRING (name, tty);
1250 tty_type = get_future_frame_param
1251 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1252 ? FRAME_TTY (XFRAME (selected_frame))->type
1253 : NULL));
1254 if (!NILP (tty_type))
1255 SAFE_ALLOCA_STRING (type, tty_type);
1257 t = init_tty (name, type, 0); /* Errors are not fatal. */
1258 SAFE_FREE ();
1261 f = make_terminal_frame (t);
1264 int width, height;
1265 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1266 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
1267 5, 0, Qterminal_frame);
1270 adjust_frame_glyphs (f);
1271 calculate_costs (f);
1272 XSETFRAME (frame, f);
1274 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
1275 store_in_alist (&parms, Qtty,
1276 (t->display_info.tty->name
1277 ? build_string (t->display_info.tty->name)
1278 : Qnil));
1279 /* On terminal frames the `minibuffer' frame parameter is always
1280 virtually t. Avoid that a different value in parms causes
1281 complaints, see Bug#24758. */
1282 store_in_alist (&parms, Qminibuffer, Qt);
1283 Fmodify_frame_parameters (frame, parms);
1285 /* Make the frame face alist be frame-specific, so that each
1286 frame could change its face definitions independently. */
1287 fset_face_alist (f, Fcopy_alist (sf->face_alist));
1288 /* Simple Fcopy_alist isn't enough, because we need the contents of
1289 the vectors which are the CDRs of associations in face_alist to
1290 be copied as well. */
1291 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
1292 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
1294 f->can_x_set_window_size = true;
1295 f->after_make_frame = true;
1297 return frame;
1301 /* Perform the switch to frame FRAME.
1303 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
1304 FRAME1 as frame.
1306 If TRACK is non-zero and the frame that currently has the focus
1307 redirects its focus to the selected frame, redirect that focused
1308 frame's focus to FRAME instead.
1310 FOR_DELETION non-zero means that the selected frame is being
1311 deleted, which includes the possibility that the frame's terminal
1312 is dead.
1314 The value of NORECORD is passed as argument to Fselect_window. */
1316 Lisp_Object
1317 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1319 struct frame *sf = SELECTED_FRAME (), *f;
1321 /* If FRAME is a switch-frame event, extract the frame we should
1322 switch to. */
1323 if (CONSP (frame)
1324 && EQ (XCAR (frame), Qswitch_frame)
1325 && CONSP (XCDR (frame)))
1326 frame = XCAR (XCDR (frame));
1328 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1329 a switch-frame event to arrive after a frame is no longer live,
1330 especially when deleting the initial frame during startup. */
1331 CHECK_FRAME (frame);
1332 f = XFRAME (frame);
1333 if (!FRAME_LIVE_P (f))
1334 return Qnil;
1335 else if (f == sf)
1336 return frame;
1338 /* If a frame's focus has been redirected toward the currently
1339 selected frame, we should change the redirection to point to the
1340 newly selected frame. This means that if the focus is redirected
1341 from a minibufferless frame to a surrogate minibuffer frame, we
1342 can use `other-window' to switch between all the frames using
1343 that minibuffer frame, and the focus redirection will follow us
1344 around. */
1345 #if 0
1346 /* This is too greedy; it causes inappropriate focus redirection
1347 that's hard to get rid of. */
1348 if (track)
1350 Lisp_Object tail;
1352 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1354 Lisp_Object focus;
1356 if (!FRAMEP (XCAR (tail)))
1357 emacs_abort ();
1359 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1361 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1362 Fredirect_frame_focus (XCAR (tail), frame);
1365 #else /* ! 0 */
1366 /* Instead, apply it only to the frame we're pointing to. */
1367 #ifdef HAVE_WINDOW_SYSTEM
1368 if (track && FRAME_WINDOW_P (f))
1370 Lisp_Object focus, xfocus;
1372 xfocus = x_get_focus_frame (f);
1373 if (FRAMEP (xfocus))
1375 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1376 if ((FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1377 /* Redirect frame focus also when FRAME has its minibuffer
1378 window on the selected frame (see Bug#24500). */
1379 || (NILP (focus)
1380 && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))
1381 Fredirect_frame_focus (xfocus, frame);
1384 #endif /* HAVE_X_WINDOWS */
1385 #endif /* ! 0 */
1387 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1388 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1390 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
1392 struct tty_display_info *tty = FRAME_TTY (f);
1393 Lisp_Object top_frame = tty->top_frame;
1395 /* Don't mark the frame garbaged and/or obscured if we are
1396 switching to the frame that is already the top frame of that
1397 TTY. */
1398 if (!EQ (frame, top_frame))
1400 if (FRAMEP (top_frame))
1401 /* Mark previously displayed frame as now obscured. */
1402 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1403 SET_FRAME_VISIBLE (f, 1);
1404 /* If the new TTY frame changed dimensions, we need to
1405 resync term.c's idea of the frame size with the new
1406 frame's data. */
1407 if (FRAME_COLS (f) != FrameCols (tty))
1408 FrameCols (tty) = FRAME_COLS (f);
1409 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1410 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1412 tty->top_frame = frame;
1415 selected_frame = frame;
1416 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1417 last_nonminibuf_frame = XFRAME (selected_frame);
1419 Fselect_window (f->selected_window, norecord);
1421 /* We want to make sure that the next event generates a frame-switch
1422 event to the appropriate frame. This seems kludgy to me, but
1423 before you take it out, make sure that evaluating something like
1424 (select-window (frame-root-window (make-frame))) doesn't end up
1425 with your typing being interpreted in the new frame instead of
1426 the one you're actually typing in. */
1427 #ifdef HAVE_WINDOW_SYSTEM
1428 if (!frame_ancestor_p (f, sf))
1429 #endif
1430 internal_last_event_frame = Qnil;
1432 return frame;
1435 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1436 doc: /* Select FRAME.
1437 Subsequent editing commands apply to its selected window.
1438 Optional argument NORECORD means to neither change the order of
1439 recently selected windows nor the buffer list.
1441 The selection of FRAME lasts until the next time the user does
1442 something to select a different frame, or until the next time
1443 this function is called. If you are using a window system, the
1444 previously selected frame may be restored as the selected frame
1445 when returning to the command loop, because it still may have
1446 the window system's input focus. On a text terminal, the next
1447 redisplay will display FRAME.
1449 This function returns FRAME, or nil if FRAME has been deleted. */)
1450 (Lisp_Object frame, Lisp_Object norecord)
1452 return do_switch_frame (frame, 1, 0, norecord);
1455 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1456 doc: /* Handle a switch-frame event EVENT.
1457 Switch-frame events are usually bound to this function.
1458 A switch-frame event tells Emacs that the window manager has requested
1459 that the user's events be directed to the frame mentioned in the event.
1460 This function selects the selected window of the frame of EVENT.
1462 If EVENT is frame object, handle it as if it were a switch-frame event
1463 to that frame. */)
1464 (Lisp_Object event)
1466 Lisp_Object value;
1468 /* Preserve prefix arg that the command loop just cleared. */
1469 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1470 run_hook (Qmouse_leave_buffer_hook);
1471 /* `switch-frame' implies a focus in. */
1472 value = do_switch_frame (event, 0, 0, Qnil);
1473 call1 (intern ("handle-focus-in"), event);
1474 return value;
1477 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1478 doc: /* Return the frame that is now selected. */)
1479 (void)
1481 return selected_frame;
1484 DEFUN ("frame-list", Fframe_list, Sframe_list,
1485 0, 0, 0,
1486 doc: /* Return a list of all live frames.
1487 The return value does not include any tooltip frame. */)
1488 (void)
1490 #ifdef HAVE_WINDOW_SYSTEM
1491 Lisp_Object list = Qnil, tail, frame;
1493 FOR_EACH_FRAME (tail, frame)
1494 if (!FRAME_TOOLTIP_P (XFRAME (frame)))
1495 list = Fcons (frame, list);
1496 /* Reverse list for consistency with the !HAVE_WINDOW_SYSTEM case. */
1497 return Fnreverse (list);
1498 #else /* !HAVE_WINDOW_SYSTEM */
1499 return Fcopy_sequence (Vframe_list);
1500 #endif /* HAVE_WINDOW_SYSTEM */
1503 DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
1504 0, 1, 0,
1505 doc: /* Return the parent frame of FRAME.
1506 The parent frame of FRAME is the Emacs frame whose window-system window
1507 is the parent window of FRAME's window-system window. When such a frame
1508 exists, FRAME is considered a child frame of that frame.
1510 Return nil if FRAME has no parent frame. This means that FRAME's
1511 window-system window is either a "top-level" window (a window whose
1512 parent window is the window-system's root window) or an embedded window
1513 \(a window whose parent window is owned by some other application). */)
1514 (Lisp_Object frame)
1516 struct frame *f = decode_live_frame (frame);
1517 struct frame *p = FRAME_PARENT_FRAME (f);
1518 Lisp_Object parent;
1520 /* Can't return f->parent_frame directly since it might not be defined
1521 for this platform. */
1522 if (p)
1524 XSETFRAME (parent, p);
1526 return parent;
1528 else
1529 return Qnil;
1532 #ifdef HAVE_WINDOW_SYSTEM
1533 bool
1534 frame_ancestor_p (struct frame *af, struct frame *df)
1536 struct frame *pf = FRAME_PARENT_FRAME (df);
1538 while (pf)
1540 if (pf == af)
1541 return true;
1542 else
1543 pf = FRAME_PARENT_FRAME (pf);
1546 return false;
1548 #endif
1550 DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1551 2, 2, 0,
1552 doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
1553 ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
1554 parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
1555 ANCESTOR and DESCENDANT must be live frames and default to the selected
1556 frame. */)
1557 (Lisp_Object ancestor, Lisp_Object descendant)
1559 #ifdef HAVE_WINDOW_SYSTEM
1560 struct frame *af = decode_live_frame (ancestor);
1561 struct frame *df = decode_live_frame (descendant);
1563 return frame_ancestor_p (af, df) ? Qt : Qnil;
1564 #else
1565 return Qnil;
1566 #endif
1569 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1570 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1571 If MINIBUF is nil, do not consider minibuffer-only candidate.
1572 If MINIBUF is `visible', do not consider an invisible candidate.
1573 If MINIBUF is a window, consider only its own frame and candidate now
1574 using that window as the minibuffer.
1575 If MINIBUF is 0, consider candidate if it is visible or iconified.
1576 Otherwise consider any candidate and return nil if CANDIDATE is not
1577 acceptable. */
1579 static Lisp_Object
1580 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1582 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1584 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1585 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1586 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1587 && FRAME_TTY (c) == FRAME_TTY (f)))
1589 if (!NILP (get_frame_param (c, Qno_other_frame)))
1590 return Qnil;
1591 else if (NILP (minibuf))
1593 if (!FRAME_MINIBUF_ONLY_P (c))
1594 return candidate;
1596 else if (EQ (minibuf, Qvisible))
1598 if (FRAME_VISIBLE_P (c))
1599 return candidate;
1601 else if (WINDOWP (minibuf))
1603 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1604 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1605 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1606 FRAME_FOCUS_FRAME (c)))
1607 return candidate;
1609 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
1611 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1612 return candidate;
1614 else
1615 return candidate;
1617 return Qnil;
1620 /* Return the next frame in the frame list after FRAME. */
1622 static Lisp_Object
1623 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1625 Lisp_Object f, tail;
1626 int passed = 0;
1628 eassume (CONSP (Vframe_list));
1630 while (passed < 2)
1631 FOR_EACH_FRAME (tail, f)
1633 if (passed)
1635 f = candidate_frame (f, frame, minibuf);
1636 if (!NILP (f))
1637 return f;
1639 if (EQ (frame, f))
1640 passed++;
1642 return frame;
1645 /* Return the previous frame in the frame list before FRAME. */
1647 static Lisp_Object
1648 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1650 Lisp_Object f, tail, prev = Qnil;
1652 eassume (CONSP (Vframe_list));
1654 FOR_EACH_FRAME (tail, f)
1656 if (EQ (frame, f) && !NILP (prev))
1657 return prev;
1658 f = candidate_frame (f, frame, minibuf);
1659 if (!NILP (f))
1660 prev = f;
1663 /* We've scanned the entire list. */
1664 if (NILP (prev))
1665 /* We went through the whole frame list without finding a single
1666 acceptable frame. Return the original frame. */
1667 return frame;
1668 else
1669 /* There were no acceptable frames in the list before FRAME; otherwise,
1670 we would have returned directly from the loop. Since PREV is the last
1671 acceptable frame in the list, return it. */
1672 return prev;
1676 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1677 doc: /* Return the next frame in the frame list after FRAME.
1678 It considers only frames on the same terminal as FRAME.
1679 By default, skip minibuffer-only frames.
1680 If omitted, FRAME defaults to the selected frame.
1681 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1682 If MINIFRAME is a window, include only its own frame
1683 and any frame now using that window as the minibuffer.
1684 If MINIFRAME is `visible', include all visible frames.
1685 If MINIFRAME is 0, include all visible and iconified frames.
1686 Otherwise, include all frames. */)
1687 (Lisp_Object frame, Lisp_Object miniframe)
1689 if (NILP (frame))
1690 frame = selected_frame;
1691 CHECK_LIVE_FRAME (frame);
1692 return next_frame (frame, miniframe);
1695 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1696 doc: /* Return the previous frame in the frame list before FRAME.
1697 It considers only frames on the same terminal as FRAME.
1698 By default, skip minibuffer-only frames.
1699 If omitted, FRAME defaults to the selected frame.
1700 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1701 If MINIFRAME is a window, include only its own frame
1702 and any frame now using that window as the minibuffer.
1703 If MINIFRAME is `visible', include all visible frames.
1704 If MINIFRAME is 0, include all visible and iconified frames.
1705 Otherwise, include all frames. */)
1706 (Lisp_Object frame, Lisp_Object miniframe)
1708 if (NILP (frame))
1709 frame = selected_frame;
1710 CHECK_LIVE_FRAME (frame);
1711 return prev_frame (frame, miniframe);
1714 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1715 Slast_nonminibuf_frame, 0, 0, 0,
1716 doc: /* Return last non-minibuffer frame selected. */)
1717 (void)
1719 Lisp_Object frame = Qnil;
1721 if (last_nonminibuf_frame)
1722 XSETFRAME (frame, last_nonminibuf_frame);
1724 return frame;
1728 * other_frames:
1730 * Return true if there exists at least one visible or iconified frame
1731 * but F. Tooltip frames do not qualify as candidates. Return false
1732 * if no such frame exists.
1734 * INVISIBLE true means we are called from make_frame_invisible where
1735 * such a frame must be visible or iconified. INVISIBLE nil means we
1736 * are called from delete_frame. In that case FORCE true means that the
1737 * visibility status of such a frame can be ignored.
1739 * If F is the terminal frame and we are using X, return true if at
1740 * least one X frame exists.
1742 static bool
1743 other_frames (struct frame *f, bool invisible, bool force)
1745 Lisp_Object frames, frame, frame1;
1746 Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
1748 XSETFRAME (frame, f);
1749 if (WINDOWP (minibuffer_window)
1750 && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
1751 minibuffer_window = Qnil;
1753 FOR_EACH_FRAME (frames, frame1)
1755 struct frame *f1 = XFRAME (frame1);
1757 if (f != f1)
1759 /* Verify that we can still talk to the frame's X window, and
1760 note any recent change in visibility. */
1761 #ifdef HAVE_X_WINDOWS
1762 if (FRAME_WINDOW_P (f1))
1763 x_sync (f1);
1764 #endif
1765 if (!FRAME_TOOLTIP_P (f1)
1766 /* Tooltips and child frames count neither for
1767 invisibility nor for deletions. */
1768 && !FRAME_PARENT_FRAME (f1)
1769 /* Frames with a non-nil `delete-before' parameter don't
1770 count for deletions. */
1771 && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
1772 /* For invisibility and normal deletions, at least one
1773 visible or iconified frame must remain (Bug#26682). */
1774 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
1775 || (!invisible
1776 && (force
1777 /* Allow deleting the terminal frame when at
1778 least one X frame exists. */
1779 || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))))
1780 return true;
1784 return false;
1787 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1788 window. Preferably use the selected frame's minibuffer window
1789 instead. If the selected frame doesn't have one, get some other
1790 frame's minibuffer window. SELECT non-zero means select the new
1791 minibuffer window. */
1792 static void
1793 check_minibuf_window (Lisp_Object frame, int select)
1795 struct frame *f = decode_live_frame (frame);
1797 XSETFRAME (frame, f);
1799 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1801 Lisp_Object frames, this, window = make_number (0);
1803 if (!EQ (frame, selected_frame)
1804 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1805 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1806 else
1807 FOR_EACH_FRAME (frames, this)
1809 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1811 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1812 break;
1816 /* Don't abort if no window was found (Bug#15247). */
1817 if (WINDOWP (window))
1819 /* Use set_window_buffer instead of Fset_window_buffer (see
1820 discussion of bug#11984, bug#12025, bug#12026). */
1821 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1822 minibuf_window = window;
1824 /* SELECT non-zero usually means that FRAME's minibuffer
1825 window was selected; select the new one. */
1826 if (select)
1827 Fselect_window (minibuf_window, Qnil);
1834 * delete_frame:
1836 * Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1837 * unconditionally. x_connection_closed and delete_terminal use this.
1838 * Any other value of FORCE implements the semantics described for
1839 * Fdelete_frame. */
1840 Lisp_Object
1841 delete_frame (Lisp_Object frame, Lisp_Object force)
1843 struct frame *f = decode_any_frame (frame);
1844 struct frame *sf;
1845 struct kboard *kb;
1846 Lisp_Object frames, frame1;
1847 int minibuffer_selected, is_tooltip_frame;
1848 bool nochild = !FRAME_PARENT_FRAME (f);
1850 if (!FRAME_LIVE_P (f))
1851 return Qnil;
1852 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1854 if (NILP (force))
1855 error ("Attempt to delete the sole visible or iconified frame");
1856 else
1857 error ("Attempt to delete the only frame");
1860 XSETFRAME (frame, f);
1862 /* Softly delete all frames with this frame as their parent frame or
1863 as their `delete-before' frame parameter value. */
1864 FOR_EACH_FRAME (frames, frame1)
1865 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
1866 /* Process `delete-before' parameter iff FRAME is not a child
1867 frame. This avoids that we enter an infinite chain of mixed
1868 dependencies. */
1869 || (nochild
1870 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
1871 delete_frame (frame1, Qnil);
1873 /* Does this frame have a minibuffer, and is it the surrogate
1874 minibuffer for any other frame? */
1875 if (FRAME_HAS_MINIBUF_P (f))
1877 FOR_EACH_FRAME (frames, frame1)
1879 Lisp_Object fminiw;
1881 if (EQ (frame1, frame))
1882 continue;
1884 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
1886 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1888 /* If we MUST delete this frame, delete the other first.
1889 But do this only if FORCE equals `noelisp'. */
1890 if (EQ (force, Qnoelisp))
1891 delete_frame (frame1, Qnoelisp);
1892 else
1893 error ("Attempt to delete a surrogate minibuffer frame");
1898 is_tooltip_frame = FRAME_TOOLTIP_P (f);
1900 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1901 frame is a tooltip. FORCE is set to `noelisp' when handling
1902 a disconnect from the terminal, so we don't dare call Lisp
1903 code. */
1904 if (NILP (Vrun_hooks) || is_tooltip_frame)
1906 else if (EQ (force, Qnoelisp))
1907 pending_funcalls
1908 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1909 pending_funcalls);
1910 else
1912 #ifdef HAVE_X_WINDOWS
1913 /* Also, save clipboard to the clipboard manager. */
1914 x_clipboard_manager_save_frame (frame);
1915 #endif
1917 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1920 /* delete_frame_functions may have deleted any frame, including this
1921 one. */
1922 if (!FRAME_LIVE_P (f))
1923 return Qnil;
1924 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1926 if (NILP (force))
1927 error ("Attempt to delete the sole visible or iconified frame");
1928 else
1929 error ("Attempt to delete the only frame");
1932 /* At this point, we are committed to deleting the frame.
1933 There is no more chance for errors to prevent it. */
1934 minibuffer_selected = EQ (minibuf_window, selected_window);
1935 sf = SELECTED_FRAME ();
1936 /* Don't let the frame remain selected. */
1937 if (f == sf)
1939 Lisp_Object tail;
1940 eassume (CONSP (Vframe_list));
1942 /* Look for another visible frame on the same terminal.
1943 Do not call next_frame here because it may loop forever.
1944 See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1945 FOR_EACH_FRAME (tail, frame1)
1947 struct frame *f1 = XFRAME (frame1);
1949 if (!EQ (frame, frame1)
1950 && !FRAME_TOOLTIP_P (f1)
1951 && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1)
1952 && FRAME_VISIBLE_P (f1))
1953 break;
1956 /* If there is none, find *some* other frame. */
1957 if (NILP (frame1) || EQ (frame1, frame))
1959 FOR_EACH_FRAME (tail, frame1)
1961 struct frame *f1 = XFRAME (frame1);
1963 if (!EQ (frame, frame1)
1964 && FRAME_LIVE_P (f1)
1965 && !FRAME_TOOLTIP_P (f1))
1967 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1969 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1971 if (!EQ (top_frame, frame))
1972 frame1 = top_frame;
1974 break;
1978 #ifdef NS_IMPL_COCOA
1979 else
1980 /* Under NS, there is no system mechanism for choosing a new
1981 window to get focus -- it is left to application code.
1982 So the portion of THIS application interfacing with NS
1983 needs to know about it. We call Fraise_frame, but the
1984 purpose is really to transfer focus. */
1985 Fraise_frame (frame1);
1986 #endif
1988 do_switch_frame (frame1, 0, 1, Qnil);
1989 sf = SELECTED_FRAME ();
1992 /* Don't allow minibuf_window to remain on a deleted frame. */
1993 check_minibuf_window (frame, minibuffer_selected);
1995 /* Don't let echo_area_window to remain on a deleted frame. */
1996 if (EQ (f->minibuffer_window, echo_area_window))
1997 echo_area_window = sf->minibuffer_window;
1999 /* Clear any X selections for this frame. */
2000 #ifdef HAVE_X_WINDOWS
2001 if (FRAME_X_P (f))
2002 x_clear_frame_selections (f);
2003 #endif
2005 /* Free glyphs.
2006 This function must be called before the window tree of the
2007 frame is deleted because windows contain dynamically allocated
2008 memory. */
2009 free_glyphs (f);
2011 #ifdef HAVE_WINDOW_SYSTEM
2012 /* Give chance to each font driver to free a frame specific data. */
2013 font_update_drivers (f, Qnil);
2014 #endif
2016 /* Mark all the windows that used to be on FRAME as deleted, and then
2017 remove the reference to them. */
2018 delete_all_child_windows (f->root_window);
2019 fset_root_window (f, Qnil);
2021 Vframe_list = Fdelq (frame, Vframe_list);
2022 SET_FRAME_VISIBLE (f, 0);
2024 /* Allow the vector of menu bar contents to be freed in the next
2025 garbage collection. The frame object itself may not be garbage
2026 collected until much later, because recent_keys and other data
2027 structures can still refer to it. */
2028 fset_menu_bar_vector (f, Qnil);
2030 /* If FRAME's buffer lists contains killed
2031 buffers, this helps GC to reclaim them. */
2032 fset_buffer_list (f, Qnil);
2033 fset_buried_buffer_list (f, Qnil);
2035 free_font_driver_list (f);
2036 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
2037 xfree (f->namebuf);
2038 #endif
2039 xfree (f->decode_mode_spec_buffer);
2040 xfree (FRAME_INSERT_COST (f));
2041 xfree (FRAME_DELETEN_COST (f));
2042 xfree (FRAME_INSERTN_COST (f));
2043 xfree (FRAME_DELETE_COST (f));
2045 /* Since some events are handled at the interrupt level, we may get
2046 an event for f at any time; if we zero out the frame's terminal
2047 now, then we may trip up the event-handling code. Instead, we'll
2048 promise that the terminal of the frame must be valid until we
2049 have called the window-system-dependent frame destruction
2050 routine. */
2052 struct terminal *terminal;
2053 block_input ();
2054 if (FRAME_TERMINAL (f)->delete_frame_hook)
2055 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
2056 terminal = FRAME_TERMINAL (f);
2057 f->output_data.nothing = 0;
2058 f->terminal = 0; /* Now the frame is dead. */
2059 unblock_input ();
2061 /* If needed, delete the terminal that this frame was on.
2062 (This must be done after the frame is killed.) */
2063 terminal->reference_count--;
2064 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
2065 /* FIXME: Deleting the terminal crashes emacs because of a GTK
2066 bug.
2067 https://lists.gnu.org/r/emacs-devel/2011-10/msg00363.html */
2069 /* Since a similar behavior was observed on the Lucid and Motif
2070 builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now
2071 don't delete the terminal for these builds either. */
2072 if (terminal->reference_count == 0 && terminal->type == output_x_window)
2073 terminal->reference_count = 1;
2074 #endif /* USE_X_TOOLKIT || USE_GTK */
2075 if (terminal->reference_count == 0)
2077 Lisp_Object tmp;
2078 XSETTERMINAL (tmp, terminal);
2080 kb = NULL;
2081 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
2083 else
2084 kb = terminal->kboard;
2087 /* If we've deleted the last_nonminibuf_frame, then try to find
2088 another one. */
2089 if (f == last_nonminibuf_frame)
2091 last_nonminibuf_frame = 0;
2093 FOR_EACH_FRAME (frames, frame1)
2095 struct frame *f1 = XFRAME (frame1);
2097 if (!FRAME_MINIBUF_ONLY_P (f1))
2099 last_nonminibuf_frame = f1;
2100 break;
2105 /* If there's no other frame on the same kboard, get out of
2106 single-kboard state if we're in it for this kboard. */
2107 if (kb != NULL)
2109 /* Some frame we found on the same kboard, or nil if there are none. */
2110 Lisp_Object frame_on_same_kboard = Qnil;
2112 FOR_EACH_FRAME (frames, frame1)
2113 if (kb == FRAME_KBOARD (XFRAME (frame1)))
2114 frame_on_same_kboard = frame1;
2116 if (NILP (frame_on_same_kboard))
2117 not_single_kboard_state (kb);
2121 /* If we've deleted this keyboard's default_minibuffer_frame, try to
2122 find another one. Prefer minibuffer-only frames, but also notice
2123 frames with other windows. */
2124 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
2126 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
2127 Lisp_Object frame_with_minibuf = Qnil;
2128 /* Some frame we found on the same kboard, or nil if there are none. */
2129 Lisp_Object frame_on_same_kboard = Qnil;
2131 FOR_EACH_FRAME (frames, frame1)
2133 struct frame *f1 = XFRAME (frame1);
2135 /* Consider only frames on the same kboard
2136 and only those with minibuffers. */
2137 if (kb == FRAME_KBOARD (f1)
2138 && FRAME_HAS_MINIBUF_P (f1))
2140 frame_with_minibuf = frame1;
2141 if (FRAME_MINIBUF_ONLY_P (f1))
2142 break;
2145 if (kb == FRAME_KBOARD (f1))
2146 frame_on_same_kboard = frame1;
2149 if (!NILP (frame_on_same_kboard))
2151 /* We know that there must be some frame with a minibuffer out
2152 there. If this were not true, all of the frames present
2153 would have to be minibufferless, which implies that at some
2154 point their minibuffer frames must have been deleted, but
2155 that is prohibited at the top; you can't delete surrogate
2156 minibuffer frames. */
2157 if (NILP (frame_with_minibuf))
2158 emacs_abort ();
2160 kset_default_minibuffer_frame (kb, frame_with_minibuf);
2162 else
2163 /* No frames left on this kboard--say no minibuffer either. */
2164 kset_default_minibuffer_frame (kb, Qnil);
2167 /* Cause frame titles to update--necessary if we now have just one frame. */
2168 if (!is_tooltip_frame)
2169 update_mode_lines = 15;
2171 return Qnil;
2174 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
2175 doc: /* Delete FRAME, permanently eliminating it from use.
2176 FRAME must be a live frame and defaults to the selected one.
2178 A frame may not be deleted if its minibuffer serves as surrogate
2179 minibuffer for another frame. Normally, you may not delete a frame if
2180 all other frames are invisible, but if the second optional argument
2181 FORCE is non-nil, you may do so.
2183 This function runs `delete-frame-functions' before actually
2184 deleting the frame, unless the frame is a tooltip.
2185 The functions are run with one argument, the frame to be deleted. */)
2186 (Lisp_Object frame, Lisp_Object force)
2188 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
2191 #ifdef HAVE_WINDOW_SYSTEM
2193 * frame_internal_border_part:
2195 * Return part of internal border the coordinates X and Y relative to
2196 * frame F are on. Return nil if the coordinates are not on the
2197 * internal border of F.
2199 * Return one of INTERNAL_BORDER_LEFT_EDGE, INTERNAL_BORDER_TOP_EDGE,
2200 * INTERNAL_BORDER_RIGHT_EDGE or INTERNAL_BORDER_BOTTOM_EDGE when the
2201 * mouse cursor is on the corresponding border with an offset of at
2202 * least one canonical character height from that border's edges.
2204 * If no border part could be found this way, return one of
2205 * INTERNAL_BORDER_TOP_LEFT_CORNER, INTERNAL_BORDER_TOP_RIGHT_CORNER,
2206 * INTERNAL_BORDER_BOTTOM_LEFT_CORNER or
2207 * INTERNAL_BORDER_BOTTOM_RIGHT_CORNER to indicate that the mouse is in
2208 * one of the corresponding corners. This means that for very small
2209 * frames an `edge' return value is preferred.
2211 enum internal_border_part
2212 frame_internal_border_part (struct frame *f, int x, int y)
2214 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
2215 int offset = FRAME_LINE_HEIGHT (f);
2216 int width = FRAME_PIXEL_WIDTH (f);
2217 int height = FRAME_PIXEL_HEIGHT (f);
2218 enum internal_border_part part = INTERNAL_BORDER_NONE;
2220 if (offset < border)
2221 /* For very wide borders make offset at least as large as
2222 border. */
2223 offset = border;
2225 if (offset < x && x < width - offset)
2226 /* Top or bottom border. */
2228 if (0 <= y && y <= border)
2229 part = INTERNAL_BORDER_TOP_EDGE;
2230 else if (height - border <= y && y <= height)
2231 part = INTERNAL_BORDER_BOTTOM_EDGE;
2233 else if (offset < y && y < height - offset)
2234 /* Left or right border. */
2236 if (0 <= x && x <= border)
2237 part = INTERNAL_BORDER_LEFT_EDGE;
2238 else if (width - border <= x && x <= width)
2239 part = INTERNAL_BORDER_RIGHT_EDGE;
2241 else
2243 /* An edge. */
2244 int half_width = width / 2;
2245 int half_height = height / 2;
2247 if (0 <= x && x <= border)
2249 /* A left edge. */
2250 if (0 <= y && y <= half_height)
2251 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2252 else if (half_height < y && y <= height)
2253 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2255 else if (width - border <= x && x <= width)
2257 /* A right edge. */
2258 if (0 <= y && y <= half_height)
2259 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2260 else if (half_height < y && y <= height)
2261 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2263 else if (0 <= y && y <= border)
2265 /* A top edge. */
2266 if (0 <= x && x <= half_width)
2267 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2268 else if (half_width < x && x <= width)
2269 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2271 else if (height - border <= y && y <= height)
2273 /* A bottom edge. */
2274 if (0 <= x && x <= half_width)
2275 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2276 else if (half_width < x && x <= width)
2277 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2281 return part;
2283 #endif
2285 /* Return mouse position in character cell units. */
2287 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
2288 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2289 The position is given in canonical character cells, where (0, 0) is the
2290 upper-left corner of the frame, X is the horizontal offset, and Y is the
2291 vertical offset, measured in units of the frame's default character size.
2292 If Emacs is running on a mouseless terminal or hasn't been programmed
2293 to read the mouse position, it returns the selected frame for FRAME
2294 and nil for X and Y.
2295 If `mouse-position-function' is non-nil, `mouse-position' calls it,
2296 passing the normal return value to that function as an argument,
2297 and returns whatever that function returns. */)
2298 (void)
2300 struct frame *f;
2301 Lisp_Object lispy_dummy;
2302 Lisp_Object x, y, retval;
2304 f = SELECTED_FRAME ();
2305 x = y = Qnil;
2307 /* It's okay for the hook to refrain from storing anything. */
2308 if (FRAME_TERMINAL (f)->mouse_position_hook)
2310 enum scroll_bar_part party_dummy;
2311 Time time_dummy;
2312 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2313 &lispy_dummy, &party_dummy,
2314 &x, &y,
2315 &time_dummy);
2318 if (! NILP (x))
2320 int col = XINT (x);
2321 int row = XINT (y);
2322 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
2323 XSETINT (x, col);
2324 XSETINT (y, row);
2326 XSETFRAME (lispy_dummy, f);
2327 retval = Fcons (lispy_dummy, Fcons (x, y));
2328 if (!NILP (Vmouse_position_function))
2329 retval = call1 (Vmouse_position_function, retval);
2330 return retval;
2333 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
2334 Smouse_pixel_position, 0, 0, 0,
2335 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2336 The position is given in pixel units, where (0, 0) is the
2337 upper-left corner of the frame, X is the horizontal offset, and Y is
2338 the vertical offset.
2339 If Emacs is running on a mouseless terminal or hasn't been programmed
2340 to read the mouse position, it returns the selected frame for FRAME
2341 and nil for X and Y. */)
2342 (void)
2344 struct frame *f;
2345 Lisp_Object lispy_dummy;
2346 Lisp_Object x, y, retval;
2348 f = SELECTED_FRAME ();
2349 x = y = Qnil;
2351 /* It's okay for the hook to refrain from storing anything. */
2352 if (FRAME_TERMINAL (f)->mouse_position_hook)
2354 enum scroll_bar_part party_dummy;
2355 Time time_dummy;
2356 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2357 &lispy_dummy, &party_dummy,
2358 &x, &y,
2359 &time_dummy);
2362 XSETFRAME (lispy_dummy, f);
2363 retval = Fcons (lispy_dummy, Fcons (x, y));
2364 if (!NILP (Vmouse_position_function))
2365 retval = call1 (Vmouse_position_function, retval);
2366 return retval;
2369 #ifdef HAVE_WINDOW_SYSTEM
2371 /* On frame F, convert character coordinates X and Y to pixel
2372 coordinates *PIX_X and *PIX_Y. */
2374 static void
2375 frame_char_to_pixel_position (struct frame *f, int x, int y,
2376 int *pix_x, int *pix_y)
2378 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
2379 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
2381 if (*pix_x < 0)
2382 *pix_x = 0;
2383 if (*pix_x > FRAME_PIXEL_WIDTH (f))
2384 *pix_x = FRAME_PIXEL_WIDTH (f);
2386 if (*pix_y < 0)
2387 *pix_y = 0;
2388 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
2389 *pix_y = FRAME_PIXEL_HEIGHT (f);
2392 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
2394 static void
2395 frame_set_mouse_position (struct frame *f, int x, int y)
2397 int pix_x, pix_y;
2399 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
2400 frame_set_mouse_pixel_position (f, pix_x, pix_y);
2403 #endif /* HAVE_WINDOW_SYSTEM */
2405 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
2406 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
2407 Coordinates are relative to the frame, not a window,
2408 so the coordinates of the top left character in the frame
2409 may be nonzero due to left-hand scroll bars or the menu bar.
2411 The position is given in canonical character cells, where (0, 0) is
2412 the upper-left corner of the frame, X is the horizontal offset, and
2413 Y is the vertical offset, measured in units of the frame's default
2414 character size.
2416 This function is a no-op for an X frame that is not visible.
2417 If you have just created a frame, you must wait for it to become visible
2418 before calling this function on it, like this.
2419 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2420 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2422 CHECK_LIVE_FRAME (frame);
2423 CHECK_TYPE_RANGED_INTEGER (int, x);
2424 CHECK_TYPE_RANGED_INTEGER (int, y);
2426 /* I think this should be done with a hook. */
2427 #ifdef HAVE_WINDOW_SYSTEM
2428 if (FRAME_WINDOW_P (XFRAME (frame)))
2429 /* Warping the mouse will cause enternotify and focus events. */
2430 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
2431 #else
2432 #if defined (MSDOS)
2433 if (FRAME_MSDOS_P (XFRAME (frame)))
2435 Fselect_frame (frame, Qnil);
2436 mouse_moveto (XINT (x), XINT (y));
2438 #else
2439 #ifdef HAVE_GPM
2441 Fselect_frame (frame, Qnil);
2442 term_mouse_moveto (XINT (x), XINT (y));
2444 #endif
2445 #endif
2446 #endif
2448 return Qnil;
2451 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
2452 Sset_mouse_pixel_position, 3, 3, 0,
2453 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
2454 The position is given in pixels, where (0, 0) is the upper-left corner
2455 of the frame, X is the horizontal offset, and Y is the vertical offset.
2457 Note, this is a no-op for an X frame that is not visible.
2458 If you have just created a frame, you must wait for it to become visible
2459 before calling this function on it, like this.
2460 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2461 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2463 CHECK_LIVE_FRAME (frame);
2464 CHECK_TYPE_RANGED_INTEGER (int, x);
2465 CHECK_TYPE_RANGED_INTEGER (int, y);
2467 /* I think this should be done with a hook. */
2468 #ifdef HAVE_WINDOW_SYSTEM
2469 if (FRAME_WINDOW_P (XFRAME (frame)))
2470 /* Warping the mouse will cause enternotify and focus events. */
2471 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
2472 #else
2473 #if defined (MSDOS)
2474 if (FRAME_MSDOS_P (XFRAME (frame)))
2476 Fselect_frame (frame, Qnil);
2477 mouse_moveto (XINT (x), XINT (y));
2479 #else
2480 #ifdef HAVE_GPM
2482 Fselect_frame (frame, Qnil);
2483 term_mouse_moveto (XINT (x), XINT (y));
2485 #endif
2486 #endif
2487 #endif
2489 return Qnil;
2492 static void make_frame_visible_1 (Lisp_Object);
2494 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
2495 0, 1, "",
2496 doc: /* Make the frame FRAME visible (assuming it is an X window).
2497 If omitted, FRAME defaults to the currently selected frame. */)
2498 (Lisp_Object frame)
2500 struct frame *f = decode_live_frame (frame);
2502 /* I think this should be done with a hook. */
2503 #ifdef HAVE_WINDOW_SYSTEM
2504 if (FRAME_WINDOW_P (f))
2505 x_make_frame_visible (f);
2506 #endif
2508 make_frame_visible_1 (f->root_window);
2510 /* Make menu bar update for the Buffers and Frames menus. */
2511 /* windows_or_buffers_changed = 15; FIXME: Why? */
2513 XSETFRAME (frame, f);
2514 return frame;
2517 /* Update the display_time slot of the buffers shown in WINDOW
2518 and all its descendants. */
2520 static void
2521 make_frame_visible_1 (Lisp_Object window)
2523 struct window *w;
2525 for (; !NILP (window); window = w->next)
2527 w = XWINDOW (window);
2528 if (WINDOWP (w->contents))
2529 make_frame_visible_1 (w->contents);
2530 else
2531 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2535 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2536 0, 2, "",
2537 doc: /* Make the frame FRAME invisible.
2538 If omitted, FRAME defaults to the currently selected frame.
2539 On graphical displays, invisible frames are not updated and are
2540 usually not displayed at all, even in a window system's \"taskbar\".
2542 Normally you may not make FRAME invisible if all other frames are invisible,
2543 but if the second optional argument FORCE is non-nil, you may do so.
2545 This function has no effect on text terminal frames. Such frames are
2546 always considered visible, whether or not they are currently being
2547 displayed in the terminal. */)
2548 (Lisp_Object frame, Lisp_Object force)
2550 struct frame *f = decode_live_frame (frame);
2552 if (NILP (force) && !other_frames (f, true, false))
2553 error ("Attempt to make invisible the sole visible or iconified frame");
2555 /* Don't allow minibuf_window to remain on an invisible frame. */
2556 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2558 /* I think this should be done with a hook. */
2559 #ifdef HAVE_WINDOW_SYSTEM
2560 if (FRAME_WINDOW_P (f))
2561 x_make_frame_invisible (f);
2562 #endif
2564 /* Make menu bar update for the Buffers and Frames menus. */
2565 windows_or_buffers_changed = 16;
2567 return Qnil;
2570 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2571 0, 1, "",
2572 doc: /* Make the frame FRAME into an icon.
2573 If omitted, FRAME defaults to the currently selected frame.
2575 If FRAME is a child frame, consult the variable `iconify-child-frame'
2576 for how to proceed. */)
2577 (Lisp_Object frame)
2579 struct frame *f = decode_live_frame (frame);
2580 #ifdef HAVE_WINDOW_SYSTEM
2581 Lisp_Object parent = f->parent_frame;
2583 if (!NILP (parent))
2585 if (NILP (iconify_child_frame))
2586 /* Do nothing. */
2587 return Qnil;
2588 else if (EQ (iconify_child_frame, Qiconify_top_level))
2590 /* Iconify top level frame instead (the default). */
2591 Ficonify_frame (parent);
2592 return Qnil;
2594 else if (EQ (iconify_child_frame, Qmake_invisible))
2596 /* Make frame invisible instead. */
2597 Fmake_frame_invisible (frame, Qnil);
2598 return Qnil;
2601 #endif /* HAVE_WINDOW_SYSTEM */
2603 /* Don't allow minibuf_window to remain on an iconified frame. */
2604 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2606 /* I think this should be done with a hook. */
2607 if (FRAME_WINDOW_P (f))
2609 #ifdef HAVE_WINDOW_SYSTEM
2610 x_iconify_frame (f);
2611 #endif
2614 return Qnil;
2617 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2618 1, 1, 0,
2619 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2620 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2621 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2622 On graphical displays, invisible frames are not updated and are
2623 usually not displayed at all, even in a window system's \"taskbar\".
2625 If FRAME is a text terminal frame, this always returns t.
2626 Such frames are always considered visible, whether or not they are
2627 currently being displayed on the terminal. */)
2628 (Lisp_Object frame)
2630 CHECK_LIVE_FRAME (frame);
2632 if (FRAME_VISIBLE_P (XFRAME (frame)))
2633 return Qt;
2634 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2635 return Qicon;
2636 return Qnil;
2639 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2640 0, 0, 0,
2641 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2642 (void)
2644 Lisp_Object tail, frame, value = Qnil;
2646 FOR_EACH_FRAME (tail, frame)
2647 if (FRAME_VISIBLE_P (XFRAME (frame)))
2648 value = Fcons (frame, value);
2650 return value;
2654 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2655 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2656 If FRAME is invisible or iconified, make it visible.
2657 If you don't specify a frame, the selected frame is used.
2658 If Emacs is displaying on an ordinary terminal or some other device which
2659 doesn't support multiple overlapping frames, this function selects FRAME. */)
2660 (Lisp_Object frame)
2662 struct frame *f = decode_live_frame (frame);
2664 XSETFRAME (frame, f);
2666 if (FRAME_TERMCAP_P (f))
2667 /* On a text terminal select FRAME. */
2668 Fselect_frame (frame, Qnil);
2669 else
2670 /* Do like the documentation says. */
2671 Fmake_frame_visible (frame);
2673 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2674 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2676 return Qnil;
2679 /* Should we have a corresponding function called Flower_Power? */
2680 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2681 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2682 If you don't specify a frame, the selected frame is used.
2683 If Emacs is displaying on an ordinary terminal or some other device which
2684 doesn't support multiple overlapping frames, this function does nothing. */)
2685 (Lisp_Object frame)
2687 struct frame *f = decode_live_frame (frame);
2689 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2690 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2692 return Qnil;
2696 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2697 1, 2, 0,
2698 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2699 In other words, switch-frame events caused by events in FRAME will
2700 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2701 FOCUS-FRAME after reading an event typed at FRAME.
2703 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2704 frame again receives its own keystrokes.
2706 Focus redirection is useful for temporarily redirecting keystrokes to
2707 a surrogate minibuffer frame when a frame doesn't have its own
2708 minibuffer window.
2710 A frame's focus redirection can be changed by `select-frame'. If frame
2711 FOO is selected, and then a different frame BAR is selected, any
2712 frames redirecting their focus to FOO are shifted to redirect their
2713 focus to BAR. This allows focus redirection to work properly when the
2714 user switches from one frame to another using `select-window'.
2716 This means that a frame whose focus is redirected to itself is treated
2717 differently from a frame whose focus is redirected to nil; the former
2718 is affected by `select-frame', while the latter is not.
2720 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2721 (Lisp_Object frame, Lisp_Object focus_frame)
2723 /* Note that we don't check for a live frame here. It's reasonable
2724 to redirect the focus of a frame you're about to delete, if you
2725 know what other frame should receive those keystrokes. */
2726 struct frame *f = decode_any_frame (frame);
2728 if (! NILP (focus_frame))
2729 CHECK_LIVE_FRAME (focus_frame);
2731 fset_focus_frame (f, focus_frame);
2733 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2734 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2736 return Qnil;
2740 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2741 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2742 If FRAME is omitted or nil, the selected frame is used.
2743 Return nil if FRAME's focus is not redirected.
2744 See `redirect-frame-focus'. */)
2745 (Lisp_Object frame)
2747 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2750 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 2, 0,
2751 doc: /* Set the input focus to FRAME.
2752 FRAME nil means use the selected frame. Optional argument NOACTIVATE
2753 means do not activate FRAME.
2755 If there is no window system support, this function does nothing. */)
2756 (Lisp_Object frame, Lisp_Object noactivate)
2758 #ifdef HAVE_WINDOW_SYSTEM
2759 x_focus_frame (decode_window_system_frame (frame), !NILP (noactivate));
2760 #endif
2761 return Qnil;
2764 DEFUN ("frame-after-make-frame",
2765 Fframe_after_make_frame,
2766 Sframe_after_make_frame, 2, 2, 0,
2767 doc: /* Mark FRAME as made.
2768 FRAME nil means use the selected frame. Second argument MADE non-nil
2769 means functions on `window-configuration-change-hook' are called
2770 whenever the window configuration of FRAME changes. MADE nil means
2771 these functions are not called.
2773 This function is currently called by `make-frame' only and should be
2774 otherwise used with utter care to avoid that running functions on
2775 `window-configuration-change-hook' is impeded forever. */)
2776 (Lisp_Object frame, Lisp_Object made)
2778 struct frame *f = decode_live_frame (frame);
2779 f->after_make_frame = !NILP (made);
2780 f->inhibit_horizontal_resize = false;
2781 f->inhibit_vertical_resize = false;
2782 return made;
2786 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2788 void
2789 frames_discard_buffer (Lisp_Object buffer)
2791 Lisp_Object frame, tail;
2793 FOR_EACH_FRAME (tail, frame)
2795 fset_buffer_list
2796 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2797 fset_buried_buffer_list
2798 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2802 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2803 If the alist already has an element for PROP, we change it. */
2805 void
2806 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2808 register Lisp_Object tem;
2810 tem = Fassq (prop, *alistptr);
2811 if (EQ (tem, Qnil))
2812 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2813 else
2814 Fsetcdr (tem, val);
2817 static int
2818 frame_name_fnn_p (char *str, ptrdiff_t len)
2820 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2822 char *p = str + 2;
2823 while ('0' <= *p && *p <= '9')
2824 p++;
2825 if (p == str + len)
2826 return 1;
2828 return 0;
2831 /* Set the name of the terminal frame. Also used by MSDOS frames.
2832 Modeled after x_set_name which is used for WINDOW frames. */
2834 static void
2835 set_term_frame_name (struct frame *f, Lisp_Object name)
2837 f->explicit_name = ! NILP (name);
2839 /* If NAME is nil, set the name to F<num>. */
2840 if (NILP (name))
2842 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2844 /* Check for no change needed in this very common case
2845 before we do any consing. */
2846 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2847 return;
2849 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2851 else
2853 CHECK_STRING (name);
2855 /* Don't change the name if it's already NAME. */
2856 if (! NILP (Fstring_equal (name, f->name)))
2857 return;
2859 /* Don't allow the user to set the frame name to F<num>, so it
2860 doesn't clash with the names we generate for terminal frames. */
2861 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2862 error ("Frame names of the form F<num> are usurped by Emacs");
2865 fset_name (f, name);
2866 update_mode_lines = 16;
2869 void
2870 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2872 register Lisp_Object old_alist_elt;
2874 if (EQ (prop, Qminibuffer))
2876 if (WINDOWP (val))
2878 if (!MINI_WINDOW_P (XWINDOW (val)))
2879 error ("The `minibuffer' parameter does not specify a valid minibuffer window");
2880 else if (FRAME_MINIBUF_ONLY_P (f))
2882 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2883 val = Qonly;
2884 else
2885 error ("Can't change the minibuffer window of a minibuffer-only frame");
2887 else if (FRAME_HAS_MINIBUF_P (f))
2889 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2890 val = Qt;
2891 else
2892 error ("Can't change the minibuffer window of a frame with its own minibuffer");
2894 else
2895 /* Store the chosen minibuffer window. */
2896 fset_minibuffer_window (f, val);
2898 else
2900 Lisp_Object old_val = Fcdr (Fassq (Qminibuffer, f->param_alist));
2902 if (!NILP (old_val))
2904 if (WINDOWP (old_val) && NILP (val))
2905 /* Don't change the value for a minibuffer-less frame if
2906 only nil was specified as new value. */
2907 val = old_val;
2908 else if (!EQ (old_val, val))
2909 error ("Can't change the `minibuffer' parameter of this frame");
2914 /* Check each parent-frame and delete-before parameter for a
2915 circular dependency. Do not check between parameters, so you can
2916 still create circular dependencies with different properties, for
2917 example a chain of frames F1->F2->...Fn such that F1 is an ancestor
2918 frame of Fn and thus cannot be deleted before Fn and a second chain
2919 Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
2920 else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
2922 Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
2924 if (!EQ (oldval, val) && !NILP (val))
2926 Lisp_Object frame;
2927 Lisp_Object frame1 = val;
2929 if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
2930 error ("Invalid `%s' frame parameter",
2931 SSDATA (SYMBOL_NAME (prop)));
2933 XSETFRAME (frame, f);
2935 while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
2936 if (EQ (frame1, frame))
2937 error ("Circular specification of `%s' frame parameter",
2938 SSDATA (SYMBOL_NAME (prop)));
2939 else
2940 frame1 = get_frame_param (XFRAME (frame1), prop);
2944 /* The buffer-list parameters are stored in a special place and not
2945 in the alist. All buffers must be live. */
2946 else if (EQ (prop, Qbuffer_list))
2948 Lisp_Object list = Qnil;
2949 for (; CONSP (val); val = XCDR (val))
2950 if (!NILP (Fbuffer_live_p (XCAR (val))))
2951 list = Fcons (XCAR (val), list);
2952 fset_buffer_list (f, Fnreverse (list));
2953 return;
2955 else if (EQ (prop, Qburied_buffer_list))
2957 Lisp_Object list = Qnil;
2958 for (; CONSP (val); val = XCDR (val))
2959 if (!NILP (Fbuffer_live_p (XCAR (val))))
2960 list = Fcons (XCAR (val), list);
2961 fset_buried_buffer_list (f, Fnreverse (list));
2962 return;
2965 /* The tty color needed to be set before the frame's parameter
2966 alist was updated with the new value. This is not true any more,
2967 but we still do this test early on. */
2968 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2969 && f == FRAME_TTY (f)->previous_frame)
2970 /* Force redisplay of this tty. */
2971 FRAME_TTY (f)->previous_frame = NULL;
2973 /* Update the frame parameter alist. */
2974 old_alist_elt = Fassq (prop, f->param_alist);
2975 if (EQ (old_alist_elt, Qnil))
2976 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2977 else
2978 Fsetcdr (old_alist_elt, val);
2980 /* Update some other special parameters in their special places
2981 in addition to the alist. */
2983 if (EQ (prop, Qbuffer_predicate))
2984 fset_buffer_predicate (f, val);
2986 if (! FRAME_WINDOW_P (f))
2988 if (EQ (prop, Qmenu_bar_lines))
2989 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2990 else if (EQ (prop, Qname))
2991 set_term_frame_name (f, val);
2995 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2996 is not an unspecified foreground or background color. */
2998 static Lisp_Object
2999 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
3001 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
3002 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
3003 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
3004 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
3007 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
3008 doc: /* Return the parameters-alist of frame FRAME.
3009 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
3010 The meaningful PARMs depend on the kind of frame.
3011 If FRAME is omitted or nil, return information on the currently selected frame. */)
3012 (Lisp_Object frame)
3014 Lisp_Object alist;
3015 struct frame *f = decode_any_frame (frame);
3016 int height, width;
3018 if (!FRAME_LIVE_P (f))
3019 return Qnil;
3021 alist = Fcopy_alist (f->param_alist);
3023 if (!FRAME_WINDOW_P (f))
3025 Lisp_Object elt;
3027 /* If the frame's parameter alist says the colors are
3028 unspecified and reversed, take the frame's background pixel
3029 for foreground and vice versa. */
3030 elt = Fassq (Qforeground_color, alist);
3031 if (CONSP (elt) && STRINGP (XCDR (elt)))
3033 elt = frame_unspecified_color (f, XCDR (elt));
3034 if (!NILP (elt))
3035 store_in_alist (&alist, Qforeground_color, elt);
3037 else
3038 store_in_alist (&alist, Qforeground_color,
3039 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
3040 elt = Fassq (Qbackground_color, alist);
3041 if (CONSP (elt) && STRINGP (XCDR (elt)))
3043 elt = frame_unspecified_color (f, XCDR (elt));
3044 if (!NILP (elt))
3045 store_in_alist (&alist, Qbackground_color, elt);
3047 else
3048 store_in_alist (&alist, Qbackground_color,
3049 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
3050 store_in_alist (&alist, Qfont,
3051 build_string (FRAME_MSDOS_P (f)
3052 ? "ms-dos"
3053 : FRAME_W32_P (f) ? "w32term"
3054 :"tty"));
3056 store_in_alist (&alist, Qname, f->name);
3057 height = (f->new_height
3058 ? (f->new_pixelwise
3059 ? (f->new_height / FRAME_LINE_HEIGHT (f))
3060 : f->new_height)
3061 : FRAME_LINES (f));
3062 store_in_alist (&alist, Qheight, make_number (height));
3063 width = (f->new_width
3064 ? (f->new_pixelwise
3065 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
3066 : f->new_width)
3067 : FRAME_COLS (f));
3068 store_in_alist (&alist, Qwidth, make_number (width));
3069 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
3070 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
3071 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
3072 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
3074 /* I think this should be done with a hook. */
3075 #ifdef HAVE_WINDOW_SYSTEM
3076 if (FRAME_WINDOW_P (f))
3077 x_report_frame_params (f, &alist);
3078 else
3079 #endif
3081 /* This ought to be correct in f->param_alist for an X frame. */
3082 Lisp_Object lines;
3083 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
3084 store_in_alist (&alist, Qmenu_bar_lines, lines);
3087 return alist;
3091 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
3092 doc: /* Return FRAME's value for parameter PARAMETER.
3093 If FRAME is nil, describe the currently selected frame. */)
3094 (Lisp_Object frame, Lisp_Object parameter)
3096 struct frame *f = decode_any_frame (frame);
3097 Lisp_Object value = Qnil;
3099 CHECK_SYMBOL (parameter);
3101 XSETFRAME (frame, f);
3103 if (FRAME_LIVE_P (f))
3105 /* Avoid consing in frequent cases. */
3106 if (EQ (parameter, Qname))
3107 value = f->name;
3108 #ifdef HAVE_WINDOW_SYSTEM
3109 /* These are used by vertical motion commands. */
3110 else if (EQ (parameter, Qvertical_scroll_bars))
3111 value = (f->vertical_scroll_bar_type == vertical_scroll_bar_none
3112 ? Qnil
3113 : (f->vertical_scroll_bar_type == vertical_scroll_bar_left
3114 ? Qleft : Qright));
3115 else if (EQ (parameter, Qhorizontal_scroll_bars))
3116 value = f->horizontal_scroll_bars ? Qt : Qnil;
3117 else if (EQ (parameter, Qline_spacing) && f->extra_line_spacing == 0)
3118 /* If this is non-zero, we can't determine whether the user specified
3119 an integer or float value without looking through 'param_alist'. */
3120 value = make_number (0);
3121 else if (EQ (parameter, Qfont) && FRAME_X_P (f))
3122 value = FRAME_FONT (f)->props[FONT_NAME_INDEX];
3123 #endif /* HAVE_WINDOW_SYSTEM */
3124 #ifdef HAVE_X_WINDOWS
3125 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
3126 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
3127 #endif /* HAVE_X_WINDOWS */
3128 else if (EQ (parameter, Qbackground_color)
3129 || EQ (parameter, Qforeground_color))
3131 value = Fassq (parameter, f->param_alist);
3132 if (CONSP (value))
3134 value = XCDR (value);
3135 /* Fframe_parameters puts the actual fg/bg color names,
3136 even if f->param_alist says otherwise. This is
3137 important when param_alist's notion of colors is
3138 "unspecified". We need to do the same here. */
3139 if (STRINGP (value) && !FRAME_WINDOW_P (f))
3141 Lisp_Object tem = frame_unspecified_color (f, value);
3143 if (!NILP (tem))
3144 value = tem;
3147 else
3148 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3150 else if (EQ (parameter, Qdisplay_type)
3151 || EQ (parameter, Qbackground_mode))
3152 value = Fcdr (Fassq (parameter, f->param_alist));
3153 else
3154 /* FIXME: Avoid this code path at all (as well as code duplication)
3155 by sharing more code with Fframe_parameters. */
3156 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3159 return value;
3163 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
3164 Smodify_frame_parameters, 2, 2, 0,
3165 doc: /* Modify FRAME according to new values of its parameters in ALIST.
3166 If FRAME is nil, it defaults to the selected frame.
3167 ALIST is an alist of parameters to change and their new values.
3168 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
3169 Which PARMs are meaningful depends on the kind of frame.
3170 The meaningful parameters are acted upon, i.e. the frame is changed
3171 according to their new values, and are also stored in the frame's
3172 parameter list so that `frame-parameters' will return them.
3173 PARMs that are not meaningful are still stored in the frame's parameter
3174 list, but are otherwise ignored. */)
3175 (Lisp_Object frame, Lisp_Object alist)
3177 struct frame *f = decode_live_frame (frame);
3178 Lisp_Object prop, val;
3180 /* I think this should be done with a hook. */
3181 #ifdef HAVE_WINDOW_SYSTEM
3182 if (FRAME_WINDOW_P (f))
3183 x_set_frame_parameters (f, alist);
3184 else
3185 #endif
3186 #ifdef MSDOS
3187 if (FRAME_MSDOS_P (f))
3188 IT_set_frame_parameters (f, alist);
3189 else
3190 #endif
3193 EMACS_INT length = XFASTINT (Flength (alist));
3194 ptrdiff_t i;
3195 Lisp_Object *parms;
3196 Lisp_Object *values;
3197 USE_SAFE_ALLOCA;
3198 SAFE_ALLOCA_LISP (parms, 2 * length);
3199 values = parms + length;
3201 /* Extract parm names and values into those vectors. */
3203 for (i = 0; CONSP (alist); alist = XCDR (alist))
3205 Lisp_Object elt;
3207 elt = XCAR (alist);
3208 parms[i] = Fcar (elt);
3209 values[i] = Fcdr (elt);
3210 i++;
3213 /* Now process them in reverse of specified order. */
3214 while (--i >= 0)
3216 prop = parms[i];
3217 val = values[i];
3218 store_frame_param (f, prop, val);
3220 if (EQ (prop, Qforeground_color)
3221 || EQ (prop, Qbackground_color))
3222 update_face_from_frame_parameter (f, prop, val);
3225 SAFE_FREE ();
3227 return Qnil;
3230 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
3231 0, 1, 0,
3232 doc: /* Height in pixels of a line in the font in frame FRAME.
3233 If FRAME is omitted or nil, the selected frame is used.
3234 For a terminal frame, the value is always 1. */)
3235 (Lisp_Object frame)
3237 #ifdef HAVE_WINDOW_SYSTEM
3238 struct frame *f = decode_any_frame (frame);
3240 if (FRAME_WINDOW_P (f))
3241 return make_number (FRAME_LINE_HEIGHT (f));
3242 else
3243 #endif
3244 return make_number (1);
3248 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
3249 0, 1, 0,
3250 doc: /* Width in pixels of characters in the font in frame FRAME.
3251 If FRAME is omitted or nil, the selected frame is used.
3252 On a graphical screen, the width is the standard width of the default font.
3253 For a terminal screen, the value is always 1. */)
3254 (Lisp_Object frame)
3256 #ifdef HAVE_WINDOW_SYSTEM
3257 struct frame *f = decode_any_frame (frame);
3259 if (FRAME_WINDOW_P (f))
3260 return make_number (FRAME_COLUMN_WIDTH (f));
3261 else
3262 #endif
3263 return make_number (1);
3266 DEFUN ("frame-native-width", Fframe_native_width,
3267 Sframe_native_width, 0, 1, 0,
3268 doc: /* Return FRAME's native width in pixels.
3269 For a terminal frame, the result really gives the width in characters.
3270 If FRAME is omitted or nil, the selected frame is used. */)
3271 (Lisp_Object frame)
3273 struct frame *f = decode_any_frame (frame);
3275 #ifdef HAVE_WINDOW_SYSTEM
3276 if (FRAME_WINDOW_P (f))
3277 return make_number (FRAME_PIXEL_WIDTH (f));
3278 else
3279 #endif
3280 return make_number (FRAME_TOTAL_COLS (f));
3283 DEFUN ("frame-native-height", Fframe_native_height,
3284 Sframe_native_height, 0, 1, 0,
3285 doc: /* Return FRAME's native height in pixels.
3286 If FRAME is omitted or nil, the selected frame is used. The exact value
3287 of the result depends on the window-system and toolkit in use:
3289 In the Gtk+ and NS versions, it includes only any window (including the
3290 minibuffer or echo area), mode line, and header line. It does not
3291 include the tool bar or menu bar. With other graphical versions, it may
3292 also include the tool bar and the menu bar.
3294 For a text terminal, it includes the menu bar. In this case, the
3295 result is really in characters rather than pixels (i.e., is identical
3296 to `frame-height'). */)
3297 (Lisp_Object frame)
3299 struct frame *f = decode_any_frame (frame);
3301 #ifdef HAVE_WINDOW_SYSTEM
3302 if (FRAME_WINDOW_P (f))
3303 return make_number (FRAME_PIXEL_HEIGHT (f));
3304 else
3305 #endif
3306 return make_number (FRAME_TOTAL_LINES (f));
3309 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
3310 Stool_bar_pixel_width, 0, 1, 0,
3311 doc: /* Return width in pixels of FRAME's tool bar.
3312 The result is greater than zero only when the tool bar is on the left
3313 or right side of FRAME. If FRAME is omitted or nil, the selected frame
3314 is used. */)
3315 (Lisp_Object frame)
3317 #ifdef FRAME_TOOLBAR_WIDTH
3318 struct frame *f = decode_any_frame (frame);
3320 if (FRAME_WINDOW_P (f))
3321 return make_number (FRAME_TOOLBAR_WIDTH (f));
3322 #endif
3323 return make_number (0);
3326 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
3327 doc: /* Return width in columns of FRAME's text area. */)
3328 (Lisp_Object frame)
3330 return make_number (FRAME_COLS (decode_any_frame (frame)));
3333 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
3334 doc: /* Return height in lines of FRAME's text area. */)
3335 (Lisp_Object frame)
3337 return make_number (FRAME_LINES (decode_any_frame (frame)));
3340 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
3341 doc: /* Return number of total columns of FRAME. */)
3342 (Lisp_Object frame)
3344 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
3347 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
3348 doc: /* Return number of total lines of FRAME. */)
3349 (Lisp_Object frame)
3351 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
3354 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
3355 doc: /* Return text area width of FRAME in pixels. */)
3356 (Lisp_Object frame)
3358 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
3361 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
3362 doc: /* Return text area height of FRAME in pixels. */)
3363 (Lisp_Object frame)
3365 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
3368 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
3369 doc: /* Return scroll bar width of FRAME in pixels. */)
3370 (Lisp_Object frame)
3372 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
3375 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
3376 doc: /* Return scroll bar height of FRAME in pixels. */)
3377 (Lisp_Object frame)
3379 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
3382 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
3383 doc: /* Return fringe width of FRAME in pixels. */)
3384 (Lisp_Object frame)
3386 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
3389 DEFUN ("frame-internal-border-width", Fframe_internal_border_width, Sframe_internal_border_width, 0, 1, 0,
3390 doc: /* Return width of FRAME's internal border in pixels. */)
3391 (Lisp_Object frame)
3393 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
3396 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
3397 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
3398 (Lisp_Object frame)
3400 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
3403 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
3404 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
3405 (Lisp_Object frame)
3407 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
3410 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
3411 doc: /* Set text height of frame FRAME to HEIGHT lines.
3412 Optional third arg PRETEND non-nil means that redisplay should use
3413 HEIGHT lines but that the idea of the actual height of the frame should
3414 not be changed.
3416 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3417 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
3418 window managers may refuse to honor a HEIGHT that is not an integer
3419 multiple of the default frame font height. */)
3420 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
3422 struct frame *f = decode_live_frame (frame);
3423 int pixel_height;
3425 CHECK_TYPE_RANGED_INTEGER (int, height);
3427 pixel_height = (!NILP (pixelwise)
3428 ? XINT (height)
3429 : XINT (height) * FRAME_LINE_HEIGHT (f));
3430 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
3432 return Qnil;
3435 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
3436 doc: /* Set text width of frame FRAME to WIDTH columns.
3437 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
3438 columns but that the idea of the actual width of the frame should not
3439 be changed.
3441 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3442 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
3443 window managers may refuse to honor a WIDTH that is not an integer
3444 multiple of the default frame font width. */)
3445 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
3447 struct frame *f = decode_live_frame (frame);
3448 int pixel_width;
3450 CHECK_TYPE_RANGED_INTEGER (int, width);
3452 pixel_width = (!NILP (pixelwise)
3453 ? XINT (width)
3454 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3455 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
3457 return Qnil;
3460 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
3461 doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
3462 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
3463 When `frame-resize-pixelwise' is nil, some window managers may refuse to
3464 honor a WIDTH that is not an integer multiple of the default frame font
3465 width or a HEIGHT that is not an integer multiple of the default frame
3466 font height. */)
3467 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
3469 struct frame *f = decode_live_frame (frame);
3470 int pixel_width, pixel_height;
3472 CHECK_TYPE_RANGED_INTEGER (int, width);
3473 CHECK_TYPE_RANGED_INTEGER (int, height);
3475 pixel_width = (!NILP (pixelwise)
3476 ? XINT (width)
3477 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3478 pixel_height = (!NILP (pixelwise)
3479 ? XINT (height)
3480 : XINT (height) * FRAME_LINE_HEIGHT (f));
3481 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
3483 return Qnil;
3486 DEFUN ("frame-position", Fframe_position,
3487 Sframe_position, 0, 1, 0,
3488 doc: /* Return top left corner of FRAME in pixels.
3489 FRAME must be a live frame and defaults to the selected one. The return
3490 value is a cons (x, y) of the coordinates of the top left corner of
3491 FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
3492 display. */)
3493 (Lisp_Object frame)
3495 register struct frame *f = decode_live_frame (frame);
3497 return Fcons (make_number (f->left_pos), make_number (f->top_pos));
3500 DEFUN ("set-frame-position", Fset_frame_position,
3501 Sset_frame_position, 3, 3, 0,
3502 doc: /* Set position of FRAME to (X, Y).
3503 FRAME must be a live frame and defaults to the selected one. X and Y,
3504 if positive, specify the coordinate of the left and top edge of FRAME's
3505 outer frame in pixels relative to an origin (0, 0) of FRAME's display.
3506 If any of X or Y is negative, it specifies the coordinates of the right
3507 or bottom edge of the outer frame of FRAME relative to the right or
3508 bottom edge of FRAME's display. */)
3509 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
3511 struct frame *f = decode_live_frame (frame);
3513 CHECK_TYPE_RANGED_INTEGER (int, x);
3514 CHECK_TYPE_RANGED_INTEGER (int, y);
3516 /* I think this should be done with a hook. */
3517 if (FRAME_WINDOW_P (f))
3519 #ifdef HAVE_WINDOW_SYSTEM
3520 x_set_offset (f, XINT (x), XINT (y), 1);
3521 #endif
3524 return Qt;
3527 /***********************************************************************
3528 Frame Parameters
3529 ***********************************************************************/
3531 /* Connect the frame-parameter names for X frames
3532 to the ways of passing the parameter values to the window system.
3534 The name of a parameter, as a Lisp symbol,
3535 has an `x-frame-parameter' property which is an integer in Lisp
3536 that is an index in this table. */
3538 struct frame_parm_table {
3539 const char *name;
3540 int sym;
3543 static const struct frame_parm_table frame_parms[] =
3545 {"auto-raise", SYMBOL_INDEX (Qauto_raise)},
3546 {"auto-lower", SYMBOL_INDEX (Qauto_lower)},
3547 {"background-color", -1},
3548 {"border-color", SYMBOL_INDEX (Qborder_color)},
3549 {"border-width", SYMBOL_INDEX (Qborder_width)},
3550 {"cursor-color", SYMBOL_INDEX (Qcursor_color)},
3551 {"cursor-type", SYMBOL_INDEX (Qcursor_type)},
3552 {"font", -1},
3553 {"foreground-color", -1},
3554 {"icon-name", SYMBOL_INDEX (Qicon_name)},
3555 {"icon-type", SYMBOL_INDEX (Qicon_type)},
3556 {"internal-border-width", SYMBOL_INDEX (Qinternal_border_width)},
3557 {"right-divider-width", SYMBOL_INDEX (Qright_divider_width)},
3558 {"bottom-divider-width", SYMBOL_INDEX (Qbottom_divider_width)},
3559 {"menu-bar-lines", SYMBOL_INDEX (Qmenu_bar_lines)},
3560 {"mouse-color", SYMBOL_INDEX (Qmouse_color)},
3561 {"name", SYMBOL_INDEX (Qname)},
3562 {"scroll-bar-width", SYMBOL_INDEX (Qscroll_bar_width)},
3563 {"scroll-bar-height", SYMBOL_INDEX (Qscroll_bar_height)},
3564 {"title", SYMBOL_INDEX (Qtitle)},
3565 {"unsplittable", SYMBOL_INDEX (Qunsplittable)},
3566 {"vertical-scroll-bars", SYMBOL_INDEX (Qvertical_scroll_bars)},
3567 {"horizontal-scroll-bars", SYMBOL_INDEX (Qhorizontal_scroll_bars)},
3568 {"visibility", SYMBOL_INDEX (Qvisibility)},
3569 {"tool-bar-lines", SYMBOL_INDEX (Qtool_bar_lines)},
3570 {"scroll-bar-foreground", SYMBOL_INDEX (Qscroll_bar_foreground)},
3571 {"scroll-bar-background", SYMBOL_INDEX (Qscroll_bar_background)},
3572 {"screen-gamma", SYMBOL_INDEX (Qscreen_gamma)},
3573 {"line-spacing", SYMBOL_INDEX (Qline_spacing)},
3574 {"left-fringe", SYMBOL_INDEX (Qleft_fringe)},
3575 {"right-fringe", SYMBOL_INDEX (Qright_fringe)},
3576 {"wait-for-wm", SYMBOL_INDEX (Qwait_for_wm)},
3577 {"fullscreen", SYMBOL_INDEX (Qfullscreen)},
3578 {"font-backend", SYMBOL_INDEX (Qfont_backend)},
3579 {"alpha", SYMBOL_INDEX (Qalpha)},
3580 {"sticky", SYMBOL_INDEX (Qsticky)},
3581 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3582 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3583 {"undecorated", SYMBOL_INDEX (Qundecorated)},
3584 {"parent-frame", SYMBOL_INDEX (Qparent_frame)},
3585 {"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
3586 {"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
3587 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3588 {"z-group", SYMBOL_INDEX (Qz_group)},
3589 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3590 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
3591 #ifdef NS_IMPL_COCOA
3592 {"ns-appearance", SYMBOL_INDEX (Qns_appearance)},
3593 {"ns-transparent-titlebar", SYMBOL_INDEX (Qns_transparent_titlebar)},
3594 #endif
3597 #ifdef HAVE_WINDOW_SYSTEM
3599 /* Enumeration type for switch in frame_float. */
3600 enum frame_float_type
3602 FRAME_FLOAT_WIDTH,
3603 FRAME_FLOAT_HEIGHT,
3604 FRAME_FLOAT_LEFT,
3605 FRAME_FLOAT_TOP
3609 * frame_float:
3611 * Process the value VAL of the float type frame parameter 'width',
3612 * 'height', 'left', or 'top' specified via a frame_float_type
3613 * enumeration type WHAT for frame F. Such parameters relate the outer
3614 * size or position of F to the size of the F's display or parent frame
3615 * which have to be both available in some way.
3617 * The return value is a size or position value in pixels. VAL must be
3618 * in the range 0.0 to 1.0 where a width/height of 0.0 means to return 0
3619 * and 1.0 means to return the full width/height of the display/parent.
3620 * For positions, 0.0 means position in the left/top corner of the
3621 * display/parent while 1.0 means to position at the right/bottom corner
3622 * of the display/parent frame.
3624 * Set PARENT_DONE and OUTER_DONE to avoid recalculation of the outer
3625 * size or parent or display attributes when more float parameters are
3626 * calculated in a row: -1 means not processed yet, 0 means processing
3627 * failed, 1 means processing succeeded.
3629 * Return DEFAULT_VALUE when processing fails for whatever reason with
3630 * one exception: When calculating F's outer edges fails (probably
3631 * because F has not been created yet) return the difference between F's
3632 * native and text size.
3634 static int
3635 frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
3636 int *parent_done, int *outer_done, int default_value)
3638 double d_val = XFLOAT_DATA (val);
3640 if (d_val < 0.0 || d_val > 1.0)
3641 /* Invalid VAL. */
3642 return default_value;
3643 else
3645 static unsigned parent_width, parent_height;
3646 static int parent_left, parent_top;
3647 static unsigned outer_minus_text_width, outer_minus_text_height;
3648 struct frame *p = FRAME_PARENT_FRAME (f);
3650 if (*parent_done == 1)
3652 else if (p)
3654 parent_width = FRAME_PIXEL_WIDTH (p);
3655 parent_height = FRAME_PIXEL_HEIGHT (p);
3656 *parent_done = 1;
3658 else
3660 if (*parent_done == 0)
3661 /* No workarea available. */
3662 return default_value;
3663 else if (*parent_done == -1)
3665 Lisp_Object monitor_attributes;
3666 Lisp_Object workarea;
3667 Lisp_Object frame;
3669 XSETFRAME (frame, f);
3670 monitor_attributes = Fcar (call1 (Qdisplay_monitor_attributes_list, frame));
3671 if (NILP (monitor_attributes))
3673 /* No monitor attributes available. */
3674 *parent_done = 0;
3676 return default_value;
3679 workarea = Fcdr (Fassq (Qworkarea, monitor_attributes));
3680 if (NILP (workarea))
3682 /* No workarea available. */
3683 *parent_done = 0;
3685 return default_value;
3688 /* Workarea available. */
3689 parent_left = XINT (Fnth (make_number (0), workarea));
3690 parent_top = XINT (Fnth (make_number (1), workarea));
3691 parent_width = XINT (Fnth (make_number (2), workarea));
3692 parent_height = XINT (Fnth (make_number (3), workarea));
3693 *parent_done = 1;
3697 if (*outer_done == 1)
3699 else if (FRAME_UNDECORATED (f))
3701 outer_minus_text_width
3702 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3703 outer_minus_text_height
3704 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3705 *outer_done = 1;
3707 else if (*outer_done == 0)
3708 /* No outer size available. */
3709 return default_value;
3710 else if (*outer_done == -1)
3712 Lisp_Object frame, outer_edges;
3714 XSETFRAME (frame, f);
3715 outer_edges = call2 (Qframe_edges, frame, Qouter_edges);
3717 if (!NILP (outer_edges))
3719 outer_minus_text_width
3720 = (XINT (Fnth (make_number (2), outer_edges))
3721 - XINT (Fnth (make_number (0), outer_edges))
3722 - FRAME_TEXT_WIDTH (f));
3723 outer_minus_text_height
3724 = (XINT (Fnth (make_number (3), outer_edges))
3725 - XINT (Fnth (make_number (1), outer_edges))
3726 - FRAME_TEXT_HEIGHT (f));
3728 else
3730 /* If we can't get any outer edges, proceed as if the frame
3731 were undecorated. */
3732 outer_minus_text_width
3733 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3734 outer_minus_text_height
3735 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3738 *outer_done = 1;
3741 switch (what)
3743 case FRAME_FLOAT_WIDTH:
3744 return parent_width * d_val - outer_minus_text_width;
3746 case FRAME_FLOAT_HEIGHT:
3747 return parent_height * d_val - outer_minus_text_height;
3749 case FRAME_FLOAT_LEFT:
3751 int rest_width = (parent_width
3752 - FRAME_TEXT_WIDTH (f)
3753 - outer_minus_text_width);
3755 if (p)
3756 return (rest_width <= 0 ? 0 : d_val * rest_width);
3757 else
3758 return (rest_width <= 0
3759 ? parent_left
3760 : parent_left + d_val * rest_width);
3762 case FRAME_FLOAT_TOP:
3764 int rest_height = (parent_height
3765 - FRAME_TEXT_HEIGHT (f)
3766 - outer_minus_text_height);
3768 if (p)
3769 return (rest_height <= 0 ? 0 : d_val * rest_height);
3770 else
3771 return (rest_height <= 0
3772 ? parent_top
3773 : parent_top + d_val * rest_height);
3775 default:
3776 emacs_abort ();
3781 /* Change the parameters of frame F as specified by ALIST.
3782 If a parameter is not specially recognized, do nothing special;
3783 otherwise call the `x_set_...' function for that parameter.
3784 Except for certain geometry properties, always call store_frame_param
3785 to store the new value in the parameter alist. */
3787 void
3788 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3790 Lisp_Object tail, frame;
3793 /* If both of these parameters are present, it's more efficient to
3794 set them both at once. So we wait until we've looked at the
3795 entire list before we set them. */
3796 int width = -1, height = -1; /* -1 denotes they were not changed. */
3798 /* Same here. */
3799 Lisp_Object left, top;
3801 /* Same with these. */
3802 Lisp_Object icon_left, icon_top;
3804 /* And with this. */
3805 Lisp_Object fullscreen;
3806 bool fullscreen_change = false;
3808 /* Record in these vectors all the parms specified. */
3809 Lisp_Object *parms;
3810 Lisp_Object *values;
3811 ptrdiff_t i, j, size;
3812 bool left_no_change = 0, top_no_change = 0;
3813 #ifdef HAVE_X_WINDOWS
3814 bool icon_left_no_change = 0, icon_top_no_change = 0;
3815 #endif
3816 int parent_done = -1, outer_done = -1;
3818 XSETFRAME (frame, f);
3819 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
3820 size++;
3821 CHECK_LIST_END (tail, alist);
3823 USE_SAFE_ALLOCA;
3824 SAFE_ALLOCA_LISP (parms, 2 * size);
3825 values = parms + size;
3827 /* Extract parm names and values into those vectors. */
3829 i = 0, j = size - 1;
3830 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3832 Lisp_Object elt = XCAR (tail), prop = Fcar (elt), val = Fcdr (elt);
3834 /* Some properties are independent of other properties, but other
3835 properties are dependent upon them. These special properties
3836 are foreground_color, background_color (affects cursor_color)
3837 and font (affects fringe widths); they're recorded starting
3838 from the end of PARMS and VALUES to process them first by using
3839 reverse iteration. */
3841 if (EQ (prop, Qforeground_color)
3842 || EQ (prop, Qbackground_color)
3843 || EQ (prop, Qfont))
3845 parms[j] = prop;
3846 values[j] = val;
3847 j--;
3849 else
3851 parms[i] = prop;
3852 values[i] = val;
3853 i++;
3857 /* TAIL and ALIST are not used again below here. */
3858 alist = tail = Qnil;
3860 top = left = Qunbound;
3861 icon_left = icon_top = Qunbound;
3863 /* Reverse order is used to make sure that special
3864 properties noticed above are processed first. */
3865 for (i = size - 1; i >= 0; i--)
3867 Lisp_Object prop, val;
3869 prop = parms[i];
3870 val = values[i];
3872 if (EQ (prop, Qwidth))
3874 if (RANGED_INTEGERP (0, val, INT_MAX))
3875 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3876 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3877 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3878 width = XFASTINT (XCDR (val));
3879 else if (FLOATP (val))
3880 width = frame_float (f, val, FRAME_FLOAT_WIDTH, &parent_done,
3881 &outer_done, -1);
3883 else if (EQ (prop, Qheight))
3885 if (RANGED_INTEGERP (0, val, INT_MAX))
3886 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3887 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3888 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3889 height = XFASTINT (XCDR (val));
3890 else if (FLOATP (val))
3891 height = frame_float (f, val, FRAME_FLOAT_HEIGHT, &parent_done,
3892 &outer_done, -1);
3894 else if (EQ (prop, Qtop))
3895 top = val;
3896 else if (EQ (prop, Qleft))
3897 left = val;
3898 else if (EQ (prop, Qicon_top))
3899 icon_top = val;
3900 else if (EQ (prop, Qicon_left))
3901 icon_left = val;
3902 else if (EQ (prop, Qfullscreen))
3904 fullscreen = val;
3905 fullscreen_change = true;
3907 else
3909 register Lisp_Object param_index, old_value;
3911 old_value = get_frame_param (f, prop);
3913 store_frame_param (f, prop, val);
3915 param_index = Fget (prop, Qx_frame_parameter);
3916 if (NATNUMP (param_index)
3917 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3918 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3919 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3923 /* Don't die if just one of these was set. */
3924 if (EQ (left, Qunbound))
3926 left_no_change = 1;
3927 if (f->left_pos < 0)
3928 left = list2 (Qplus, make_number (f->left_pos));
3929 else
3930 XSETINT (left, f->left_pos);
3932 if (EQ (top, Qunbound))
3934 top_no_change = 1;
3935 if (f->top_pos < 0)
3936 top = list2 (Qplus, make_number (f->top_pos));
3937 else
3938 XSETINT (top, f->top_pos);
3941 /* If one of the icon positions was not set, preserve or default it. */
3942 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3944 #ifdef HAVE_X_WINDOWS
3945 icon_left_no_change = 1;
3946 #endif
3947 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3948 if (NILP (icon_left))
3949 XSETINT (icon_left, 0);
3951 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3953 #ifdef HAVE_X_WINDOWS
3954 icon_top_no_change = 1;
3955 #endif
3956 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3957 if (NILP (icon_top))
3958 XSETINT (icon_top, 0);
3961 /* Don't set these parameters unless they've been explicitly
3962 specified. The window might be mapped or resized while we're in
3963 this function, and we don't want to override that unless the lisp
3964 code has asked for it.
3966 Don't set these parameters unless they actually differ from the
3967 window's current parameters; the window may not actually exist
3968 yet. */
3969 if ((width != -1 && width != FRAME_TEXT_WIDTH (f))
3970 || (height != -1 && height != FRAME_TEXT_HEIGHT (f)))
3971 /* We could consider checking f->after_make_frame here, but I
3972 don't have the faintest idea why the following is needed at
3973 all. With the old setting it can get a Heisenbug when
3974 EmacsFrameResize intermittently provokes a delayed
3975 change_frame_size in the middle of adjust_frame_size. */
3976 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
3977 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters);
3979 if ((!NILP (left) || !NILP (top))
3980 && ! (left_no_change && top_no_change)
3981 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3982 && NUMBERP (top) && XINT (top) == f->top_pos))
3984 int leftpos = 0;
3985 int toppos = 0;
3987 /* Record the signs. */
3988 f->size_hint_flags &= ~ (XNegative | YNegative);
3989 if (EQ (left, Qminus))
3990 f->size_hint_flags |= XNegative;
3991 else if (TYPE_RANGED_INTEGERP (int, left))
3993 leftpos = XINT (left);
3994 if (leftpos < 0)
3995 f->size_hint_flags |= XNegative;
3997 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3998 && CONSP (XCDR (left))
3999 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
4001 leftpos = - XINT (XCAR (XCDR (left)));
4002 f->size_hint_flags |= XNegative;
4004 else if (CONSP (left) && EQ (XCAR (left), Qplus)
4005 && CONSP (XCDR (left))
4006 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
4007 leftpos = XINT (XCAR (XCDR (left)));
4008 else if (FLOATP (left))
4009 leftpos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
4010 &outer_done, 0);
4012 if (EQ (top, Qminus))
4013 f->size_hint_flags |= YNegative;
4014 else if (TYPE_RANGED_INTEGERP (int, top))
4016 toppos = XINT (top);
4017 if (toppos < 0)
4018 f->size_hint_flags |= YNegative;
4020 else if (CONSP (top) && EQ (XCAR (top), Qminus)
4021 && CONSP (XCDR (top))
4022 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
4024 toppos = - XINT (XCAR (XCDR (top)));
4025 f->size_hint_flags |= YNegative;
4027 else if (CONSP (top) && EQ (XCAR (top), Qplus)
4028 && CONSP (XCDR (top))
4029 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
4030 toppos = XINT (XCAR (XCDR (top)));
4031 else if (FLOATP (top))
4032 toppos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
4033 &outer_done, 0);
4035 /* Store the numeric value of the position. */
4036 f->top_pos = toppos;
4037 f->left_pos = leftpos;
4039 f->win_gravity = NorthWestGravity;
4041 /* Actually set that position, and convert to absolute. */
4042 x_set_offset (f, leftpos, toppos, -1);
4045 if (fullscreen_change)
4047 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
4049 frame_size_history_add
4050 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
4052 store_frame_param (f, Qfullscreen, fullscreen);
4053 if (!EQ (fullscreen, old_value))
4054 x_set_fullscreen (f, fullscreen, old_value);
4058 #ifdef HAVE_X_WINDOWS
4059 if ((!NILP (icon_left) || !NILP (icon_top))
4060 && ! (icon_left_no_change && icon_top_no_change))
4061 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
4062 #endif /* HAVE_X_WINDOWS */
4064 SAFE_FREE ();
4068 /* Insert a description of internally-recorded parameters of frame X
4069 into the parameter alist *ALISTPTR that is to be given to the user.
4070 Only parameters that are specific to the X window system
4071 and whose values are not correctly recorded in the frame's
4072 param_alist need to be considered here. */
4074 void
4075 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
4077 Lisp_Object tem;
4078 uprintmax_t w;
4079 char buf[INT_BUFSIZE_BOUND (w)];
4081 /* Represent negative positions (off the top or left screen edge)
4082 in a way that Fmodify_frame_parameters will understand correctly. */
4083 XSETINT (tem, f->left_pos);
4084 if (f->left_pos >= 0)
4085 store_in_alist (alistptr, Qleft, tem);
4086 else
4087 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
4089 XSETINT (tem, f->top_pos);
4090 if (f->top_pos >= 0)
4091 store_in_alist (alistptr, Qtop, tem);
4092 else
4093 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
4095 store_in_alist (alistptr, Qborder_width,
4096 make_number (f->border_width));
4097 store_in_alist (alistptr, Qinternal_border_width,
4098 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
4099 store_in_alist (alistptr, Qright_divider_width,
4100 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
4101 store_in_alist (alistptr, Qbottom_divider_width,
4102 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
4103 store_in_alist (alistptr, Qleft_fringe,
4104 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
4105 store_in_alist (alistptr, Qright_fringe,
4106 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
4107 store_in_alist (alistptr, Qscroll_bar_width,
4108 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4109 ? make_number (0)
4110 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
4111 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4112 /* nil means "use default width"
4113 for non-toolkit scroll bar.
4114 ruler-mode.el depends on this. */
4115 : Qnil));
4116 store_in_alist (alistptr, Qscroll_bar_height,
4117 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
4118 ? make_number (0)
4119 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
4120 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4121 /* nil means "use default height"
4122 for non-toolkit scroll bar. */
4123 : Qnil));
4124 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
4125 MS-Windows it returns a value whose type is HANDLE, which is
4126 actually a pointer. Explicit casting avoids compiler
4127 warnings. */
4128 w = (uintptr_t) FRAME_X_WINDOW (f);
4129 store_in_alist (alistptr, Qwindow_id,
4130 make_formatted_string (buf, "%"pMu, w));
4131 #ifdef HAVE_X_WINDOWS
4132 #ifdef USE_X_TOOLKIT
4133 /* Tooltip frame may not have this widget. */
4134 if (FRAME_X_OUTPUT (f)->widget)
4135 #endif
4136 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
4137 store_in_alist (alistptr, Qouter_window_id,
4138 make_formatted_string (buf, "%"pMu, w));
4139 #endif
4140 store_in_alist (alistptr, Qicon_name, f->icon_name);
4141 store_in_alist (alistptr, Qvisibility,
4142 (FRAME_VISIBLE_P (f) ? Qt
4143 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
4144 store_in_alist (alistptr, Qdisplay,
4145 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
4147 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
4148 tem = Qnil;
4149 else
4150 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
4151 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
4152 store_in_alist (alistptr, Qparent_id, tem);
4153 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
4157 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
4158 the previous value of that parameter, NEW_VALUE is the new value. */
4160 void
4161 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4163 if (NILP (new_value))
4164 f->want_fullscreen = FULLSCREEN_NONE;
4165 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
4166 f->want_fullscreen = FULLSCREEN_BOTH;
4167 else if (EQ (new_value, Qfullwidth))
4168 f->want_fullscreen = FULLSCREEN_WIDTH;
4169 else if (EQ (new_value, Qfullheight))
4170 f->want_fullscreen = FULLSCREEN_HEIGHT;
4171 else if (EQ (new_value, Qmaximized))
4172 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
4174 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
4175 FRAME_TERMINAL (f)->fullscreen_hook (f);
4179 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
4180 the previous value of that parameter, NEW_VALUE is the new value. */
4182 void
4183 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4185 if (NILP (new_value))
4186 f->extra_line_spacing = 0;
4187 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
4188 f->extra_line_spacing = XFASTINT (new_value);
4189 else if (FLOATP (new_value))
4191 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
4193 if (new_spacing >= 0)
4194 f->extra_line_spacing = new_spacing;
4195 else
4196 signal_error ("Invalid line-spacing", new_value);
4198 else
4199 signal_error ("Invalid line-spacing", new_value);
4200 if (FRAME_VISIBLE_P (f))
4201 redraw_frame (f);
4205 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
4206 the previous value of that parameter, NEW_VALUE is the new value. */
4208 void
4209 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4211 Lisp_Object bgcolor;
4213 if (NILP (new_value))
4214 f->gamma = 0;
4215 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
4216 /* The value 0.4545 is the normal viewing gamma. */
4217 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
4218 else
4219 signal_error ("Invalid screen-gamma", new_value);
4221 /* Apply the new gamma value to the frame background. */
4222 bgcolor = Fassq (Qbackground_color, f->param_alist);
4223 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
4225 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
4226 if (NATNUMP (parm_index)
4227 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
4228 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4229 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4230 (f, bgcolor, Qnil);
4233 clear_face_cache (true); /* FIXME: Why of all frames? */
4234 fset_redisplay (f);
4238 void
4239 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4241 Lisp_Object font_object;
4242 int fontset = -1;
4243 #ifdef HAVE_X_WINDOWS
4244 Lisp_Object font_param = arg;
4245 #endif
4247 /* Set the frame parameter back to the old value because we may
4248 fail to use ARG as the new parameter value. */
4249 store_frame_param (f, Qfont, oldval);
4251 /* ARG is a fontset name, a font name, a cons of fontset name and a
4252 font object, or a font object. In the last case, this function
4253 never fail. */
4254 if (STRINGP (arg))
4256 fontset = fs_query_fontset (arg, 0);
4257 if (fontset < 0)
4259 font_object = font_open_by_name (f, arg);
4260 if (NILP (font_object))
4261 error ("Font `%s' is not defined", SSDATA (arg));
4262 arg = AREF (font_object, FONT_NAME_INDEX);
4264 else if (fontset > 0)
4266 font_object = font_open_by_name (f, fontset_ascii (fontset));
4267 if (NILP (font_object))
4268 error ("Font `%s' is not defined", SDATA (arg));
4269 arg = AREF (font_object, FONT_NAME_INDEX);
4271 else
4272 error ("The default fontset can't be used for a frame font");
4274 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
4276 /* This is the case that the ASCII font of F's fontset XCAR
4277 (arg) is changed to the font XCDR (arg) by
4278 `set-fontset-font'. */
4279 fontset = fs_query_fontset (XCAR (arg), 0);
4280 if (fontset < 0)
4281 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
4282 font_object = XCDR (arg);
4283 arg = AREF (font_object, FONT_NAME_INDEX);
4284 #ifdef HAVE_X_WINDOWS
4285 font_param = Ffont_get (font_object, QCname);
4286 #endif
4288 else if (FONT_OBJECT_P (arg))
4290 font_object = arg;
4291 #ifdef HAVE_X_WINDOWS
4292 font_param = Ffont_get (font_object, QCname);
4293 #endif
4294 /* This is to store the XLFD font name in the frame parameter for
4295 backward compatibility. We should store the font-object
4296 itself in the future. */
4297 arg = AREF (font_object, FONT_NAME_INDEX);
4298 fontset = FRAME_FONTSET (f);
4299 /* Check if we can use the current fontset. If not, set FONTSET
4300 to -1 to generate a new fontset from FONT-OBJECT. */
4301 if (fontset >= 0)
4303 Lisp_Object ascii_font = fontset_ascii (fontset);
4304 Lisp_Object spec = font_spec_from_name (ascii_font);
4306 /* SPEC might be nil because ASCII_FONT's name doesn't parse
4307 according to stupid XLFD rules, which, for example,
4308 disallow font names that include a dash followed by a
4309 number. So in those cases we simply request x_new_font
4310 below to generate a new fontset. */
4311 if (NILP (spec) || ! font_match_p (spec, font_object))
4312 fontset = -1;
4315 else
4316 signal_error ("Invalid font", arg);
4318 if (! NILP (Fequal (font_object, oldval)))
4319 return;
4321 x_new_font (f, font_object, fontset);
4322 store_frame_param (f, Qfont, arg);
4323 #ifdef HAVE_X_WINDOWS
4324 store_frame_param (f, Qfont_parameter, font_param);
4325 #endif
4326 /* Recalculate toolbar height. */
4327 f->n_tool_bar_rows = 0;
4329 /* Ensure we redraw it. */
4330 clear_current_matrices (f);
4332 /* Attempt to hunt down bug#16028. */
4333 SET_FRAME_GARBAGED (f);
4335 /* This is important if we are called by some Lisp as part of
4336 redisplaying the frame, see redisplay_internal. */
4337 f->fonts_changed = true;
4339 recompute_basic_faces (f);
4341 do_pending_window_change (0);
4343 /* We used to call face-set-after-frame-default here, but it leads to
4344 recursive calls (since that function can set the `default' face's
4345 font which in turns changes the frame's `font' parameter).
4346 Also I don't know what this call is meant to do, but it seems the
4347 wrong way to do it anyway (it does a lot more work than what seems
4348 reasonable in response to a change to `font'). */
4352 void
4353 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4355 if (! NILP (new_value)
4356 && !CONSP (new_value))
4358 char *p0, *p1;
4360 CHECK_STRING (new_value);
4361 p0 = p1 = SSDATA (new_value);
4362 new_value = Qnil;
4363 while (*p0)
4365 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
4366 if (p0 < p1)
4367 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
4368 new_value);
4369 if (*p1)
4371 int c;
4373 while ((c = *++p1) && c_isspace (c));
4375 p0 = p1;
4377 new_value = Fnreverse (new_value);
4380 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
4381 return;
4383 if (FRAME_FONT (f))
4384 free_all_realized_faces (Qnil);
4386 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
4387 if (NILP (new_value))
4389 if (NILP (old_value))
4390 error ("No font backend available");
4391 font_update_drivers (f, old_value);
4392 error ("None of specified font backends are available");
4394 store_frame_param (f, Qfont_backend, new_value);
4396 if (FRAME_FONT (f))
4398 Lisp_Object frame;
4400 XSETFRAME (frame, f);
4401 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
4402 face_change = true;
4403 windows_or_buffers_changed = 18;
4407 void
4408 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4410 int unit = FRAME_COLUMN_WIDTH (f);
4411 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
4412 int new_width;
4414 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4415 ? eabs (XINT (new_value)) : 8);
4417 if (new_width != old_width)
4419 f->left_fringe_width = new_width;
4420 f->fringe_cols /* Round up. */
4421 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
4423 if (FRAME_X_WINDOW (f) != 0)
4424 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
4426 SET_FRAME_GARBAGED (f);
4431 void
4432 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4434 int unit = FRAME_COLUMN_WIDTH (f);
4435 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
4436 int new_width;
4438 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4439 ? eabs (XINT (new_value)) : 8);
4441 if (new_width != old_width)
4443 f->right_fringe_width = new_width;
4444 f->fringe_cols /* Round up. */
4445 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
4447 if (FRAME_X_WINDOW (f) != 0)
4448 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
4450 SET_FRAME_GARBAGED (f);
4455 void
4456 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4458 CHECK_TYPE_RANGED_INTEGER (int, arg);
4460 if (XINT (arg) == f->border_width)
4461 return;
4463 if (FRAME_X_WINDOW (f) != 0)
4464 error ("Cannot change the border width of a frame");
4466 f->border_width = XINT (arg);
4469 void
4470 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4472 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
4473 CHECK_TYPE_RANGED_INTEGER (int, arg);
4474 int new = max (0, XINT (arg));
4475 if (new != old)
4477 f->right_divider_width = new;
4478 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
4479 adjust_frame_glyphs (f);
4480 SET_FRAME_GARBAGED (f);
4484 void
4485 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4487 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
4488 CHECK_TYPE_RANGED_INTEGER (int, arg);
4489 int new = max (0, XINT (arg));
4490 if (new != old)
4492 f->bottom_divider_width = new;
4493 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
4494 adjust_frame_glyphs (f);
4495 SET_FRAME_GARBAGED (f);
4499 void
4500 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
4502 Lisp_Object frame;
4503 XSETFRAME (frame, f);
4505 if (NILP (value))
4506 Fmake_frame_invisible (frame, Qt);
4507 else if (EQ (value, Qicon))
4508 Ficonify_frame (frame);
4509 else
4510 Fmake_frame_visible (frame);
4513 void
4514 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4516 f->auto_raise = !EQ (Qnil, arg);
4519 void
4520 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4522 f->auto_lower = !EQ (Qnil, arg);
4525 void
4526 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4528 f->no_split = !NILP (arg);
4531 void
4532 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4534 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4535 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
4536 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4537 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
4539 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
4540 = (NILP (arg)
4541 ? vertical_scroll_bar_none
4542 : EQ (Qleft, arg)
4543 ? vertical_scroll_bar_left
4544 : EQ (Qright, arg)
4545 ? vertical_scroll_bar_right
4546 : EQ (Qleft, Vdefault_frame_scroll_bars)
4547 ? vertical_scroll_bar_left
4548 : EQ (Qright, Vdefault_frame_scroll_bars)
4549 ? vertical_scroll_bar_right
4550 : vertical_scroll_bar_none);
4552 /* We set this parameter before creating the X window for the
4553 frame, so we can get the geometry right from the start.
4554 However, if the window hasn't been created yet, we shouldn't
4555 call x_set_window_size. */
4556 if (FRAME_X_WINDOW (f))
4557 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
4559 SET_FRAME_GARBAGED (f);
4563 void
4564 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4566 #if USE_HORIZONTAL_SCROLL_BARS
4567 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
4568 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
4570 f->horizontal_scroll_bars = NILP (arg) ? false : true;
4572 /* We set this parameter before creating the X window for the
4573 frame, so we can get the geometry right from the start.
4574 However, if the window hasn't been created yet, we shouldn't
4575 call x_set_window_size. */
4576 if (FRAME_X_WINDOW (f))
4577 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
4579 SET_FRAME_GARBAGED (f);
4581 #endif
4584 void
4585 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4587 int unit = FRAME_COLUMN_WIDTH (f);
4589 if (NILP (arg))
4591 x_set_scroll_bar_default_width (f);
4593 if (FRAME_X_WINDOW (f))
4594 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4596 SET_FRAME_GARBAGED (f);
4598 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4599 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4601 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
4602 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
4603 if (FRAME_X_WINDOW (f))
4604 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4606 SET_FRAME_GARBAGED (f);
4609 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
4610 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
4613 void
4614 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4616 #if USE_HORIZONTAL_SCROLL_BARS
4617 int unit = FRAME_LINE_HEIGHT (f);
4619 if (NILP (arg))
4621 x_set_scroll_bar_default_height (f);
4623 if (FRAME_X_WINDOW (f))
4624 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4626 SET_FRAME_GARBAGED (f);
4628 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4629 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4631 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
4632 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
4633 if (FRAME_X_WINDOW (f))
4634 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4636 SET_FRAME_GARBAGED (f);
4639 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
4640 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
4641 #endif
4644 void
4645 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4647 double alpha = 1.0;
4648 double newval[2];
4649 int i;
4650 Lisp_Object item;
4652 for (i = 0; i < 2; i++)
4654 newval[i] = 1.0;
4655 if (CONSP (arg))
4657 item = CAR (arg);
4658 arg = CDR (arg);
4660 else
4661 item = arg;
4663 if (NILP (item))
4664 alpha = - 1.0;
4665 else if (FLOATP (item))
4667 alpha = XFLOAT_DATA (item);
4668 if (! (0 <= alpha && alpha <= 1.0))
4669 args_out_of_range (make_float (0.0), make_float (1.0));
4671 else if (INTEGERP (item))
4673 EMACS_INT ialpha = XINT (item);
4674 if (! (0 <= ialpha && ialpha <= 100))
4675 args_out_of_range (make_number (0), make_number (100));
4676 alpha = ialpha / 100.0;
4678 else
4679 wrong_type_argument (Qnumberp, item);
4680 newval[i] = alpha;
4683 for (i = 0; i < 2; i++)
4684 f->alpha[i] = newval[i];
4686 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
4687 block_input ();
4688 x_set_frame_alpha (f);
4689 unblock_input ();
4690 #endif
4692 return;
4697 * x_set_no_special_glyphs:
4699 * Set frame F's `no-special-glyphs' parameter which, if non-nil,
4700 * suppresses the display of truncation and continuation glyphs
4701 * outside fringes.
4703 void
4704 x_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4706 if (!EQ (new_value, old_value))
4707 FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (new_value);
4711 #ifndef HAVE_NS
4713 /* Non-zero if mouse is grabbed on DPYINFO
4714 and we know the frame where it is. */
4716 bool x_mouse_grabbed (Display_Info *dpyinfo)
4718 return (dpyinfo->grabbed
4719 && dpyinfo->last_mouse_frame
4720 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
4723 /* Re-highlight something with mouse-face properties
4724 on DPYINFO using saved frame and mouse position. */
4726 void
4727 x_redo_mouse_highlight (Display_Info *dpyinfo)
4729 if (dpyinfo->last_mouse_motion_frame
4730 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
4731 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
4732 dpyinfo->last_mouse_motion_x,
4733 dpyinfo->last_mouse_motion_y);
4736 #endif /* HAVE_NS */
4738 /* Subroutines of creating an X frame. */
4740 /* Make sure that Vx_resource_name is set to a reasonable value.
4741 Fix it up, or set it to `emacs' if it is too hopeless. */
4743 void
4744 validate_x_resource_name (void)
4746 ptrdiff_t len = 0;
4747 /* Number of valid characters in the resource name. */
4748 ptrdiff_t good_count = 0;
4749 /* Number of invalid characters in the resource name. */
4750 ptrdiff_t bad_count = 0;
4751 Lisp_Object new;
4752 ptrdiff_t i;
4754 if (!STRINGP (Vx_resource_class))
4755 Vx_resource_class = build_string (EMACS_CLASS);
4757 if (STRINGP (Vx_resource_name))
4759 unsigned char *p = SDATA (Vx_resource_name);
4761 len = SBYTES (Vx_resource_name);
4763 /* Only letters, digits, - and _ are valid in resource names.
4764 Count the valid characters and count the invalid ones. */
4765 for (i = 0; i < len; i++)
4767 int c = p[i];
4768 if (! ((c >= 'a' && c <= 'z')
4769 || (c >= 'A' && c <= 'Z')
4770 || (c >= '0' && c <= '9')
4771 || c == '-' || c == '_'))
4772 bad_count++;
4773 else
4774 good_count++;
4777 else
4778 /* Not a string => completely invalid. */
4779 bad_count = 5, good_count = 0;
4781 /* If name is valid already, return. */
4782 if (bad_count == 0)
4783 return;
4785 /* If name is entirely invalid, or nearly so, or is so implausibly
4786 large that alloca might not work, use `emacs'. */
4787 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
4789 Vx_resource_name = build_string ("emacs");
4790 return;
4793 /* Name is partly valid. Copy it and replace the invalid characters
4794 with underscores. */
4796 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
4798 for (i = 0; i < len; i++)
4800 int c = SREF (new, i);
4801 if (! ((c >= 'a' && c <= 'z')
4802 || (c >= 'A' && c <= 'Z')
4803 || (c >= '0' && c <= '9')
4804 || c == '-' || c == '_'))
4805 SSET (new, i, '_');
4809 /* Get specified attribute from resource database RDB.
4810 See Fx_get_resource below for other parameters. */
4812 static Lisp_Object
4813 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
4815 CHECK_STRING (attribute);
4816 CHECK_STRING (class);
4818 if (!NILP (component))
4819 CHECK_STRING (component);
4820 if (!NILP (subclass))
4821 CHECK_STRING (subclass);
4822 if (NILP (component) != NILP (subclass))
4823 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
4825 validate_x_resource_name ();
4827 /* Allocate space for the components, the dots which separate them,
4828 and the final '\0'. Make them big enough for the worst case. */
4829 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4830 + (STRINGP (component)
4831 ? SBYTES (component) : 0)
4832 + SBYTES (attribute)
4833 + 3);
4835 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4836 + SBYTES (class)
4837 + (STRINGP (subclass)
4838 ? SBYTES (subclass) : 0)
4839 + 3);
4840 USE_SAFE_ALLOCA;
4841 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4842 char *class_key = name_key + name_keysize;
4843 name_key = ptr_bounds_clip (name_key, name_keysize);
4844 class_key = ptr_bounds_clip (class_key, class_keysize);
4846 /* Start with emacs.FRAMENAME for the name (the specific one)
4847 and with `Emacs' for the class key (the general one). */
4848 char *nz = lispstpcpy (name_key, Vx_resource_name);
4849 char *cz = lispstpcpy (class_key, Vx_resource_class);
4851 *cz++ = '.';
4852 cz = lispstpcpy (cz, class);
4854 if (!NILP (component))
4856 *cz++ = '.';
4857 lispstpcpy (cz, subclass);
4859 *nz++ = '.';
4860 nz = lispstpcpy (nz, component);
4863 *nz++ = '.';
4864 lispstpcpy (nz, attribute);
4866 char *value = x_get_string_resource (rdb, name_key, class_key);
4867 SAFE_FREE();
4869 if (value && *value)
4870 return build_string (value);
4871 else
4872 return Qnil;
4876 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4877 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4878 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4879 class, where INSTANCE is the name under which Emacs was invoked, or
4880 the name specified by the `-name' or `-rn' command-line arguments.
4882 The optional arguments COMPONENT and SUBCLASS add to the key and the
4883 class, respectively. You must specify both of them or neither.
4884 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4885 and the class is `Emacs.CLASS.SUBCLASS'. */)
4886 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4887 Lisp_Object subclass)
4889 check_window_system (NULL);
4891 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4892 attribute, class, component, subclass);
4895 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4897 Lisp_Object
4898 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4899 Lisp_Object class, Lisp_Object component,
4900 Lisp_Object subclass)
4902 return xrdb_get_resource (dpyinfo->xrdb,
4903 attribute, class, component, subclass);
4906 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
4907 /* Used when C code wants a resource value. */
4908 /* Called from oldXMenu/Create.c. */
4909 char *
4910 x_get_resource_string (const char *attribute, const char *class)
4912 char *result;
4913 struct frame *sf = SELECTED_FRAME ();
4914 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4915 USE_SAFE_ALLOCA;
4917 /* Allocate space for the components, the dots which separate them,
4918 and the final '\0'. */
4919 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4920 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4921 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4922 char *class_key = name_key + name_keysize;
4923 name_key = ptr_bounds_clip (name_key, name_keysize);
4924 class_key = ptr_bounds_clip (class_key, class_keysize);
4926 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4927 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4929 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4930 name_key, class_key);
4931 SAFE_FREE ();
4932 return result;
4934 #endif
4936 /* Return the value of parameter PARAM.
4938 First search ALIST, then Vdefault_frame_alist, then the X defaults
4939 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4941 Convert the resource to the type specified by desired_type.
4943 If no default is specified, return Qunbound. If you call
4944 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4945 and don't let it get stored in any Lisp-visible variables! */
4947 Lisp_Object
4948 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4949 const char *attribute, const char *class, enum resource_types type)
4951 Lisp_Object tem;
4953 tem = Fassq (param, alist);
4955 if (!NILP (tem))
4957 /* If we find this parm in ALIST, clear it out
4958 so that it won't be "left over" at the end. */
4959 Lisp_Object tail;
4960 XSETCAR (tem, Qnil);
4961 /* In case the parameter appears more than once in the alist,
4962 clear it out. */
4963 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4964 if (CONSP (XCAR (tail))
4965 && EQ (XCAR (XCAR (tail)), param))
4966 XSETCAR (XCAR (tail), Qnil);
4968 else
4969 tem = Fassq (param, Vdefault_frame_alist);
4971 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4972 look in the X resources. */
4973 if (EQ (tem, Qnil))
4975 if (attribute && dpyinfo)
4977 AUTO_STRING (at, attribute);
4978 AUTO_STRING (cl, class);
4979 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4981 if (NILP (tem))
4982 return Qunbound;
4984 switch (type)
4986 case RES_TYPE_NUMBER:
4987 return make_number (atoi (SSDATA (tem)));
4989 case RES_TYPE_BOOLEAN_NUMBER:
4990 if (!strcmp (SSDATA (tem), "on")
4991 || !strcmp (SSDATA (tem), "true"))
4992 return make_number (1);
4993 return make_number (atoi (SSDATA (tem)));
4994 break;
4996 case RES_TYPE_FLOAT:
4997 return make_float (atof (SSDATA (tem)));
4999 case RES_TYPE_BOOLEAN:
5000 tem = Fdowncase (tem);
5001 if (!strcmp (SSDATA (tem), "on")
5002 #ifdef HAVE_NS
5003 || !strcmp (SSDATA (tem), "yes")
5004 #endif
5005 || !strcmp (SSDATA (tem), "true"))
5006 return Qt;
5007 else
5008 return Qnil;
5010 case RES_TYPE_STRING:
5011 return tem;
5013 case RES_TYPE_SYMBOL:
5014 /* As a special case, we map the values `true' and `on'
5015 to Qt, and `false' and `off' to Qnil. */
5017 Lisp_Object lower;
5018 lower = Fdowncase (tem);
5019 if (!strcmp (SSDATA (lower), "on")
5020 #ifdef HAVE_NS
5021 || !strcmp (SSDATA (lower), "yes")
5022 #endif
5023 || !strcmp (SSDATA (lower), "true"))
5024 return Qt;
5025 else if (!strcmp (SSDATA (lower), "off")
5026 #ifdef HAVE_NS
5027 || !strcmp (SSDATA (lower), "no")
5028 #endif
5029 || !strcmp (SSDATA (lower), "false"))
5030 return Qnil;
5031 else
5032 return Fintern (tem, Qnil);
5035 default:
5036 emacs_abort ();
5039 else
5040 return Qunbound;
5042 return Fcdr (tem);
5045 static Lisp_Object
5046 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
5047 const char *attribute, const char *class,
5048 enum resource_types type)
5050 return x_get_arg (FRAME_DISPLAY_INFO (f),
5051 alist, param, attribute, class, type);
5054 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
5056 Lisp_Object
5057 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
5058 Lisp_Object param,
5059 const char *attribute, const char *class,
5060 enum resource_types type)
5062 Lisp_Object value;
5064 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
5065 attribute, class, type);
5066 if (! NILP (value) && ! EQ (value, Qunbound))
5067 store_frame_param (f, param, value);
5069 return value;
5073 /* Record in frame F the specified or default value according to ALIST
5074 of the parameter named PROP (a Lisp symbol).
5075 If no value is specified for PROP, look for an X default for XPROP
5076 on the frame named NAME.
5077 If that is not found either, use the value DEFLT. */
5079 Lisp_Object
5080 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
5081 Lisp_Object deflt, const char *xprop, const char *xclass,
5082 enum resource_types type)
5084 Lisp_Object tem;
5086 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
5087 if (EQ (tem, Qunbound))
5088 tem = deflt;
5089 AUTO_FRAME_ARG (arg, prop, tem);
5090 x_set_frame_parameters (f, arg);
5091 return tem;
5095 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
5098 * XParseGeometry parses strings of the form
5099 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5100 * width, height, xoffset, and yoffset are unsigned integers.
5101 * Example: "=80x24+300-49"
5102 * The equal sign is optional.
5103 * It returns a bitmask that indicates which of the four values
5104 * were actually found in the string. For each value found,
5105 * the corresponding argument is updated; for each value
5106 * not found, the corresponding argument is left unchanged.
5109 static int
5110 XParseGeometry (char *string,
5111 int *x, int *y,
5112 unsigned int *width, unsigned int *height)
5114 int mask = NoValue;
5115 char *strind;
5116 unsigned long tempWidth UNINIT, tempHeight UNINIT;
5117 long int tempX UNINIT, tempY UNINIT;
5118 char *nextCharacter;
5120 if (string == NULL || *string == '\0')
5121 return mask;
5122 if (*string == '=')
5123 string++; /* ignore possible '=' at beg of geometry spec */
5125 strind = string;
5126 if (*strind != '+' && *strind != '-' && *strind != 'x')
5128 tempWidth = strtoul (strind, &nextCharacter, 10);
5129 if (strind == nextCharacter)
5130 return 0;
5131 strind = nextCharacter;
5132 mask |= WidthValue;
5135 if (*strind == 'x' || *strind == 'X')
5137 strind++;
5138 tempHeight = strtoul (strind, &nextCharacter, 10);
5139 if (strind == nextCharacter)
5140 return 0;
5141 strind = nextCharacter;
5142 mask |= HeightValue;
5145 if (*strind == '+' || *strind == '-')
5147 if (*strind == '-')
5148 mask |= XNegative;
5149 tempX = strtol (strind, &nextCharacter, 10);
5150 if (strind == nextCharacter)
5151 return 0;
5152 strind = nextCharacter;
5153 mask |= XValue;
5154 if (*strind == '+' || *strind == '-')
5156 if (*strind == '-')
5157 mask |= YNegative;
5158 tempY = strtol (strind, &nextCharacter, 10);
5159 if (strind == nextCharacter)
5160 return 0;
5161 strind = nextCharacter;
5162 mask |= YValue;
5166 /* If strind isn't at the end of the string then it's an invalid
5167 geometry specification. */
5169 if (*strind != '\0')
5170 return 0;
5172 if (mask & XValue)
5173 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
5174 if (mask & YValue)
5175 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
5176 if (mask & WidthValue)
5177 *width = min (tempWidth, UINT_MAX);
5178 if (mask & HeightValue)
5179 *height = min (tempHeight, UINT_MAX);
5180 return mask;
5183 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
5186 /* NS used to define x-parse-geometry in ns-win.el, but that confused
5187 make-docfile: the documentation string in ns-win.el was used for
5188 x-parse-geometry even in non-NS builds.
5190 With two definitions of x-parse-geometry in this file, various
5191 things still get confused (eg M-x apropos documentation), so that
5192 it is best if the two definitions just share the same doc-string.
5194 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
5195 doc: /* Parse a display geometry string STRING.
5196 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
5197 The properties returned may include `top', `left', `height', and `width'.
5198 For X, the value of `left' or `top' may be an integer,
5199 or a list (+ N) meaning N pixels relative to top/left corner,
5200 or a list (- N) meaning -N pixels relative to bottom/right corner.
5201 On Nextstep, this just calls `ns-parse-geometry'. */)
5202 (Lisp_Object string)
5204 int geometry, x, y;
5205 unsigned int width, height;
5206 Lisp_Object result;
5208 CHECK_STRING (string);
5210 #ifdef HAVE_NS
5211 if (strchr (SSDATA (string), ' ') != NULL)
5212 return call1 (Qns_parse_geometry, string);
5213 #endif
5214 geometry = XParseGeometry (SSDATA (string),
5215 &x, &y, &width, &height);
5216 result = Qnil;
5217 if (geometry & XValue)
5219 Lisp_Object element;
5221 if (x >= 0 && (geometry & XNegative))
5222 element = list3 (Qleft, Qminus, make_number (-x));
5223 else if (x < 0 && ! (geometry & XNegative))
5224 element = list3 (Qleft, Qplus, make_number (x));
5225 else
5226 element = Fcons (Qleft, make_number (x));
5227 result = Fcons (element, result);
5230 if (geometry & YValue)
5232 Lisp_Object element;
5234 if (y >= 0 && (geometry & YNegative))
5235 element = list3 (Qtop, Qminus, make_number (-y));
5236 else if (y < 0 && ! (geometry & YNegative))
5237 element = list3 (Qtop, Qplus, make_number (y));
5238 else
5239 element = Fcons (Qtop, make_number (y));
5240 result = Fcons (element, result);
5243 if (geometry & WidthValue)
5244 result = Fcons (Fcons (Qwidth, make_number (width)), result);
5245 if (geometry & HeightValue)
5246 result = Fcons (Fcons (Qheight, make_number (height)), result);
5248 return result;
5252 /* Calculate the desired size and position of frame F.
5253 Return the flags saying which aspects were specified.
5255 Also set the win_gravity and size_hint_flags of F.
5257 Adjust height for toolbar if TOOLBAR_P is 1.
5259 This function does not make the coordinates positive. */
5261 #define DEFAULT_ROWS 36
5262 #define DEFAULT_COLS 80
5264 long
5265 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x_width, int *x_height)
5267 Lisp_Object height, width, user_size, top, left, user_position;
5268 long window_prompting = 0;
5269 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
5270 int parent_done = -1, outer_done = -1;
5272 /* Default values if we fall through.
5273 Actually, if that happens we should get
5274 window manager prompting. */
5275 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
5276 SET_FRAME_COLS (f, DEFAULT_COLS);
5277 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
5278 SET_FRAME_LINES (f, DEFAULT_ROWS);
5280 /* Window managers expect that if program-specified
5281 positions are not (0,0), they're intentional, not defaults. */
5282 f->top_pos = 0;
5283 f->left_pos = 0;
5285 /* Calculate a tool bar height so that the user gets a text display
5286 area of the size he specified with -g or via .Xdefaults. Later
5287 changes of the tool bar height don't change the frame size. This
5288 is done so that users can create tall Emacs frames without having
5289 to guess how tall the tool bar will get. */
5290 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
5292 if (frame_default_tool_bar_height)
5293 FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
5294 else
5296 int margin, relief;
5298 relief = (tool_bar_button_relief >= 0
5299 ? tool_bar_button_relief
5300 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
5302 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
5303 margin = XFASTINT (Vtool_bar_button_margin);
5304 else if (CONSP (Vtool_bar_button_margin)
5305 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
5306 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
5307 else
5308 margin = 0;
5310 FRAME_TOOL_BAR_HEIGHT (f)
5311 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5315 /* Ensure that earlier new_width and new_height settings won't
5316 override what we specify below. */
5317 f->new_width = f->new_height = 0;
5319 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
5320 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
5321 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
5323 if (!EQ (width, Qunbound))
5325 if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
5327 CHECK_NUMBER (XCDR (width));
5328 if ((XINT (XCDR (width)) < 0 || XINT (XCDR (width)) > INT_MAX))
5329 xsignal1 (Qargs_out_of_range, XCDR (width));
5331 SET_FRAME_WIDTH (f, XINT (XCDR (width)));
5332 f->inhibit_horizontal_resize = true;
5333 *x_width = XINT (XCDR (width));
5335 else if (FLOATP (width))
5337 double d_width = XFLOAT_DATA (width);
5339 if (d_width < 0.0 || d_width > 1.0)
5340 xsignal1 (Qargs_out_of_range, width);
5341 else
5343 int new_width = frame_float (f, width, FRAME_FLOAT_WIDTH,
5344 &parent_done, &outer_done, -1);
5346 if (new_width > -1)
5347 SET_FRAME_WIDTH (f, new_width);
5350 else
5352 CHECK_NUMBER (width);
5353 if ((XINT (width) < 0 || XINT (width) > INT_MAX))
5354 xsignal1 (Qargs_out_of_range, width);
5356 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
5360 if (!EQ (height, Qunbound))
5362 if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
5364 CHECK_NUMBER (XCDR (height));
5365 if ((XINT (XCDR (height)) < 0 || XINT (XCDR (height)) > INT_MAX))
5366 xsignal1 (Qargs_out_of_range, XCDR (height));
5368 SET_FRAME_HEIGHT (f, XINT (XCDR (height)));
5369 f->inhibit_vertical_resize = true;
5370 *x_height = XINT (XCDR (height));
5372 else if (FLOATP (height))
5374 double d_height = XFLOAT_DATA (height);
5376 if (d_height < 0.0 || d_height > 1.0)
5377 xsignal1 (Qargs_out_of_range, height);
5378 else
5380 int new_height = frame_float (f, height, FRAME_FLOAT_HEIGHT,
5381 &parent_done, &outer_done, -1);
5383 if (new_height > -1)
5384 SET_FRAME_HEIGHT (f, new_height);
5387 else
5389 CHECK_NUMBER (height);
5390 if ((XINT (height) < 0) || (XINT (height) > INT_MAX))
5391 xsignal1 (Qargs_out_of_range, height);
5393 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
5397 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
5398 if (!NILP (user_size) && !EQ (user_size, Qunbound))
5399 window_prompting |= USSize;
5400 else
5401 window_prompting |= PSize;
5404 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
5405 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
5406 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
5407 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
5409 if (EQ (top, Qminus))
5411 f->top_pos = 0;
5412 window_prompting |= YNegative;
5414 else if (CONSP (top) && EQ (XCAR (top), Qminus)
5415 && CONSP (XCDR (top))
5416 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
5418 f->top_pos = - XINT (XCAR (XCDR (top)));
5419 window_prompting |= YNegative;
5421 else if (CONSP (top) && EQ (XCAR (top), Qplus)
5422 && CONSP (XCDR (top))
5423 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
5425 f->top_pos = XINT (XCAR (XCDR (top)));
5427 else if (FLOATP (top))
5428 f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
5429 &outer_done, 0);
5430 else if (EQ (top, Qunbound))
5431 f->top_pos = 0;
5432 else
5434 CHECK_TYPE_RANGED_INTEGER (int, top);
5435 f->top_pos = XINT (top);
5436 if (f->top_pos < 0)
5437 window_prompting |= YNegative;
5440 if (EQ (left, Qminus))
5442 f->left_pos = 0;
5443 window_prompting |= XNegative;
5445 else if (CONSP (left) && EQ (XCAR (left), Qminus)
5446 && CONSP (XCDR (left))
5447 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
5449 f->left_pos = - XINT (XCAR (XCDR (left)));
5450 window_prompting |= XNegative;
5452 else if (CONSP (left) && EQ (XCAR (left), Qplus)
5453 && CONSP (XCDR (left))
5454 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
5456 f->left_pos = XINT (XCAR (XCDR (left)));
5458 else if (FLOATP (left))
5459 f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
5460 &outer_done, 0);
5461 else if (EQ (left, Qunbound))
5462 f->left_pos = 0;
5463 else
5465 CHECK_TYPE_RANGED_INTEGER (int, left);
5466 f->left_pos = XINT (left);
5467 if (f->left_pos < 0)
5468 window_prompting |= XNegative;
5471 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
5472 window_prompting |= USPosition;
5473 else
5474 window_prompting |= PPosition;
5477 if (window_prompting & XNegative)
5479 if (window_prompting & YNegative)
5480 f->win_gravity = SouthEastGravity;
5481 else
5482 f->win_gravity = NorthEastGravity;
5484 else
5486 if (window_prompting & YNegative)
5487 f->win_gravity = SouthWestGravity;
5488 else
5489 f->win_gravity = NorthWestGravity;
5492 f->size_hint_flags = window_prompting;
5494 return window_prompting;
5499 #endif /* HAVE_WINDOW_SYSTEM */
5501 void
5502 frame_make_pointer_invisible (struct frame *f)
5504 if (! NILP (Vmake_pointer_invisible))
5506 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
5507 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5509 f->mouse_moved = 0;
5510 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
5511 f->pointer_invisible = 1;
5516 void
5517 frame_make_pointer_visible (struct frame *f)
5519 /* We don't check Vmake_pointer_invisible here in case the
5520 pointer was invisible when Vmake_pointer_invisible was set to nil. */
5521 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
5522 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5524 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
5525 f->pointer_invisible = 0;
5529 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
5530 Sframe_pointer_visible_p, 0, 1, 0,
5531 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
5532 Otherwise it returns nil. FRAME omitted or nil means the
5533 selected frame. This is useful when `make-pointer-invisible' is set. */)
5534 (Lisp_Object frame)
5536 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
5541 /***********************************************************************
5542 Multimonitor data
5543 ***********************************************************************/
5545 #ifdef HAVE_WINDOW_SYSTEM
5547 # if (defined HAVE_NS \
5548 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
5549 void
5550 free_monitors (struct MonitorInfo *monitors, int n_monitors)
5552 int i;
5553 for (i = 0; i < n_monitors; ++i)
5554 xfree (monitors[i].name);
5555 xfree (monitors);
5557 # endif
5559 Lisp_Object
5560 make_monitor_attribute_list (struct MonitorInfo *monitors,
5561 int n_monitors,
5562 int primary_monitor,
5563 Lisp_Object monitor_frames,
5564 const char *source)
5566 Lisp_Object attributes_list = Qnil;
5567 Lisp_Object primary_monitor_attributes = Qnil;
5568 int i;
5570 for (i = 0; i < n_monitors; ++i)
5572 Lisp_Object geometry, workarea, attributes = Qnil;
5573 struct MonitorInfo *mi = &monitors[i];
5575 if (mi->geom.width == 0) continue;
5577 workarea = list4i (mi->work.x, mi->work.y,
5578 mi->work.width, mi->work.height);
5579 geometry = list4i (mi->geom.x, mi->geom.y,
5580 mi->geom.width, mi->geom.height);
5581 attributes = Fcons (Fcons (Qsource, build_string (source)),
5582 attributes);
5583 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
5584 attributes);
5585 attributes = Fcons (Fcons (Qmm_size,
5586 list2i (mi->mm_width, mi->mm_height)),
5587 attributes);
5588 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5589 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5590 if (mi->name)
5591 attributes = Fcons (Fcons (Qname, make_string (mi->name,
5592 strlen (mi->name))),
5593 attributes);
5595 if (i == primary_monitor)
5596 primary_monitor_attributes = attributes;
5597 else
5598 attributes_list = Fcons (attributes, attributes_list);
5601 if (!NILP (primary_monitor_attributes))
5602 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
5603 return attributes_list;
5606 #endif /* HAVE_WINDOW_SYSTEM */
5609 /***********************************************************************
5610 Initialization
5611 ***********************************************************************/
5613 void
5614 syms_of_frame (void)
5616 DEFSYM (Qframep, "framep");
5617 DEFSYM (Qframe_live_p, "frame-live-p");
5618 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
5619 DEFSYM (Qdisplay_monitor_attributes_list, "display-monitor-attributes-list");
5620 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
5621 DEFSYM (Qexplicit_name, "explicit-name");
5622 DEFSYM (Qheight, "height");
5623 DEFSYM (Qicon, "icon");
5624 DEFSYM (Qminibuffer, "minibuffer");
5625 DEFSYM (Qundecorated, "undecorated");
5626 DEFSYM (Qno_special_glyphs, "no-special-glyphs");
5627 DEFSYM (Qparent_frame, "parent-frame");
5628 DEFSYM (Qskip_taskbar, "skip-taskbar");
5629 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
5630 DEFSYM (Qno_accept_focus, "no-accept-focus");
5631 DEFSYM (Qz_group, "z-group");
5632 DEFSYM (Qoverride_redirect, "override-redirect");
5633 DEFSYM (Qdelete_before, "delete-before");
5634 DEFSYM (Qmodeline, "modeline");
5635 DEFSYM (Qonly, "only");
5636 DEFSYM (Qnone, "none");
5637 DEFSYM (Qwidth, "width");
5638 DEFSYM (Qtext_pixels, "text-pixels");
5639 DEFSYM (Qgeometry, "geometry");
5640 DEFSYM (Qicon_left, "icon-left");
5641 DEFSYM (Qicon_top, "icon-top");
5642 DEFSYM (Qtooltip, "tooltip");
5643 DEFSYM (Quser_position, "user-position");
5644 DEFSYM (Quser_size, "user-size");
5645 DEFSYM (Qwindow_id, "window-id");
5646 #ifdef HAVE_X_WINDOWS
5647 DEFSYM (Qouter_window_id, "outer-window-id");
5648 #endif
5649 DEFSYM (Qparent_id, "parent-id");
5650 DEFSYM (Qx, "x");
5651 DEFSYM (Qw32, "w32");
5652 DEFSYM (Qpc, "pc");
5653 DEFSYM (Qns, "ns");
5654 DEFSYM (Qvisible, "visible");
5655 DEFSYM (Qbuffer_predicate, "buffer-predicate");
5656 DEFSYM (Qbuffer_list, "buffer-list");
5657 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
5658 DEFSYM (Qdisplay_type, "display-type");
5659 DEFSYM (Qbackground_mode, "background-mode");
5660 DEFSYM (Qnoelisp, "noelisp");
5661 DEFSYM (Qtty_color_mode, "tty-color-mode");
5662 DEFSYM (Qtty, "tty");
5663 DEFSYM (Qtty_type, "tty-type");
5665 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
5667 DEFSYM (Qfullwidth, "fullwidth");
5668 DEFSYM (Qfullheight, "fullheight");
5669 DEFSYM (Qfullboth, "fullboth");
5670 DEFSYM (Qmaximized, "maximized");
5671 DEFSYM (Qx_resource_name, "x-resource-name");
5672 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
5674 DEFSYM (Qworkarea, "workarea");
5675 DEFSYM (Qmm_size, "mm-size");
5676 DEFSYM (Qframes, "frames");
5677 DEFSYM (Qsource, "source");
5679 DEFSYM (Qframe_edges, "frame-edges");
5680 DEFSYM (Qouter_edges, "outer-edges");
5681 DEFSYM (Qouter_position, "outer-position");
5682 DEFSYM (Qouter_size, "outer-size");
5683 DEFSYM (Qnative_edges, "native-edges");
5684 DEFSYM (Qinner_edges, "inner-edges");
5685 DEFSYM (Qexternal_border_size, "external-border-size");
5686 DEFSYM (Qtitle_bar_size, "title-bar-size");
5687 DEFSYM (Qmenu_bar_external, "menu-bar-external");
5688 DEFSYM (Qmenu_bar_size, "menu-bar-size");
5689 DEFSYM (Qtool_bar_external, "tool-bar-external");
5690 DEFSYM (Qtool_bar_size, "tool-bar-size");
5691 /* The following are used for frame_size_history. */
5692 DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
5693 DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
5694 DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
5695 DEFSYM (Qx_set_frame_parameters, "x-set-frame-parameters");
5696 DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
5697 DEFSYM (Qset_frame_size, "set-frame-size");
5698 DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
5699 DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
5700 DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
5701 DEFSYM (Qxg_frame_resized, "xg-frame-resized");
5702 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
5703 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
5704 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
5705 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
5706 DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
5707 DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
5708 DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
5709 DEFSYM (Qx_net_wm_state, "x-net-wm-state");
5710 DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
5711 DEFSYM (Qtb_size_cb, "tb-size-cb");
5712 DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
5713 DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
5714 DEFSYM (Qx_set_menu_bar_lines, "x-set-menu-bar-lines");
5715 DEFSYM (Qchange_frame_size, "change-frame-size");
5716 DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
5717 DEFSYM (Qset_window_configuration, "set-window-configuration");
5718 DEFSYM (Qx_create_frame_1, "x-create-frame-1");
5719 DEFSYM (Qx_create_frame_2, "x-create-frame-2");
5720 DEFSYM (Qterminal_frame, "terminal-frame");
5722 #ifdef HAVE_NS
5723 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
5724 #endif
5725 #ifdef NS_IMPL_COCOA
5726 DEFSYM (Qns_appearance, "ns-appearance");
5727 DEFSYM (Qns_transparent_titlebar, "ns-transparent-titlebar");
5728 #endif
5730 DEFSYM (Qalpha, "alpha");
5731 DEFSYM (Qauto_lower, "auto-lower");
5732 DEFSYM (Qauto_raise, "auto-raise");
5733 DEFSYM (Qborder_color, "border-color");
5734 DEFSYM (Qborder_width, "border-width");
5735 DEFSYM (Qouter_border_width, "outer-border-width");
5736 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
5737 DEFSYM (Qcursor_color, "cursor-color");
5738 DEFSYM (Qcursor_type, "cursor-type");
5739 DEFSYM (Qfont_backend, "font-backend");
5740 DEFSYM (Qfullscreen, "fullscreen");
5741 DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
5742 DEFSYM (Qicon_name, "icon-name");
5743 DEFSYM (Qicon_type, "icon-type");
5744 DEFSYM (Qinternal_border_width, "internal-border-width");
5745 DEFSYM (Qleft_fringe, "left-fringe");
5746 DEFSYM (Qline_spacing, "line-spacing");
5747 DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
5748 DEFSYM (Qupdate_frame_menubar, "update-frame-menubar");
5749 DEFSYM (Qfree_frame_menubar_1, "free-frame-menubar-1");
5750 DEFSYM (Qfree_frame_menubar_2, "free-frame-menubar-2");
5751 DEFSYM (Qmouse_color, "mouse-color");
5752 DEFSYM (Qname, "name");
5753 DEFSYM (Qright_divider_width, "right-divider-width");
5754 DEFSYM (Qright_fringe, "right-fringe");
5755 DEFSYM (Qscreen_gamma, "screen-gamma");
5756 DEFSYM (Qscroll_bar_background, "scroll-bar-background");
5757 DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
5758 DEFSYM (Qscroll_bar_height, "scroll-bar-height");
5759 DEFSYM (Qscroll_bar_width, "scroll-bar-width");
5760 DEFSYM (Qsticky, "sticky");
5761 DEFSYM (Qtitle, "title");
5762 DEFSYM (Qtool_bar_lines, "tool-bar-lines");
5763 DEFSYM (Qtool_bar_position, "tool-bar-position");
5764 DEFSYM (Qunsplittable, "unsplittable");
5765 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
5766 DEFSYM (Qvisibility, "visibility");
5767 DEFSYM (Qwait_for_wm, "wait-for-wm");
5768 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5769 DEFSYM (Qno_other_frame, "no-other-frame");
5770 DEFSYM (Qbelow, "below");
5771 DEFSYM (Qabove_suspended, "above-suspended");
5772 DEFSYM (Qmin_width, "min-width");
5773 DEFSYM (Qmin_height, "min-height");
5774 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
5775 DEFSYM (Qkeep_ratio, "keep-ratio");
5776 DEFSYM (Qwidth_only, "width-only");
5777 DEFSYM (Qheight_only, "height-only");
5778 DEFSYM (Qleft_only, "left-only");
5779 DEFSYM (Qtop_only, "top-only");
5780 DEFSYM (Qiconify_top_level, "iconify-top-level");
5781 DEFSYM (Qmake_invisible, "make-invisible");
5784 int i;
5786 for (i = 0; i < ARRAYELTS (frame_parms); i++)
5788 Lisp_Object v = (frame_parms[i].sym < 0
5789 ? intern_c_string (frame_parms[i].name)
5790 : builtin_lisp_symbol (frame_parms[i].sym));
5791 Fput (v, Qx_frame_parameter, make_number (i));
5795 #ifdef HAVE_WINDOW_SYSTEM
5796 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
5797 doc: /* The name Emacs uses to look up X resources.
5798 `x-get-resource' uses this as the first component of the instance name
5799 when requesting resource values.
5800 Emacs initially sets `x-resource-name' to the name under which Emacs
5801 was invoked, or to the value specified with the `-name' or `-rn'
5802 switches, if present.
5804 It may be useful to bind this variable locally around a call
5805 to `x-get-resource'. See also the variable `x-resource-class'. */);
5806 Vx_resource_name = Qnil;
5808 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
5809 doc: /* The class Emacs uses to look up X resources.
5810 `x-get-resource' uses this as the first component of the instance class
5811 when requesting resource values.
5813 Emacs initially sets `x-resource-class' to "Emacs".
5815 Setting this variable permanently is not a reasonable thing to do,
5816 but binding this variable locally around a call to `x-get-resource'
5817 is a reasonable practice. See also the variable `x-resource-name'. */);
5818 Vx_resource_class = build_string (EMACS_CLASS);
5820 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
5821 doc: /* The lower limit of the frame opacity (alpha transparency).
5822 The value should range from 0 (invisible) to 100 (completely opaque).
5823 You can also use a floating number between 0.0 and 1.0. */);
5824 Vframe_alpha_lower_limit = make_number (20);
5825 #endif
5827 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
5828 doc: /* Alist of default values for frame creation.
5829 These may be set in your init file, like this:
5830 (setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
5831 These override values given in window system configuration data,
5832 including X Windows' defaults database.
5833 For values specific to the first Emacs frame, see `initial-frame-alist'.
5834 For window-system specific values, see `window-system-default-frame-alist'.
5835 For values specific to the separate minibuffer frame, see
5836 `minibuffer-frame-alist'.
5837 The `menu-bar-lines' element of the list controls whether new frames
5838 have menu bars; `menu-bar-mode' works by altering this element.
5839 Setting this variable does not affect existing frames, only new ones. */);
5840 Vdefault_frame_alist = Qnil;
5842 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
5843 doc: /* Default position of vertical scroll bars on this window-system. */);
5844 #ifdef HAVE_WINDOW_SYSTEM
5845 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
5846 /* MS-Windows, macOS, and GTK have scroll bars on the right by
5847 default. */
5848 Vdefault_frame_scroll_bars = Qright;
5849 #else
5850 Vdefault_frame_scroll_bars = Qleft;
5851 #endif
5852 #else
5853 Vdefault_frame_scroll_bars = Qnil;
5854 #endif
5856 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
5857 scroll_bar_adjust_thumb_portion_p,
5858 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
5859 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
5860 even if the end of the buffer is shown (i.e. overscrolling).
5861 Set to nil if you want the thumb to be at the bottom when the end of the buffer
5862 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
5863 is visible. In this case you can not overscroll. */);
5864 scroll_bar_adjust_thumb_portion_p = 1;
5866 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
5867 doc: /* The initial frame-object, which represents Emacs's stdout. */);
5869 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
5870 doc: /* If non-nil, function to transform normal value of `mouse-position'.
5871 `mouse-position' and `mouse-pixel-position' call this function, passing their
5872 usual return value as argument, and return whatever this function returns.
5873 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
5874 which need to do mouse handling at the Lisp level. */);
5875 Vmouse_position_function = Qnil;
5877 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
5878 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
5879 If the value is an integer, highlighting is only shown after moving the
5880 mouse, while keyboard input turns off the highlight even when the mouse
5881 is over the clickable text. However, the mouse shape still indicates
5882 when the mouse is over clickable text. */);
5883 Vmouse_highlight = Qt;
5885 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
5886 doc: /* If non-nil, make pointer invisible while typing.
5887 The pointer becomes visible again when the mouse is moved. */);
5888 Vmake_pointer_invisible = Qt;
5890 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
5891 doc: /* Normal hook run when a frame gains input focus.
5892 The frame gaining focus is selected at the time this hook is run. */);
5893 Vfocus_in_hook = Qnil;
5895 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
5896 doc: /* Normal hook run when all frames lost input focus. */);
5897 Vfocus_out_hook = Qnil;
5899 DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
5900 doc: /* Functions run after a frame was moved.
5901 The functions are run with one arg, the frame that moved. */);
5902 Vmove_frame_functions = Qnil;
5904 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
5905 doc: /* Functions run before deleting a frame.
5906 The functions are run with one arg, the frame to be deleted.
5907 See `delete-frame'.
5909 Note that functions in this list may be called just before the frame is
5910 actually deleted, or some time later (or even both when an earlier function
5911 in `delete-frame-functions' (indirectly) calls `delete-frame'
5912 recursively). */);
5913 Vdelete_frame_functions = Qnil;
5914 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
5916 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
5917 doc: /* Non-nil if Menu-Bar mode is enabled.
5918 See the command `menu-bar-mode' for a description of this minor mode.
5919 Setting this variable directly does not take effect;
5920 either customize it (see the info node `Easy Customization')
5921 or call the function `menu-bar-mode'. */);
5922 Vmenu_bar_mode = Qt;
5924 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
5925 doc: /* Non-nil if Tool-Bar mode is enabled.
5926 See the command `tool-bar-mode' for a description of this minor mode.
5927 Setting this variable directly does not take effect;
5928 either customize it (see the info node `Easy Customization')
5929 or call the function `tool-bar-mode'. */);
5930 #ifdef HAVE_WINDOW_SYSTEM
5931 Vtool_bar_mode = Qt;
5932 #else
5933 Vtool_bar_mode = Qnil;
5934 #endif
5936 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
5937 doc: /* Minibuffer-less frames by default use this frame's minibuffer.
5938 Emacs consults this variable only when creating a minibuffer-less frame
5939 and no explicit minibuffer window has been specified for that frame via
5940 the `minibuffer' frame parameter. Once such a frame has been created,
5941 setting this variable does not change that frame's previous association.
5943 This variable is local to the current terminal and cannot be buffer-local. */);
5945 DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
5946 doc: /* Non-nil if window system changes focus when you move the mouse.
5947 You should set this variable to tell Emacs how your window manager
5948 handles focus, since there is no way in general for Emacs to find out
5949 automatically.
5951 There are three meaningful values:
5953 - The default nil should be used when your window manager follows a
5954 "click-to-focus" policy where you have to click the mouse inside of a
5955 frame in order for that frame to get focus.
5957 - The value t should be used when your window manager has the focus
5958 automatically follow the position of the mouse pointer but a window
5959 that gains focus is not raised automatically.
5961 - The value `auto-raise' should be used when your window manager has the
5962 focus automatically follow the position of the mouse pointer and a
5963 window that gains focus is raised automatically.
5965 If this option is non-nil, Emacs moves the mouse pointer to the frame
5966 selected by `select-frame-set-input-focus'. This function is used by a
5967 number of commands like, for example, `other-frame' and `pop-to-buffer'.
5968 If this option is nil and your focus follows mouse window manager does
5969 not autonomously move the mouse pointer to the newly selected frame, the
5970 previously selected window manager window might get reselected instead
5971 immediately.
5973 The distinction between the values t and `auto-raise' is not needed for
5974 "normal" frames because the window manager takes care of raising them.
5975 Setting this to `auto-raise' will, however, override the standard
5976 behavior of a window manager that does not automatically raise the frame
5977 that gets focus. Setting this to `auto-raise' is also necessary to
5978 automatically raise child frames which are usually left alone by the
5979 window manager.
5981 Note that this option does not distinguish "sloppy" focus (where the
5982 frame that previously had focus retains focus as long as the mouse
5983 pointer does not move into another window manager window) from "strict"
5984 focus (where a frame immediately loses focus when it's left by the mouse
5985 pointer).
5987 In order to extend a "focus follows mouse" policy to individual Emacs
5988 windows, customize the variable `mouse-autoselect-window'. */);
5989 focus_follows_mouse = Qnil;
5991 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5992 doc: /* Non-nil means resize frames pixelwise.
5993 If this option is nil, resizing a frame rounds its sizes to the frame's
5994 current values of `frame-char-height' and `frame-char-width'. If this
5995 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5996 by one pixel.
5998 With some window managers you may have to set this to non-nil in order
5999 to set the size of a frame in pixels, to maximize frames or to make them
6000 fullscreen. To resize your initial frame pixelwise, set this option to
6001 a non-nil value in your init file. */);
6002 frame_resize_pixelwise = 0;
6004 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
6005 doc: /* Whether frames should be resized implicitly.
6006 If this option is nil, setting font, menu bar, tool bar, internal
6007 borders, fringes or scroll bars of a specific frame may resize the frame
6008 in order to preserve the number of columns or lines it displays. If
6009 this option is t, no such resizing is done. Note that the size of
6010 fullscreen and maximized frames, the height of fullheight frames and the
6011 width of fullwidth frames never change implicitly.
6013 The value of this option can be also be a list of frame parameters. In
6014 this case, resizing is inhibited when changing a parameter that appears
6015 in that list. The parameters currently handled by this option include
6016 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
6017 `tool-bar-lines'.
6019 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
6020 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
6021 `right-fringe' is handled as if the frame contained just one live
6022 window. This means, for example, that removing vertical scroll bars on
6023 a frame containing several side by side windows will shrink the frame
6024 width by the width of one scroll bar provided this option is nil and
6025 keep it unchanged if this option is either t or a list containing
6026 `vertical-scroll-bars'.
6028 The default value is \\='(tool-bar-lines) on Lucid, Motif and Windows
6029 \(which means that adding/removing a tool bar does not change the frame
6030 height), nil on all other window systems including GTK+ (which means
6031 that changing any of the parameters listed above may change the size of
6032 the frame), and t otherwise (which means the frame size never changes
6033 implicitly when there's no window system support).
6035 Note that when a frame is not large enough to accommodate a change of
6036 any of the parameters listed above, Emacs may try to enlarge the frame
6037 even if this option is non-nil. */);
6038 #if defined (HAVE_WINDOW_SYSTEM)
6039 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
6040 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
6041 #else
6042 frame_inhibit_implied_resize = Qnil;
6043 #endif
6044 #else
6045 frame_inhibit_implied_resize = Qt;
6046 #endif
6048 DEFVAR_LISP ("frame-size-history", frame_size_history,
6049 doc: /* History of frame size adjustments.
6050 If non-nil, list recording frame size adjustment. Adjustments are
6051 recorded only if the first element of this list is a positive number.
6052 Adding an adjustment decrements that number by one.
6054 The remaining elements are the adjustments. Each adjustment is a list
6055 of four elements `frame', `function', `sizes' and `more'. `frame' is
6056 the affected frame and `function' the invoking function. `sizes' is
6057 usually a list of four elements `old-width', `old-height', `new-width'
6058 and `new-height' representing the old and new sizes recorded/requested
6059 by `function'. `more' is a list with additional information.
6061 The function `frame--size-history' displays the value of this variable
6062 in a more readable form. */);
6063 frame_size_history = Qnil;
6065 DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame,
6066 doc: /* Non-nil means reuse hidden tooltip frames.
6067 When this is nil, delete a tooltip frame when hiding the associated
6068 tooltip. When this is non-nil, make the tooltip frame invisible only,
6069 so it can be reused when the next tooltip is shown.
6071 Setting this to non-nil may drastically reduce the consing overhead
6072 incurred by creating new tooltip frames. However, a value of non-nil
6073 means also that intermittent changes of faces or `default-frame-alist'
6074 are not applied when showing a tooltip in a reused frame.
6076 This variable is effective only with the X toolkit (and there only when
6077 Gtk+ tooltips are not used) and on Windows. */);
6078 tooltip_reuse_hidden_frame = false;
6080 DEFVAR_LISP ("iconify-child-frame", iconify_child_frame,
6081 doc: /* How to handle iconification of child frames.
6082 This variable tells Emacs how to proceed when it is asked to iconify a
6083 child frame. If it is nil, `iconify-frame' will do nothing when invoked
6084 on a child frame. If it is `iconify-top-level', Emacs will try to
6085 iconify the top level frame associated with this child frame instead.
6086 If it is `make-invisible', Emacs will try to make this child frame
6087 invisible instead.
6089 Any other value means to try iconifying the child frame. Since such an
6090 attempt is not honored by all window managers and may even lead to
6091 making the child frame unresponsive to user actions, the default is to
6092 iconify the top level frame instead. */);
6093 iconify_child_frame = Qiconify_top_level;
6095 staticpro (&Vframe_list);
6097 defsubr (&Sframep);
6098 defsubr (&Sframe_live_p);
6099 defsubr (&Swindow_system);
6100 defsubr (&Sframe_windows_min_size);
6101 defsubr (&Smake_terminal_frame);
6102 defsubr (&Shandle_switch_frame);
6103 defsubr (&Sselect_frame);
6104 defsubr (&Sselected_frame);
6105 defsubr (&Sframe_list);
6106 defsubr (&Sframe_parent);
6107 defsubr (&Sframe_ancestor_p);
6108 defsubr (&Snext_frame);
6109 defsubr (&Sprevious_frame);
6110 defsubr (&Slast_nonminibuf_frame);
6111 defsubr (&Sdelete_frame);
6112 defsubr (&Smouse_position);
6113 defsubr (&Smouse_pixel_position);
6114 defsubr (&Sset_mouse_position);
6115 defsubr (&Sset_mouse_pixel_position);
6116 #if 0
6117 defsubr (&Sframe_configuration);
6118 defsubr (&Srestore_frame_configuration);
6119 #endif
6120 defsubr (&Smake_frame_visible);
6121 defsubr (&Smake_frame_invisible);
6122 defsubr (&Siconify_frame);
6123 defsubr (&Sframe_visible_p);
6124 defsubr (&Svisible_frame_list);
6125 defsubr (&Sraise_frame);
6126 defsubr (&Slower_frame);
6127 defsubr (&Sx_focus_frame);
6128 defsubr (&Sframe_after_make_frame);
6129 defsubr (&Sredirect_frame_focus);
6130 defsubr (&Sframe_focus);
6131 defsubr (&Sframe_parameters);
6132 defsubr (&Sframe_parameter);
6133 defsubr (&Smodify_frame_parameters);
6134 defsubr (&Sframe_char_height);
6135 defsubr (&Sframe_char_width);
6136 defsubr (&Sframe_native_height);
6137 defsubr (&Sframe_native_width);
6138 defsubr (&Sframe_text_cols);
6139 defsubr (&Sframe_text_lines);
6140 defsubr (&Sframe_total_cols);
6141 defsubr (&Sframe_total_lines);
6142 defsubr (&Sframe_text_width);
6143 defsubr (&Sframe_text_height);
6144 defsubr (&Sscroll_bar_width);
6145 defsubr (&Sscroll_bar_height);
6146 defsubr (&Sfringe_width);
6147 defsubr (&Sframe_internal_border_width);
6148 defsubr (&Sright_divider_width);
6149 defsubr (&Sbottom_divider_width);
6150 defsubr (&Stool_bar_pixel_width);
6151 defsubr (&Sset_frame_height);
6152 defsubr (&Sset_frame_width);
6153 defsubr (&Sset_frame_size);
6154 defsubr (&Sframe_position);
6155 defsubr (&Sset_frame_position);
6156 defsubr (&Sframe_pointer_visible_p);
6158 #ifdef HAVE_WINDOW_SYSTEM
6159 defsubr (&Sx_get_resource);
6160 defsubr (&Sx_parse_geometry);
6161 #endif