Fix multiple spaces in Emacs manual
[emacs.git] / src / frame.c
blobd5b080d688aaae07bd9e35b1ee463cfd65c3d17f
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 "frame.h"
39 #include "blockinput.h"
40 #include "termchar.h"
41 #include "termhooks.h"
42 #include "dispextern.h"
43 #include "window.h"
44 #ifdef HAVE_WINDOW_SYSTEM
45 #include "fontset.h"
46 #endif
47 #include "cm.h"
48 #ifdef MSDOS
49 #include "msdos.h"
50 #include "dosfns.h"
51 #endif
52 #ifdef USE_X_TOOLKIT
53 #include "widget.h"
54 #endif
56 /* The currently selected frame. */
58 Lisp_Object selected_frame;
60 /* A frame which is not just a mini-buffer, or NULL if there are no such
61 frames. This is usually the most recent such frame that was selected. */
63 static struct frame *last_nonminibuf_frame;
65 /* False means there are no visible garbaged frames. */
66 bool frame_garbaged;
68 /* The default tool bar height for future frames. */
69 #if defined USE_GTK || defined HAVE_NS
70 enum { frame_default_tool_bar_height = 0 };
71 #else
72 int frame_default_tool_bar_height;
73 #endif
75 #ifdef HAVE_WINDOW_SYSTEM
76 static void x_report_frame_params (struct frame *, Lisp_Object *);
77 #endif
79 /* These setters are used only in this file, so they can be private. */
80 static void
81 fset_buffer_predicate (struct frame *f, Lisp_Object val)
83 f->buffer_predicate = val;
85 static void
86 fset_minibuffer_window (struct frame *f, Lisp_Object val)
88 f->minibuffer_window = val;
91 struct frame *
92 decode_live_frame (register Lisp_Object frame)
94 if (NILP (frame))
95 frame = selected_frame;
96 CHECK_LIVE_FRAME (frame);
97 return XFRAME (frame);
100 struct frame *
101 decode_any_frame (register Lisp_Object frame)
103 if (NILP (frame))
104 frame = selected_frame;
105 CHECK_FRAME (frame);
106 return XFRAME (frame);
109 #ifdef HAVE_WINDOW_SYSTEM
110 bool
111 display_available (void)
113 return x_display_list != NULL;
115 #endif
117 struct frame *
118 decode_window_system_frame (Lisp_Object frame)
120 struct frame *f = decode_live_frame (frame);
121 check_window_system (f);
122 #ifdef HAVE_WINDOW_SYSTEM
123 return f;
124 #endif
127 void
128 check_window_system (struct frame *f)
130 #ifdef HAVE_WINDOW_SYSTEM
131 if (window_system_available (f))
132 return;
133 #endif
134 error (f ? "Window system frame should be used"
135 : "Window system is not in use or not initialized");
138 /* Return the value of frame parameter PROP in frame FRAME. */
140 Lisp_Object
141 get_frame_param (register struct frame *frame, Lisp_Object prop)
143 register Lisp_Object tem;
145 tem = Fassq (prop, frame->param_alist);
146 if (EQ (tem, Qnil))
147 return tem;
148 return Fcdr (tem);
152 void
153 frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
154 int width, int height, Lisp_Object rest)
156 Lisp_Object frame;
158 XSETFRAME (frame, f);
159 if (CONSP (frame_size_history)
160 && INTEGERP (XCAR (frame_size_history))
161 && 0 < XINT (XCAR (frame_size_history)))
162 frame_size_history =
163 Fcons (make_number (XINT (XCAR (frame_size_history)) - 1),
164 Fcons (list4
165 (frame, fun_symbol,
166 ((width > 0)
167 ? list4 (make_number (FRAME_TEXT_WIDTH (f)),
168 make_number (FRAME_TEXT_HEIGHT (f)),
169 make_number (width),
170 make_number (height))
171 : Qnil),
172 rest),
173 XCDR (frame_size_history)));
177 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
178 state of frame F would be affected by a vertical (horizontal if
179 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
180 parameter that is changed. */
181 bool
182 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
184 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
185 bool inhibit
186 = (f->after_make_frame
187 ? (EQ (frame_inhibit_implied_resize, Qt)
188 || (CONSP (frame_inhibit_implied_resize)
189 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
190 || (horizontal
191 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullheight))
192 || (!horizontal
193 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullwidth))
194 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
195 : ((horizontal && f->inhibit_horizontal_resize)
196 || (!horizontal && f->inhibit_vertical_resize)));
197 if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
198 frame_size_history_add
199 (f, Qframe_inhibit_resize, 0, 0,
200 list5 (horizontal ? Qt : Qnil, parameter,
201 f->after_make_frame ? Qt : Qnil,
202 frame_inhibit_implied_resize,
203 fullscreen));
205 return inhibit;
208 static void
209 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
211 int nlines;
212 int olines = FRAME_MENU_BAR_LINES (f);
214 /* Right now, menu bars don't work properly in minibuf-only frames;
215 most of the commands try to apply themselves to the minibuffer
216 frame itself, and get an error because you can't switch buffers
217 in or split the minibuffer window. */
218 if (FRAME_MINIBUF_ONLY_P (f))
219 return;
221 if (TYPE_RANGED_INTEGERP (int, value))
222 nlines = XINT (value);
223 else
224 nlines = 0;
226 if (nlines != olines)
228 windows_or_buffers_changed = 14;
229 FRAME_MENU_BAR_LINES (f) = nlines;
230 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
231 change_frame_size (f, FRAME_COLS (f),
232 FRAME_LINES (f) + olines - nlines,
233 0, 1, 0, 0);
237 Lisp_Object Vframe_list;
240 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
241 doc: /* Return non-nil if OBJECT is a frame.
242 Value is:
243 t for a termcap frame (a character-only terminal),
244 `x' for an Emacs frame that is really an X window,
245 `w32' for an Emacs frame that is a window on MS-Windows display,
246 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
247 `pc' for a direct-write MS-DOS frame.
248 See also `frame-live-p'. */)
249 (Lisp_Object object)
251 if (!FRAMEP (object))
252 return Qnil;
253 switch (XFRAME (object)->output_method)
255 case output_initial: /* The initial frame is like a termcap frame. */
256 case output_termcap:
257 return Qt;
258 case output_x_window:
259 return Qx;
260 case output_w32:
261 return Qw32;
262 case output_msdos_raw:
263 return Qpc;
264 case output_ns:
265 return Qns;
266 default:
267 emacs_abort ();
271 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
272 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
273 Value is nil if OBJECT is not a live frame. If object is a live
274 frame, the return value indicates what sort of terminal device it is
275 displayed on. See the documentation of `framep' for possible
276 return values. */)
277 (Lisp_Object object)
279 return ((FRAMEP (object)
280 && FRAME_LIVE_P (XFRAME (object)))
281 ? Fframep (object)
282 : Qnil);
285 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
286 doc: /* The name of the window system that FRAME is displaying through.
287 The value is a symbol:
288 nil for a termcap frame (a character-only terminal),
289 `x' for an Emacs frame that is really an X window,
290 `w32' for an Emacs frame that is a window on MS-Windows display,
291 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
292 `pc' for a direct-write MS-DOS frame.
294 FRAME defaults to the currently selected frame.
296 Use of this function as a predicate is deprecated. Instead,
297 use `display-graphic-p' or any of the other `display-*-p'
298 predicates which report frame's specific UI-related capabilities. */)
299 (Lisp_Object frame)
301 Lisp_Object type;
302 if (NILP (frame))
303 frame = selected_frame;
305 type = Fframep (frame);
307 if (NILP (type))
308 wrong_type_argument (Qframep, frame);
310 if (EQ (type, Qt))
311 return Qnil;
312 else
313 return type;
316 /* Placeholder used by temacs -nw before window.el is loaded. */
317 DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
318 Sframe_windows_min_size, 4, 4, 0,
319 doc: /* */
320 attributes: const)
321 (Lisp_Object frame, Lisp_Object horizontal,
322 Lisp_Object ignore, Lisp_Object pixelwise)
324 return make_number (0);
328 * frame_windows_min_size:
330 * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
331 * of FRAME. If PIXELWISE is non-nil, return the minimum inner height
332 * (width) of FRAME in pixels.
334 * This value is calculated by the function `frame-windows-min-size' in
335 * window.el unless the `min-height' (`min-width' if HORIZONTAL is
336 * non-nil) parameter of FRAME is non-nil thus explicitly specifying the
337 * value to be returned. In that latter case IGNORE is ignored.
339 * If `frame-windows-min-size' is called, it will make sure that the
340 * return value accommodates all windows of FRAME respecting the values
341 * of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil).
342 * With IGNORE non-nil the values of these variables are ignored.
344 * In either case, never return a value less than 1.
346 static int
347 frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
348 Lisp_Object ignore, Lisp_Object pixelwise)
350 struct frame *f = XFRAME (frame);
351 Lisp_Object par_size;
353 if ((!NILP (horizontal)
354 && NUMBERP (par_size = get_frame_param (f, Qmin_width)))
355 || (NILP (horizontal)
356 && NUMBERP (par_size = get_frame_param (f, Qmin_height))))
358 int min_size = XINT (par_size);
360 /* Don't allow phantom frames. */
361 if (min_size < 1)
362 min_size = 1;
364 return (NILP (pixelwise)
365 ? min_size
366 : min_size * (NILP (horizontal)
367 ? FRAME_LINE_HEIGHT (f)
368 : FRAME_COLUMN_WIDTH (f)));
370 else
371 return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
372 ignore, pixelwise));
376 #ifdef HAVE_WINDOW_SYSTEM
378 * keep_ratio:
380 * Preserve ratios of frame F which usually happens after its parent
381 * frame P got resized. OLD_WIDTH, OLD_HEIGHT specifies the old native
382 * size of F's parent, NEW_WIDTH and NEW_HEIGHT its new size.
384 * Adjust F's width if F's 'keep_ratio' parameter is non-nil and, if
385 * it is a cons, its car is not 'height-only'. Adjust F's height if F's
386 * 'keep_ratio' parameter is non-nil and, if it is a cons, its car
387 * is not 'width-only'.
389 * Adjust F's left position if F's 'keep_ratio' parameter is non-nil
390 * and, if its is a cons, its cdr is non-nil and not 'top-only'. Adjust
391 * F's top position if F's 'keep_ratio' parameter is non-nil and, if
392 * its is a cons, its cdr is non-nil and not 'left-only'.
394 * Note that when positional adjustment is requested but the size of F
395 * should remain unaltered in the corresponding direction, this routine
396 * tries to constrain F to its parent frame - something which usually
397 * happens when the parent frame shrinks. This means, however, that
398 * when the parent frame is re-enlarged later, the child's original
399 * position will not get restored to its pre-shrinking value.
401 * This routine is currently useful for child frames only. It might be
402 * eventually useful when moving non-child frames between monitors with
403 * different resolutions.
405 static void
406 keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
407 int new_width, int new_height)
409 Lisp_Object keep_ratio = get_frame_param (f, Qkeep_ratio);
412 if (!NILP (keep_ratio))
414 double width_factor = (double)new_width / (double)old_width;
415 double height_factor = (double)new_height / (double)old_height;
416 int pixel_width, pixel_height, pos_x, pos_y;
418 if (!CONSP (keep_ratio) || !NILP (Fcdr (keep_ratio)))
420 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qtop_only))
421 pos_x = f->left_pos;
422 else
424 pos_x = (int)(f->left_pos * width_factor + 0.5);
426 if (CONSP (keep_ratio)
427 && (NILP (Fcar (keep_ratio))
428 || EQ (Fcar (keep_ratio), Qheight_only))
429 && p->pixel_width - f->pixel_width < pos_x)
431 int p_f_width = p->pixel_width - f->pixel_width;
433 if (p_f_width <= 0)
434 pos_x = 0;
435 else
436 pos_x = (int)(p_f_width * width_factor * 0.5 + 0.5);
439 f->left_pos = pos_x;
442 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qleft_only))
443 pos_y = f->top_pos;
444 else
446 pos_y = (int)(f->top_pos * height_factor + 0.5);
448 if (CONSP (keep_ratio)
449 && (NILP (Fcar (keep_ratio))
450 || EQ (Fcar (keep_ratio), Qwidth_only))
451 && p->pixel_height - f->pixel_height < pos_y)
452 /* When positional adjustment was requested and the
453 width of F should remain unaltered, try to constrain
454 F to its parent. This means that when the parent
455 frame is enlarged later the child's original position
456 won't get restored. */
458 int p_f_height = p->pixel_height - f->pixel_height;
460 if (p_f_height <= 0)
461 pos_y = 0;
462 else
463 pos_y = (int)(p_f_height * height_factor * 0.5 + 0.5);
466 f->top_pos = pos_y;
469 x_set_offset (f, pos_x, pos_y, -1);
472 if (!CONSP (keep_ratio) || !NILP (Fcar (keep_ratio)))
474 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qheight_only))
475 pixel_width = -1;
476 else
478 pixel_width = (int)(f->pixel_width * width_factor + 0.5);
479 pixel_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixel_width);
482 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qwidth_only))
483 pixel_height = -1;
484 else
486 pixel_height = (int)(f->pixel_height * height_factor + 0.5);
487 pixel_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixel_height);
490 adjust_frame_size (f, pixel_width, pixel_height, 1, 0,
491 Qkeep_ratio);
495 #endif
499 * adjust_frame_size:
501 * Adjust size of frame F. NEW_WIDTH and NEW_HEIGHT specify the new
502 * text size of F in pixels. A value of -1 means no change is requested
503 * for that direction (but the frame may still have to be resized to
504 * accommodate windows with their minimum sizes). This can either issue
505 * a request to resize the frame externally (via x_set_window_size), to
506 * resize the frame internally (via resize_frame_windows) or do nothing
507 * at all.
509 * The argument INHIBIT can assume the following values:
511 * 0 means to unconditionally call x_set_window_size even if sizes
512 * apparently do not change. Fx_create_frame uses this to pass the
513 * initial size to the window manager.
515 * 1 means to call x_set_window_size if the native frame size really
516 * changes. Fset_frame_size, Fset_frame_height, ... use this.
518 * 2 means to call x_set_window_size provided frame_inhibit_resize
519 * allows it. The menu and tool bar code use this ("3" won't work
520 * here in general because menu and tool bar are often not counted in
521 * the frame's text height).
523 * 3 means call x_set_window_size if window minimum sizes must be
524 * preserved or frame_inhibit_resize allows it. x_set_left_fringe,
525 * x_set_scroll_bar_width, x_new_font ... use (or should use) this.
527 * 4 means call x_set_window_size only if window minimum sizes must be
528 * preserved. x_set_right_divider_width, x_set_border_width and the
529 * code responsible for wrapping the tool bar use this.
531 * 5 means to never call x_set_window_size. change_frame_size uses
532 * this.
534 * Note that even when x_set_window_size is not called, individual
535 * windows may have to be resized (via `window--sanitize-window-sizes')
536 * in order to support minimum size constraints.
538 * PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
539 * symbol of the parameter changed (like `menu-bar-lines', `font', ...).
540 * This is passed on to frame_inhibit_resize to let the latter decide on
541 * a case-by-case basis whether the frame may be resized externally.
543 void
544 adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
545 bool pretend, Lisp_Object parameter)
547 int unit_width = FRAME_COLUMN_WIDTH (f);
548 int unit_height = FRAME_LINE_HEIGHT (f);
549 int old_pixel_width = FRAME_PIXEL_WIDTH (f);
550 int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
551 int old_cols = FRAME_COLS (f);
552 int old_lines = FRAME_LINES (f);
553 int new_pixel_width, new_pixel_height;
554 /* The following two values are calculated from the old frame pixel
555 sizes and any "new" settings for tool bar, menu bar and internal
556 borders. We do it this way to detect whether we have to call
557 x_set_window_size as consequence of the new settings. */
558 int windows_width = FRAME_WINDOWS_WIDTH (f);
559 int windows_height = FRAME_WINDOWS_HEIGHT (f);
560 int min_windows_width, min_windows_height;
561 /* These are a bit tedious, maybe we should use a macro. */
562 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
563 int old_windows_width = WINDOW_PIXEL_WIDTH (r);
564 int old_windows_height
565 = (WINDOW_PIXEL_HEIGHT (r)
566 + ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
567 ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
568 : 0));
569 int new_windows_width, new_windows_height;
570 int old_text_width = FRAME_TEXT_WIDTH (f);
571 int old_text_height = FRAME_TEXT_HEIGHT (f);
572 /* If a size is < 0 use the old value. */
573 int new_text_width = (new_width >= 0) ? new_width : old_text_width;
574 int new_text_height = (new_height >= 0) ? new_height : old_text_height;
575 int new_cols, new_lines;
576 bool inhibit_horizontal, inhibit_vertical;
577 Lisp_Object frame;
579 XSETFRAME (frame, f);
581 frame_size_history_add
582 (f, Qadjust_frame_size_1, new_text_width, new_text_height,
583 list2 (parameter, make_number (inhibit)));
585 /* The following two values are calculated from the old window body
586 sizes and any "new" settings for scroll bars, dividers, fringes and
587 margins (though the latter should have been processed already). */
588 min_windows_width
589 = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
590 min_windows_height
591 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
593 if (inhibit >= 2 && inhibit <= 4)
594 /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
595 within the limits and either resizing is inhibited or INHIBIT
596 equals 4. */
598 inhibit_horizontal = (windows_width >= min_windows_width
599 && (inhibit == 4
600 || frame_inhibit_resize (f, true, parameter)));
601 inhibit_vertical = (windows_height >= min_windows_height
602 && (inhibit == 4
603 || frame_inhibit_resize (f, false, parameter)));
605 else
606 /* Otherwise inhibit if INHIBIT equals 5. */
607 inhibit_horizontal = inhibit_vertical = inhibit == 5;
609 new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
610 ? old_pixel_width
611 : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
612 min_windows_width
613 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
614 new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
615 new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
616 new_cols = new_text_width / unit_width;
618 new_pixel_height = ((inhibit_vertical && (inhibit < 5))
619 ? old_pixel_height
620 : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
621 min_windows_height
622 + FRAME_TOP_MARGIN_HEIGHT (f)
623 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
624 new_windows_height = (new_pixel_height
625 - FRAME_TOP_MARGIN_HEIGHT (f)
626 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
627 new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
628 new_lines = new_text_height / unit_height;
630 #ifdef HAVE_WINDOW_SYSTEM
631 if (FRAME_WINDOW_P (f)
632 && f->can_x_set_window_size
633 && ((!inhibit_horizontal
634 && (new_pixel_width != old_pixel_width
635 || inhibit == 0 || inhibit == 2))
636 || (!inhibit_vertical
637 && (new_pixel_height != old_pixel_height
638 || inhibit == 0 || inhibit == 2))))
639 /* We are either allowed to change the frame size or the minimum
640 sizes request such a change. Do not care for fixing minimum
641 sizes here, we do that eventually when we're called from
642 change_frame_size. */
644 /* Make sure we respect fullheight and fullwidth. */
645 if (inhibit_horizontal)
646 new_text_width = old_text_width;
647 else if (inhibit_vertical)
648 new_text_height = old_text_height;
650 frame_size_history_add
651 (f, Qadjust_frame_size_2, new_text_width, new_text_height,
652 list2 (inhibit_horizontal ? Qt : Qnil,
653 inhibit_vertical ? Qt : Qnil));
655 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
656 f->resized_p = true;
658 return;
660 #endif
662 if (new_text_width == old_text_width
663 && new_text_height == old_text_height
664 && new_windows_width == old_windows_width
665 && new_windows_height == old_windows_height
666 && new_pixel_width == old_pixel_width
667 && new_pixel_height == old_pixel_height
668 && new_cols == old_cols
669 && new_lines == old_lines)
670 /* No change. Sanitize window sizes and return. */
672 sanitize_window_sizes (Qt);
673 sanitize_window_sizes (Qnil);
675 return;
678 block_input ();
680 #ifdef MSDOS
681 /* We only can set screen dimensions to certain values supported by
682 our video hardware. Try to find the smallest size greater or
683 equal to the requested dimensions, while accounting for the fact
684 that the menu-bar lines are not counted in the frame height. */
685 int dos_new_lines = new_lines + FRAME_TOP_MARGIN (f);
686 dos_set_window_size (&dos_new_lines, &new_cols);
687 new_lines = dos_new_lines - FRAME_TOP_MARGIN (f);
688 #endif
690 if (new_windows_width != old_windows_width)
692 resize_frame_windows (f, new_windows_width, 1, 1);
694 /* MSDOS frames cannot PRETEND, as they change frame size by
695 manipulating video hardware. */
696 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
697 FrameCols (FRAME_TTY (f)) = new_cols;
699 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
700 if (WINDOWP (f->tool_bar_window))
702 XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
703 XWINDOW (f->tool_bar_window)->total_cols
704 = new_windows_width / unit_width;
706 #endif
708 else if (new_cols != old_cols)
709 call2 (Qwindow__pixel_to_total, frame, Qt);
711 if (new_windows_height != old_windows_height
712 /* When the top margin has changed we have to recalculate the top
713 edges of all windows. No such calculation is necessary for the
714 left edges. */
715 || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
717 resize_frame_windows (f, new_windows_height, 0, 1);
719 /* MSDOS frames cannot PRETEND, as they change frame size by
720 manipulating video hardware. */
721 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
722 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
724 else if (new_lines != old_lines)
725 call2 (Qwindow__pixel_to_total, frame, Qnil);
727 frame_size_history_add
728 (f, Qadjust_frame_size_3, new_text_width, new_text_height,
729 list4 (make_number (old_pixel_width), make_number (old_pixel_height),
730 make_number (new_pixel_width), make_number (new_pixel_height)));
732 /* Assign new sizes. */
733 FRAME_TEXT_WIDTH (f) = new_text_width;
734 FRAME_TEXT_HEIGHT (f) = new_text_height;
735 FRAME_PIXEL_WIDTH (f) = new_pixel_width;
736 FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
737 SET_FRAME_COLS (f, new_cols);
738 SET_FRAME_LINES (f, new_lines);
741 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
742 int text_area_x, text_area_y, text_area_width, text_area_height;
744 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
745 &text_area_height);
746 if (w->cursor.x >= text_area_x + text_area_width)
747 w->cursor.hpos = w->cursor.x = 0;
748 if (w->cursor.y >= text_area_y + text_area_height)
749 w->cursor.vpos = w->cursor.y = 0;
752 /* Sanitize window sizes. */
753 sanitize_window_sizes (Qt);
754 sanitize_window_sizes (Qnil);
756 adjust_frame_glyphs (f);
757 calculate_costs (f);
758 SET_FRAME_GARBAGED (f);
760 /* A frame was "resized" if one of its pixelsizes changed, even if its
761 X window wasn't resized at all. */
762 f->resized_p = (new_pixel_width != old_pixel_width
763 || new_pixel_height != old_pixel_height);
765 unblock_input ();
767 #ifdef HAVE_WINDOW_SYSTEM
769 /* Adjust size of F's child frames. */
770 Lisp_Object frames, frame1;
772 FOR_EACH_FRAME (frames, frame1)
773 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f)
774 keep_ratio (XFRAME (frame1), f, old_pixel_width, old_pixel_height,
775 new_pixel_width, new_pixel_height);
777 #endif
780 /* Allocate basically initialized frame. */
782 static struct frame *
783 allocate_frame (void)
785 return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
788 struct frame *
789 make_frame (bool mini_p)
791 Lisp_Object frame;
792 struct frame *f;
793 struct window *rw, *mw UNINIT;
794 Lisp_Object root_window;
795 Lisp_Object mini_window;
797 f = allocate_frame ();
798 XSETFRAME (frame, f);
800 #ifdef USE_GTK
801 /* Initialize Lisp data. Note that allocate_frame initializes all
802 Lisp data to nil, so do it only for slots which should not be nil. */
803 fset_tool_bar_position (f, Qtop);
804 #endif
806 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
807 non-Lisp data, so do it only for slots which should not be zero.
808 To avoid subtle bugs and for the sake of readability, it's better to
809 initialize enum members explicitly even if their values are zero. */
810 f->wants_modeline = true;
811 f->redisplay = true;
812 f->garbaged = true;
813 f->can_x_set_window_size = false;
814 f->after_make_frame = false;
815 f->inhibit_horizontal_resize = false;
816 f->inhibit_vertical_resize = false;
817 f->tool_bar_redisplayed = false;
818 f->tool_bar_resized = false;
819 f->column_width = 1; /* !FRAME_WINDOW_P value. */
820 f->line_height = 1; /* !FRAME_WINDOW_P value. */
821 #ifdef HAVE_WINDOW_SYSTEM
822 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
823 f->horizontal_scroll_bars = false;
824 f->want_fullscreen = FULLSCREEN_NONE;
825 f->undecorated = false;
826 f->no_special_glyphs = false;
827 #ifndef HAVE_NTGUI
828 f->override_redirect = false;
829 #endif
830 f->skip_taskbar = false;
831 f->no_focus_on_map = false;
832 f->no_accept_focus = false;
833 f->z_group = z_group_none;
834 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
835 f->last_tool_bar_item = -1;
836 #endif
837 #ifdef NS_IMPL_COCOA
838 f->ns_appearance = ns_appearance_aqua;
839 f->ns_transparent_titlebar = false;
840 #endif
841 #endif
843 root_window = make_window ();
844 rw = XWINDOW (root_window);
845 if (mini_p)
847 mini_window = make_window ();
848 mw = XWINDOW (mini_window);
849 wset_next (rw, mini_window);
850 wset_prev (mw, root_window);
851 mw->mini = 1;
852 wset_frame (mw, frame);
853 fset_minibuffer_window (f, mini_window);
854 store_frame_param (f, Qminibuffer, Qt);
856 else
858 mini_window = Qnil;
859 wset_next (rw, Qnil);
860 fset_minibuffer_window (f, Qnil);
863 wset_frame (rw, frame);
865 /* 10 is arbitrary,
866 just so that there is "something there."
867 Correct size will be set up later with adjust_frame_size. */
869 SET_FRAME_COLS (f, 10);
870 SET_FRAME_LINES (f, 10);
871 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
872 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
874 rw->total_cols = 10;
875 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
876 rw->total_lines = mini_p ? 9 : 10;
877 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
879 if (mini_p)
881 mw->top_line = rw->total_lines;
882 mw->pixel_top = rw->pixel_height;
883 mw->total_cols = rw->total_cols;
884 mw->pixel_width = rw->pixel_width;
885 mw->total_lines = 1;
886 mw->pixel_height = FRAME_LINE_HEIGHT (f);
889 /* Choose a buffer for the frame's root window. */
891 Lisp_Object buf = Fcurrent_buffer ();
893 /* If current buffer is hidden, try to find another one. */
894 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
895 buf = other_buffer_safely (buf);
897 /* Use set_window_buffer, not Fset_window_buffer, and don't let
898 hooks be run by it. The reason is that the whole frame/window
899 arrangement is not yet fully initialized at this point. Windows
900 don't have the right size, glyph matrices aren't initialized
901 etc. Running Lisp functions at this point surely ends in a
902 SEGV. */
903 set_window_buffer (root_window, buf, 0, 0);
904 fset_buffer_list (f, list1 (buf));
907 if (mini_p)
909 set_window_buffer (mini_window,
910 (NILP (Vminibuffer_list)
911 ? get_minibuffer (0)
912 : Fcar (Vminibuffer_list)),
913 0, 0);
914 /* No horizontal scroll bars in minibuffers. */
915 wset_horizontal_scroll_bar (mw, Qnil);
918 fset_root_window (f, root_window);
919 fset_selected_window (f, root_window);
920 /* Make sure this window seems more recently used than
921 a newly-created, never-selected window. */
922 XWINDOW (f->selected_window)->use_time = ++window_select_count;
924 return f;
927 #ifdef HAVE_WINDOW_SYSTEM
928 /* Make a frame using a separate minibuffer window on another frame.
929 MINI_WINDOW is the minibuffer window to use. nil means use the
930 default (the global minibuffer). */
932 struct frame *
933 make_frame_without_minibuffer (Lisp_Object mini_window, KBOARD *kb,
934 Lisp_Object display)
936 struct frame *f;
938 if (!NILP (mini_window))
939 CHECK_LIVE_WINDOW (mini_window);
941 if (!NILP (mini_window)
942 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
943 error ("Frame and minibuffer must be on the same terminal");
945 /* Make a frame containing just a root window. */
946 f = make_frame (0);
948 if (NILP (mini_window))
950 /* Use default-minibuffer-frame if possible. */
951 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
952 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
954 Lisp_Object frame_dummy;
956 XSETFRAME (frame_dummy, f);
957 /* If there's no minibuffer frame to use, create one. */
958 kset_default_minibuffer_frame
959 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
962 mini_window
963 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
966 fset_minibuffer_window (f, mini_window);
967 store_frame_param (f, Qminibuffer, mini_window);
969 /* Make the chosen minibuffer window display the proper minibuffer,
970 unless it is already showing a minibuffer. */
971 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
972 /* Use set_window_buffer instead of Fset_window_buffer (see
973 discussion of bug#11984, bug#12025, bug#12026). */
974 set_window_buffer (mini_window,
975 (NILP (Vminibuffer_list)
976 ? get_minibuffer (0)
977 : Fcar (Vminibuffer_list)), 0, 0);
978 return f;
981 /* Make a frame containing only a minibuffer window. */
983 struct frame *
984 make_minibuffer_frame (void)
986 /* First make a frame containing just a root window, no minibuffer. */
988 register struct frame *f = make_frame (0);
989 register Lisp_Object mini_window;
990 register Lisp_Object frame;
992 XSETFRAME (frame, f);
994 f->auto_raise = 0;
995 f->auto_lower = 0;
996 f->no_split = 1;
997 f->wants_modeline = 0;
999 /* Now label the root window as also being the minibuffer.
1000 Avoid infinite looping on the window chain by marking next pointer
1001 as nil. */
1003 mini_window = f->root_window;
1004 fset_minibuffer_window (f, mini_window);
1005 store_frame_param (f, Qminibuffer, Qonly);
1006 XWINDOW (mini_window)->mini = 1;
1007 wset_next (XWINDOW (mini_window), Qnil);
1008 wset_prev (XWINDOW (mini_window), Qnil);
1009 wset_frame (XWINDOW (mini_window), frame);
1011 /* Put the proper buffer in that window. */
1013 /* Use set_window_buffer instead of Fset_window_buffer (see
1014 discussion of bug#11984, bug#12025, bug#12026). */
1015 set_window_buffer (mini_window,
1016 (NILP (Vminibuffer_list)
1017 ? get_minibuffer (0)
1018 : Fcar (Vminibuffer_list)), 0, 0);
1019 return f;
1021 #endif /* HAVE_WINDOW_SYSTEM */
1023 /* Construct a frame that refers to a terminal. */
1025 static printmax_t tty_frame_count;
1027 struct frame *
1028 make_initial_frame (void)
1030 struct frame *f;
1031 struct terminal *terminal;
1032 Lisp_Object frame;
1034 eassert (initial_kboard);
1036 /* The first call must initialize Vframe_list. */
1037 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
1038 Vframe_list = Qnil;
1040 terminal = init_initial_terminal ();
1042 f = make_frame (1);
1043 XSETFRAME (frame, f);
1045 Vframe_list = Fcons (frame, Vframe_list);
1047 tty_frame_count = 1;
1048 fset_name (f, build_pure_c_string ("F1"));
1050 SET_FRAME_VISIBLE (f, 1);
1052 f->output_method = terminal->type;
1053 f->terminal = terminal;
1054 f->terminal->reference_count++;
1055 f->output_data.nothing = 0;
1057 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1058 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1060 #ifdef HAVE_WINDOW_SYSTEM
1061 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1062 f->horizontal_scroll_bars = false;
1063 #endif
1065 /* The default value of menu-bar-mode is t. */
1066 set_menu_bar_lines (f, make_number (1), Qnil);
1068 /* Allocate glyph matrices. */
1069 adjust_frame_glyphs (f);
1071 if (!noninteractive)
1072 init_frame_faces (f);
1074 last_nonminibuf_frame = f;
1076 f->can_x_set_window_size = true;
1077 f->after_make_frame = true;
1079 return f;
1083 static struct frame *
1084 make_terminal_frame (struct terminal *terminal)
1086 register struct frame *f;
1087 Lisp_Object frame;
1088 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
1090 if (!terminal->name)
1091 error ("Terminal is not live, can't create new frames on it");
1093 f = make_frame (1);
1095 XSETFRAME (frame, f);
1096 Vframe_list = Fcons (frame, Vframe_list);
1098 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
1100 SET_FRAME_VISIBLE (f, 1);
1102 f->terminal = terminal;
1103 f->terminal->reference_count++;
1104 #ifdef MSDOS
1105 f->output_data.tty->display_info = &the_only_display_info;
1106 if (!inhibit_window_system
1107 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
1108 || XFRAME (selected_frame)->output_method == output_msdos_raw))
1109 f->output_method = output_msdos_raw;
1110 else
1111 f->output_method = output_termcap;
1112 #else /* not MSDOS */
1113 f->output_method = output_termcap;
1114 create_tty_output (f);
1115 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1116 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1117 #endif /* not MSDOS */
1119 #ifdef HAVE_WINDOW_SYSTEM
1120 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1121 f->horizontal_scroll_bars = false;
1122 #endif
1124 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
1125 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
1126 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
1127 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
1129 /* Set the top frame to the newly created frame. */
1130 if (FRAMEP (FRAME_TTY (f)->top_frame)
1131 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
1132 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
1134 FRAME_TTY (f)->top_frame = frame;
1136 if (!noninteractive)
1137 init_frame_faces (f);
1139 return f;
1142 /* Get a suitable value for frame parameter PARAMETER for a newly
1143 created frame, based on (1) the user-supplied frame parameter
1144 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
1146 static Lisp_Object
1147 get_future_frame_param (Lisp_Object parameter,
1148 Lisp_Object supplied_parms,
1149 char *current_value)
1151 Lisp_Object result;
1153 result = Fassq (parameter, supplied_parms);
1154 if (NILP (result))
1155 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
1156 if (NILP (result) && current_value != NULL)
1157 result = build_string (current_value);
1158 if (!NILP (result) && !STRINGP (result))
1159 result = XCDR (result);
1160 if (NILP (result) || !STRINGP (result))
1161 result = Qnil;
1163 return result;
1166 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1167 1, 1, 0,
1168 doc: /* Create an additional terminal frame, possibly on another terminal.
1169 This function takes one argument, an alist specifying frame parameters.
1171 You can create multiple frames on a single text terminal, but only one
1172 of them (the selected terminal frame) is actually displayed.
1174 In practice, generally you don't need to specify any parameters,
1175 except when you want to create a new frame on another terminal.
1176 In that case, the `tty' parameter specifies the device file to open,
1177 and the `tty-type' parameter specifies the terminal type. Example:
1179 (make-terminal-frame \\='((tty . "/dev/pts/5") (tty-type . "xterm")))
1181 Note that changing the size of one terminal frame automatically
1182 affects all frames on the same terminal device. */)
1183 (Lisp_Object parms)
1185 struct frame *f;
1186 struct terminal *t = NULL;
1187 Lisp_Object frame, tem;
1188 struct frame *sf = SELECTED_FRAME ();
1190 #ifdef MSDOS
1191 if (sf->output_method != output_msdos_raw
1192 && sf->output_method != output_termcap)
1193 emacs_abort ();
1194 #else /* not MSDOS */
1196 #ifdef WINDOWSNT /* This should work now! */
1197 if (sf->output_method != output_termcap)
1198 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
1199 #endif
1200 #endif /* not MSDOS */
1203 Lisp_Object terminal;
1205 terminal = Fassq (Qterminal, parms);
1206 if (CONSP (terminal))
1208 terminal = XCDR (terminal);
1209 t = decode_live_terminal (terminal);
1211 #ifdef MSDOS
1212 if (t && t != the_only_display_info.terminal)
1213 /* msdos.c assumes a single tty_display_info object. */
1214 error ("Multiple terminals are not supported on this platform");
1215 if (!t)
1216 t = the_only_display_info.terminal;
1217 #endif
1220 if (!t)
1222 char *name = 0, *type = 0;
1223 Lisp_Object tty, tty_type;
1224 USE_SAFE_ALLOCA;
1226 tty = get_future_frame_param
1227 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1228 ? FRAME_TTY (XFRAME (selected_frame))->name
1229 : NULL));
1230 if (!NILP (tty))
1231 SAFE_ALLOCA_STRING (name, tty);
1233 tty_type = get_future_frame_param
1234 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1235 ? FRAME_TTY (XFRAME (selected_frame))->type
1236 : NULL));
1237 if (!NILP (tty_type))
1238 SAFE_ALLOCA_STRING (type, tty_type);
1240 t = init_tty (name, type, 0); /* Errors are not fatal. */
1241 SAFE_FREE ();
1244 f = make_terminal_frame (t);
1247 int width, height;
1248 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1249 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
1250 5, 0, Qterminal_frame);
1253 adjust_frame_glyphs (f);
1254 calculate_costs (f);
1255 XSETFRAME (frame, f);
1257 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
1258 store_in_alist (&parms, Qtty,
1259 (t->display_info.tty->name
1260 ? build_string (t->display_info.tty->name)
1261 : Qnil));
1262 /* On terminal frames the `minibuffer' frame parameter is always
1263 virtually t. Avoid that a different value in parms causes
1264 complaints, see Bug#24758. */
1265 store_in_alist (&parms, Qminibuffer, Qt);
1266 Fmodify_frame_parameters (frame, parms);
1268 /* Make the frame face alist be frame-specific, so that each
1269 frame could change its face definitions independently. */
1270 fset_face_alist (f, Fcopy_alist (sf->face_alist));
1271 /* Simple Fcopy_alist isn't enough, because we need the contents of
1272 the vectors which are the CDRs of associations in face_alist to
1273 be copied as well. */
1274 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
1275 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
1277 f->can_x_set_window_size = true;
1278 f->after_make_frame = true;
1280 return frame;
1284 /* Perform the switch to frame FRAME.
1286 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
1287 FRAME1 as frame.
1289 If TRACK is non-zero and the frame that currently has the focus
1290 redirects its focus to the selected frame, redirect that focused
1291 frame's focus to FRAME instead.
1293 FOR_DELETION non-zero means that the selected frame is being
1294 deleted, which includes the possibility that the frame's terminal
1295 is dead.
1297 The value of NORECORD is passed as argument to Fselect_window. */
1299 Lisp_Object
1300 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1302 struct frame *sf = SELECTED_FRAME (), *f;
1304 /* If FRAME is a switch-frame event, extract the frame we should
1305 switch to. */
1306 if (CONSP (frame)
1307 && EQ (XCAR (frame), Qswitch_frame)
1308 && CONSP (XCDR (frame)))
1309 frame = XCAR (XCDR (frame));
1311 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1312 a switch-frame event to arrive after a frame is no longer live,
1313 especially when deleting the initial frame during startup. */
1314 CHECK_FRAME (frame);
1315 f = XFRAME (frame);
1316 if (!FRAME_LIVE_P (f))
1317 return Qnil;
1318 else if (f == sf)
1319 return frame;
1321 /* If a frame's focus has been redirected toward the currently
1322 selected frame, we should change the redirection to point to the
1323 newly selected frame. This means that if the focus is redirected
1324 from a minibufferless frame to a surrogate minibuffer frame, we
1325 can use `other-window' to switch between all the frames using
1326 that minibuffer frame, and the focus redirection will follow us
1327 around. */
1328 #if 0
1329 /* This is too greedy; it causes inappropriate focus redirection
1330 that's hard to get rid of. */
1331 if (track)
1333 Lisp_Object tail;
1335 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1337 Lisp_Object focus;
1339 if (!FRAMEP (XCAR (tail)))
1340 emacs_abort ();
1342 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1344 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1345 Fredirect_frame_focus (XCAR (tail), frame);
1348 #else /* ! 0 */
1349 /* Instead, apply it only to the frame we're pointing to. */
1350 #ifdef HAVE_WINDOW_SYSTEM
1351 if (track && FRAME_WINDOW_P (f))
1353 Lisp_Object focus, xfocus;
1355 xfocus = x_get_focus_frame (f);
1356 if (FRAMEP (xfocus))
1358 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1359 if ((FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1360 /* Redirect frame focus also when FRAME has its minibuffer
1361 window on the selected frame (see Bug#24500). */
1362 || (NILP (focus)
1363 && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))
1364 Fredirect_frame_focus (xfocus, frame);
1367 #endif /* HAVE_X_WINDOWS */
1368 #endif /* ! 0 */
1370 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1371 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1373 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
1375 struct tty_display_info *tty = FRAME_TTY (f);
1376 Lisp_Object top_frame = tty->top_frame;
1378 /* Don't mark the frame garbaged and/or obscured if we are
1379 switching to the frame that is already the top frame of that
1380 TTY. */
1381 if (!EQ (frame, top_frame))
1383 if (FRAMEP (top_frame))
1384 /* Mark previously displayed frame as now obscured. */
1385 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1386 SET_FRAME_VISIBLE (f, 1);
1387 /* If the new TTY frame changed dimensions, we need to
1388 resync term.c's idea of the frame size with the new
1389 frame's data. */
1390 if (FRAME_COLS (f) != FrameCols (tty))
1391 FrameCols (tty) = FRAME_COLS (f);
1392 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1393 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1395 tty->top_frame = frame;
1398 selected_frame = frame;
1399 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1400 last_nonminibuf_frame = XFRAME (selected_frame);
1402 Fselect_window (f->selected_window, norecord);
1404 /* We want to make sure that the next event generates a frame-switch
1405 event to the appropriate frame. This seems kludgy to me, but
1406 before you take it out, make sure that evaluating something like
1407 (select-window (frame-root-window (new-frame))) doesn't end up
1408 with your typing being interpreted in the new frame instead of
1409 the one you're actually typing in. */
1410 #ifdef HAVE_WINDOW_SYSTEM
1411 if (!frame_ancestor_p (f, sf))
1412 #endif
1413 internal_last_event_frame = Qnil;
1415 return frame;
1418 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1419 doc: /* Select FRAME.
1420 Subsequent editing commands apply to its selected window.
1421 Optional argument NORECORD means to neither change the order of
1422 recently selected windows nor the buffer list.
1424 The selection of FRAME lasts until the next time the user does
1425 something to select a different frame, or until the next time
1426 this function is called. If you are using a window system, the
1427 previously selected frame may be restored as the selected frame
1428 when returning to the command loop, because it still may have
1429 the window system's input focus. On a text terminal, the next
1430 redisplay will display FRAME.
1432 This function returns FRAME, or nil if FRAME has been deleted. */)
1433 (Lisp_Object frame, Lisp_Object norecord)
1435 return do_switch_frame (frame, 1, 0, norecord);
1438 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1439 doc: /* Handle a switch-frame event EVENT.
1440 Switch-frame events are usually bound to this function.
1441 A switch-frame event tells Emacs that the window manager has requested
1442 that the user's events be directed to the frame mentioned in the event.
1443 This function selects the selected window of the frame of EVENT.
1445 If EVENT is frame object, handle it as if it were a switch-frame event
1446 to that frame. */)
1447 (Lisp_Object event)
1449 Lisp_Object value;
1451 /* Preserve prefix arg that the command loop just cleared. */
1452 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1453 run_hook (Qmouse_leave_buffer_hook);
1454 /* `switch-frame' implies a focus in. */
1455 value = do_switch_frame (event, 0, 0, Qnil);
1456 call1 (intern ("handle-focus-in"), event);
1457 return value;
1460 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1461 doc: /* Return the frame that is now selected. */)
1462 (void)
1464 return selected_frame;
1467 DEFUN ("frame-list", Fframe_list, Sframe_list,
1468 0, 0, 0,
1469 doc: /* Return a list of all live frames. */)
1470 (void)
1472 Lisp_Object frames;
1473 frames = Fcopy_sequence (Vframe_list);
1474 #ifdef HAVE_WINDOW_SYSTEM
1475 if (FRAMEP (tip_frame)
1476 #ifdef USE_GTK
1477 && !NILP (Fframe_parameter (tip_frame, Qtooltip))
1478 #endif
1480 frames = Fdelq (tip_frame, frames);
1481 #endif
1482 return frames;
1485 DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
1486 0, 1, 0,
1487 doc: /* Return the parent frame of FRAME.
1488 The parent frame of FRAME is the Emacs frame whose window-system window
1489 is the parent window of FRAME's window-system window. When such a frame
1490 exists, FRAME is considered a child frame of that frame.
1492 Return nil if FRAME has no parent frame. This means that FRAME's
1493 window-system window is either a "top-level" window (a window whose
1494 parent window is the window-system's root window) or an embedded window
1495 \(a window whose parent window is owned by some other application). */)
1496 (Lisp_Object frame)
1498 struct frame *f = decode_live_frame (frame);
1499 struct frame *p = FRAME_PARENT_FRAME (f);
1500 Lisp_Object parent;
1502 /* Can't return f->parent_frame directly since it might not be defined
1503 for this platform. */
1504 if (p)
1506 XSETFRAME (parent, p);
1508 return parent;
1510 else
1511 return Qnil;
1514 #ifdef HAVE_WINDOW_SYSTEM
1515 bool
1516 frame_ancestor_p (struct frame *af, struct frame *df)
1518 struct frame *pf = FRAME_PARENT_FRAME (df);
1520 while (pf)
1522 if (pf == af)
1523 return true;
1524 else
1525 pf = FRAME_PARENT_FRAME (pf);
1528 return false;
1530 #endif
1532 DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1533 2, 2, 0,
1534 doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
1535 ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
1536 parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
1537 ANCESTOR and DESCENDANT must be live frames and default to the selected
1538 frame. */)
1539 (Lisp_Object ancestor, Lisp_Object descendant)
1541 #ifdef HAVE_WINDOW_SYSTEM
1542 struct frame *af = decode_live_frame (ancestor);
1543 struct frame *df = decode_live_frame (descendant);
1545 return frame_ancestor_p (af, df) ? Qt : Qnil;
1546 #else
1547 return Qnil;
1548 #endif
1551 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1552 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1553 If MINIBUF is nil, do not consider minibuffer-only candidate.
1554 If MINIBUF is `visible', do not consider an invisible candidate.
1555 If MINIBUF is a window, consider only its own frame and candidate now
1556 using that window as the minibuffer.
1557 If MINIBUF is 0, consider candidate if it is visible or iconified.
1558 Otherwise consider any candidate and return nil if CANDIDATE is not
1559 acceptable. */
1561 static Lisp_Object
1562 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1564 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1566 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1567 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1568 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1569 && FRAME_TTY (c) == FRAME_TTY (f)))
1571 if (!NILP (get_frame_param (c, Qno_other_frame)))
1572 return Qnil;
1573 else if (NILP (minibuf))
1575 if (!FRAME_MINIBUF_ONLY_P (c))
1576 return candidate;
1578 else if (EQ (minibuf, Qvisible))
1580 if (FRAME_VISIBLE_P (c))
1581 return candidate;
1583 else if (WINDOWP (minibuf))
1585 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1586 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1587 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1588 FRAME_FOCUS_FRAME (c)))
1589 return candidate;
1591 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
1593 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1594 return candidate;
1596 else
1597 return candidate;
1599 return Qnil;
1602 /* Return the next frame in the frame list after FRAME. */
1604 static Lisp_Object
1605 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1607 Lisp_Object f, tail;
1608 int passed = 0;
1610 eassume (CONSP (Vframe_list));
1612 while (passed < 2)
1613 FOR_EACH_FRAME (tail, f)
1615 if (passed)
1617 f = candidate_frame (f, frame, minibuf);
1618 if (!NILP (f))
1619 return f;
1621 if (EQ (frame, f))
1622 passed++;
1624 return frame;
1627 /* Return the previous frame in the frame list before FRAME. */
1629 static Lisp_Object
1630 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1632 Lisp_Object f, tail, prev = Qnil;
1634 eassume (CONSP (Vframe_list));
1636 FOR_EACH_FRAME (tail, f)
1638 if (EQ (frame, f) && !NILP (prev))
1639 return prev;
1640 f = candidate_frame (f, frame, minibuf);
1641 if (!NILP (f))
1642 prev = f;
1645 /* We've scanned the entire list. */
1646 if (NILP (prev))
1647 /* We went through the whole frame list without finding a single
1648 acceptable frame. Return the original frame. */
1649 return frame;
1650 else
1651 /* There were no acceptable frames in the list before FRAME; otherwise,
1652 we would have returned directly from the loop. Since PREV is the last
1653 acceptable frame in the list, return it. */
1654 return prev;
1658 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1659 doc: /* Return the next frame in the frame list after FRAME.
1660 It considers only frames on the same terminal as FRAME.
1661 By default, skip minibuffer-only frames.
1662 If omitted, FRAME defaults to the selected frame.
1663 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1664 If MINIFRAME is a window, include only its own frame
1665 and any frame now using that window as the minibuffer.
1666 If MINIFRAME is `visible', include all visible frames.
1667 If MINIFRAME is 0, include all visible and iconified frames.
1668 Otherwise, include all frames. */)
1669 (Lisp_Object frame, Lisp_Object miniframe)
1671 if (NILP (frame))
1672 frame = selected_frame;
1673 CHECK_LIVE_FRAME (frame);
1674 return next_frame (frame, miniframe);
1677 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1678 doc: /* Return the previous frame in the frame list before FRAME.
1679 It considers only frames on the same terminal as FRAME.
1680 By default, skip minibuffer-only frames.
1681 If omitted, FRAME defaults to the selected frame.
1682 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1683 If MINIFRAME is a window, include only its own frame
1684 and any frame now using that window as the minibuffer.
1685 If MINIFRAME is `visible', include all visible frames.
1686 If MINIFRAME is 0, include all visible and iconified frames.
1687 Otherwise, include all frames. */)
1688 (Lisp_Object frame, Lisp_Object miniframe)
1690 if (NILP (frame))
1691 frame = selected_frame;
1692 CHECK_LIVE_FRAME (frame);
1693 return prev_frame (frame, miniframe);
1696 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1697 Slast_nonminibuf_frame, 0, 0, 0,
1698 doc: /* Return last non-minibuffer frame selected. */)
1699 (void)
1701 Lisp_Object frame = Qnil;
1703 if (last_nonminibuf_frame)
1704 XSETFRAME (frame, last_nonminibuf_frame);
1706 return frame;
1710 * other_frames:
1712 * Return true if there exists at least one visible or iconified frame
1713 * but F. Return false otherwise.
1715 * INVISIBLE true means we are called from make_frame_invisible where
1716 * such a frame must be visible or iconified. INVISIBLE nil means we
1717 * are called from delete_frame. In that case FORCE true means that the
1718 * visibility status of such a frame can be ignored.
1720 * If F is the terminal frame and we are using X, return true if at
1721 * least one X frame exists.
1723 static bool
1724 other_frames (struct frame *f, bool invisible, bool force)
1726 Lisp_Object frames, frame, frame1;
1727 struct frame *f1;
1728 Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
1730 XSETFRAME (frame, f);
1731 if (WINDOWP (minibuffer_window)
1732 && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
1733 minibuffer_window = Qnil;
1735 FOR_EACH_FRAME (frames, frame1)
1737 f1 = XFRAME (frame1);
1738 if (f != f1)
1740 /* Verify that we can still talk to the frame's X window, and
1741 note any recent change in visibility. */
1742 #ifdef HAVE_X_WINDOWS
1743 if (FRAME_WINDOW_P (f1))
1744 x_sync (f1);
1745 #endif
1746 if (NILP (Fframe_parameter (frame1, Qtooltip))
1747 /* Tooltips and child frames count neither for
1748 invisibility nor for deletions. */
1749 && !FRAME_PARENT_FRAME (f1)
1750 /* Frames with a non-nil `delete-before' parameter don't
1751 count for deletions. */
1752 && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
1753 /* For invisibility and normal deletions, at least one
1754 visible or iconified frame must remain (Bug#26682). */
1755 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
1756 || (!invisible
1757 && (force
1758 /* Allow deleting the terminal frame when at
1759 least one X frame exists. */
1760 || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))))
1761 return true;
1765 return false;
1768 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1769 window. Preferably use the selected frame's minibuffer window
1770 instead. If the selected frame doesn't have one, get some other
1771 frame's minibuffer window. SELECT non-zero means select the new
1772 minibuffer window. */
1773 static void
1774 check_minibuf_window (Lisp_Object frame, int select)
1776 struct frame *f = decode_live_frame (frame);
1778 XSETFRAME (frame, f);
1780 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1782 Lisp_Object frames, this, window = make_number (0);
1784 if (!EQ (frame, selected_frame)
1785 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1786 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1787 else
1788 FOR_EACH_FRAME (frames, this)
1790 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1792 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1793 break;
1797 /* Don't abort if no window was found (Bug#15247). */
1798 if (WINDOWP (window))
1800 /* Use set_window_buffer instead of Fset_window_buffer (see
1801 discussion of bug#11984, bug#12025, bug#12026). */
1802 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1803 minibuf_window = window;
1805 /* SELECT non-zero usually means that FRAME's minibuffer
1806 window was selected; select the new one. */
1807 if (select)
1808 Fselect_window (minibuf_window, Qnil);
1815 * delete_frame:
1817 * Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1818 * unconditionally. x_connection_closed and delete_terminal use this.
1819 * Any other value of FORCE implements the semantics described for
1820 * Fdelete_frame. */
1821 Lisp_Object
1822 delete_frame (Lisp_Object frame, Lisp_Object force)
1824 struct frame *f = decode_any_frame (frame);
1825 struct frame *sf;
1826 struct kboard *kb;
1827 Lisp_Object frames, frame1;
1828 int minibuffer_selected, is_tooltip_frame;
1829 bool nochild = !FRAME_PARENT_FRAME (f);
1831 if (!FRAME_LIVE_P (f))
1832 return Qnil;
1833 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1835 if (NILP (force))
1836 error ("Attempt to delete the sole visible or iconified frame");
1837 else
1838 error ("Attempt to delete the only frame");
1841 XSETFRAME (frame, f);
1843 /* Softly delete all frames with this frame as their parent frame or
1844 as their `delete-before' frame parameter value. */
1845 FOR_EACH_FRAME (frames, frame1)
1846 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
1847 /* Process `delete-before' parameter iff FRAME is not a child
1848 frame. This avoids that we enter an infinite chain of mixed
1849 dependencies. */
1850 || (nochild
1851 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
1852 delete_frame (frame1, Qnil);
1854 /* Does this frame have a minibuffer, and is it the surrogate
1855 minibuffer for any other frame? */
1856 if (FRAME_HAS_MINIBUF_P (f))
1858 FOR_EACH_FRAME (frames, frame1)
1860 Lisp_Object fminiw;
1862 if (EQ (frame1, frame))
1863 continue;
1865 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
1867 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1869 /* If we MUST delete this frame, delete the other first.
1870 But do this only if FORCE equals `noelisp'. */
1871 if (EQ (force, Qnoelisp))
1872 delete_frame (frame1, Qnoelisp);
1873 else
1874 error ("Attempt to delete a surrogate minibuffer frame");
1879 is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
1881 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1882 frame is a tooltip. FORCE is set to `noelisp' when handling
1883 a disconnect from the terminal, so we don't dare call Lisp
1884 code. */
1885 if (NILP (Vrun_hooks) || is_tooltip_frame)
1887 else if (EQ (force, Qnoelisp))
1888 pending_funcalls
1889 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1890 pending_funcalls);
1891 else
1893 #ifdef HAVE_X_WINDOWS
1894 /* Also, save clipboard to the clipboard manager. */
1895 x_clipboard_manager_save_frame (frame);
1896 #endif
1898 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1901 /* delete_frame_functions may have deleted any frame, including this
1902 one. */
1903 if (!FRAME_LIVE_P (f))
1904 return Qnil;
1905 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1907 if (NILP (force))
1908 error ("Attempt to delete the sole visible or iconified frame");
1909 else
1910 error ("Attempt to delete the only frame");
1913 /* At this point, we are committed to deleting the frame.
1914 There is no more chance for errors to prevent it. */
1915 minibuffer_selected = EQ (minibuf_window, selected_window);
1916 sf = SELECTED_FRAME ();
1917 /* Don't let the frame remain selected. */
1918 if (f == sf)
1920 Lisp_Object tail;
1921 eassume (CONSP (Vframe_list));
1923 /* Look for another visible frame on the same terminal.
1924 Do not call next_frame here because it may loop forever.
1925 See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1926 FOR_EACH_FRAME (tail, frame1)
1927 if (!EQ (frame, frame1)
1928 && NILP (Fframe_parameter (frame1, Qtooltip))
1929 && (FRAME_TERMINAL (XFRAME (frame))
1930 == FRAME_TERMINAL (XFRAME (frame1)))
1931 && FRAME_VISIBLE_P (XFRAME (frame1)))
1932 break;
1934 /* If there is none, find *some* other frame. */
1935 if (NILP (frame1) || EQ (frame1, frame))
1937 FOR_EACH_FRAME (tail, frame1)
1939 if (!EQ (frame, frame1)
1940 && FRAME_LIVE_P (XFRAME (frame1))
1941 && NILP (Fframe_parameter (frame1, Qtooltip)))
1943 /* Do not change a text terminal's top-frame. */
1944 struct frame *f1 = XFRAME (frame1);
1945 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1947 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1948 if (!EQ (top_frame, frame))
1949 frame1 = top_frame;
1951 break;
1955 #ifdef NS_IMPL_COCOA
1956 else
1957 /* Under NS, there is no system mechanism for choosing a new
1958 window to get focus -- it is left to application code.
1959 So the portion of THIS application interfacing with NS
1960 needs to know about it. We call Fraise_frame, but the
1961 purpose is really to transfer focus. */
1962 Fraise_frame (frame1);
1963 #endif
1965 do_switch_frame (frame1, 0, 1, Qnil);
1966 sf = SELECTED_FRAME ();
1969 /* Don't allow minibuf_window to remain on a deleted frame. */
1970 check_minibuf_window (frame, minibuffer_selected);
1972 /* Don't let echo_area_window to remain on a deleted frame. */
1973 if (EQ (f->minibuffer_window, echo_area_window))
1974 echo_area_window = sf->minibuffer_window;
1976 /* Clear any X selections for this frame. */
1977 #ifdef HAVE_X_WINDOWS
1978 if (FRAME_X_P (f))
1979 x_clear_frame_selections (f);
1980 #endif
1982 /* Free glyphs.
1983 This function must be called before the window tree of the
1984 frame is deleted because windows contain dynamically allocated
1985 memory. */
1986 free_glyphs (f);
1988 #ifdef HAVE_WINDOW_SYSTEM
1989 /* Give chance to each font driver to free a frame specific data. */
1990 font_update_drivers (f, Qnil);
1991 #endif
1993 /* Mark all the windows that used to be on FRAME as deleted, and then
1994 remove the reference to them. */
1995 delete_all_child_windows (f->root_window);
1996 fset_root_window (f, Qnil);
1998 Vframe_list = Fdelq (frame, Vframe_list);
1999 SET_FRAME_VISIBLE (f, 0);
2001 /* Allow the vector of menu bar contents to be freed in the next
2002 garbage collection. The frame object itself may not be garbage
2003 collected until much later, because recent_keys and other data
2004 structures can still refer to it. */
2005 fset_menu_bar_vector (f, Qnil);
2007 /* If FRAME's buffer lists contains killed
2008 buffers, this helps GC to reclaim them. */
2009 fset_buffer_list (f, Qnil);
2010 fset_buried_buffer_list (f, Qnil);
2012 free_font_driver_list (f);
2013 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
2014 xfree (f->namebuf);
2015 #endif
2016 xfree (f->decode_mode_spec_buffer);
2017 xfree (FRAME_INSERT_COST (f));
2018 xfree (FRAME_DELETEN_COST (f));
2019 xfree (FRAME_INSERTN_COST (f));
2020 xfree (FRAME_DELETE_COST (f));
2022 /* Since some events are handled at the interrupt level, we may get
2023 an event for f at any time; if we zero out the frame's terminal
2024 now, then we may trip up the event-handling code. Instead, we'll
2025 promise that the terminal of the frame must be valid until we
2026 have called the window-system-dependent frame destruction
2027 routine. */
2029 struct terminal *terminal;
2030 block_input ();
2031 if (FRAME_TERMINAL (f)->delete_frame_hook)
2032 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
2033 terminal = FRAME_TERMINAL (f);
2034 f->output_data.nothing = 0;
2035 f->terminal = 0; /* Now the frame is dead. */
2036 unblock_input ();
2038 /* If needed, delete the terminal that this frame was on.
2039 (This must be done after the frame is killed.) */
2040 terminal->reference_count--;
2041 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
2042 /* FIXME: Deleting the terminal crashes emacs because of a GTK
2043 bug.
2044 https://lists.gnu.org/r/emacs-devel/2011-10/msg00363.html */
2046 /* Since a similar behavior was observed on the Lucid and Motif
2047 builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now
2048 don't delete the terminal for these builds either. */
2049 if (terminal->reference_count == 0 && terminal->type == output_x_window)
2050 terminal->reference_count = 1;
2051 #endif /* USE_X_TOOLKIT || USE_GTK */
2052 if (terminal->reference_count == 0)
2054 Lisp_Object tmp;
2055 XSETTERMINAL (tmp, terminal);
2057 kb = NULL;
2058 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
2060 else
2061 kb = terminal->kboard;
2064 /* If we've deleted the last_nonminibuf_frame, then try to find
2065 another one. */
2066 if (f == last_nonminibuf_frame)
2068 last_nonminibuf_frame = 0;
2070 FOR_EACH_FRAME (frames, frame1)
2072 struct frame *f1 = XFRAME (frame1);
2074 if (!FRAME_MINIBUF_ONLY_P (f1))
2076 last_nonminibuf_frame = f1;
2077 break;
2082 /* If there's no other frame on the same kboard, get out of
2083 single-kboard state if we're in it for this kboard. */
2084 if (kb != NULL)
2086 /* Some frame we found on the same kboard, or nil if there are none. */
2087 Lisp_Object frame_on_same_kboard = Qnil;
2089 FOR_EACH_FRAME (frames, frame1)
2090 if (kb == FRAME_KBOARD (XFRAME (frame1)))
2091 frame_on_same_kboard = frame1;
2093 if (NILP (frame_on_same_kboard))
2094 not_single_kboard_state (kb);
2098 /* If we've deleted this keyboard's default_minibuffer_frame, try to
2099 find another one. Prefer minibuffer-only frames, but also notice
2100 frames with other windows. */
2101 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
2103 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
2104 Lisp_Object frame_with_minibuf = Qnil;
2105 /* Some frame we found on the same kboard, or nil if there are none. */
2106 Lisp_Object frame_on_same_kboard = Qnil;
2108 FOR_EACH_FRAME (frames, frame1)
2110 struct frame *f1 = XFRAME (frame1);
2112 /* Consider only frames on the same kboard
2113 and only those with minibuffers. */
2114 if (kb == FRAME_KBOARD (f1)
2115 && FRAME_HAS_MINIBUF_P (f1))
2117 frame_with_minibuf = frame1;
2118 if (FRAME_MINIBUF_ONLY_P (f1))
2119 break;
2122 if (kb == FRAME_KBOARD (f1))
2123 frame_on_same_kboard = frame1;
2126 if (!NILP (frame_on_same_kboard))
2128 /* We know that there must be some frame with a minibuffer out
2129 there. If this were not true, all of the frames present
2130 would have to be minibufferless, which implies that at some
2131 point their minibuffer frames must have been deleted, but
2132 that is prohibited at the top; you can't delete surrogate
2133 minibuffer frames. */
2134 if (NILP (frame_with_minibuf))
2135 emacs_abort ();
2137 kset_default_minibuffer_frame (kb, frame_with_minibuf);
2139 else
2140 /* No frames left on this kboard--say no minibuffer either. */
2141 kset_default_minibuffer_frame (kb, Qnil);
2144 /* Cause frame titles to update--necessary if we now have just one frame. */
2145 if (!is_tooltip_frame)
2146 update_mode_lines = 15;
2148 return Qnil;
2151 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
2152 doc: /* Delete FRAME, permanently eliminating it from use.
2153 FRAME must be a live frame and defaults to the selected one.
2155 A frame may not be deleted if its minibuffer serves as surrogate
2156 minibuffer for another frame. Normally, you may not delete a frame if
2157 all other frames are invisible, but if the second optional argument
2158 FORCE is non-nil, you may do so.
2160 This function runs `delete-frame-functions' before actually
2161 deleting the frame, unless the frame is a tooltip.
2162 The functions are run with one argument, the frame to be deleted. */)
2163 (Lisp_Object frame, Lisp_Object force)
2165 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
2168 #ifdef HAVE_WINDOW_SYSTEM
2170 * frame_internal_border_part:
2172 * Return part of internal border the coordinates X and Y relative to
2173 * frame F are on. Return nil if the coordinates are not on the
2174 * internal border of F.
2176 * Return one of INTERNAL_BORDER_LEFT_EDGE, INTERNAL_BORDER_TOP_EDGE,
2177 * INTERNAL_BORDER_RIGHT_EDGE or INTERNAL_BORDER_BOTTOM_EDGE when the
2178 * mouse cursor is on the corresponding border with an offset of at
2179 * least one canonical character height from that border's edges.
2181 * If no border part could be found this way, return one of
2182 * INTERNAL_BORDER_TOP_LEFT_CORNER, INTERNAL_BORDER_TOP_RIGHT_CORNER,
2183 * INTERNAL_BORDER_BOTTOM_LEFT_CORNER or
2184 * INTERNAL_BORDER_BOTTOM_RIGHT_CORNER to indicate that the mouse is in
2185 * one of the corresponding corners. This means that for very small
2186 * frames an `edge' return value is preferred.
2188 enum internal_border_part
2189 frame_internal_border_part (struct frame *f, int x, int y)
2191 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
2192 int offset = FRAME_LINE_HEIGHT (f);
2193 int width = FRAME_PIXEL_WIDTH (f);
2194 int height = FRAME_PIXEL_HEIGHT (f);
2195 enum internal_border_part part = INTERNAL_BORDER_NONE;
2197 if (offset < border)
2198 /* For very wide borders make offset at least as large as
2199 border. */
2200 offset = border;
2202 if (offset < x && x < width - offset)
2203 /* Top or bottom border. */
2205 if (0 <= y && y <= border)
2206 part = INTERNAL_BORDER_TOP_EDGE;
2207 else if (height - border <= y && y <= height)
2208 part = INTERNAL_BORDER_BOTTOM_EDGE;
2210 else if (offset < y && y < height - offset)
2211 /* Left or right border. */
2213 if (0 <= x && x <= border)
2214 part = INTERNAL_BORDER_LEFT_EDGE;
2215 else if (width - border <= x && x <= width)
2216 part = INTERNAL_BORDER_RIGHT_EDGE;
2218 else
2220 /* An edge. */
2221 int half_width = width / 2;
2222 int half_height = height / 2;
2224 if (0 <= x && x <= border)
2226 /* A left edge. */
2227 if (0 <= y && y <= half_height)
2228 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2229 else if (half_height < y && y <= height)
2230 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2232 else if (width - border <= x && x <= width)
2234 /* A right edge. */
2235 if (0 <= y && y <= half_height)
2236 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2237 else if (half_height < y && y <= height)
2238 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2240 else if (0 <= y && y <= border)
2242 /* A top edge. */
2243 if (0 <= x && x <= half_width)
2244 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2245 else if (half_width < x && x <= width)
2246 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2248 else if (height - border <= y && y <= height)
2250 /* A bottom edge. */
2251 if (0 <= x && x <= half_width)
2252 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2253 else if (half_width < x && x <= width)
2254 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2258 return part;
2260 #endif
2262 /* Return mouse position in character cell units. */
2264 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
2265 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2266 The position is given in canonical character cells, where (0, 0) is the
2267 upper-left corner of the frame, X is the horizontal offset, and Y is the
2268 vertical offset, measured in units of the frame's default character size.
2269 If Emacs is running on a mouseless terminal or hasn't been programmed
2270 to read the mouse position, it returns the selected frame for FRAME
2271 and nil for X and Y.
2272 If `mouse-position-function' is non-nil, `mouse-position' calls it,
2273 passing the normal return value to that function as an argument,
2274 and returns whatever that function returns. */)
2275 (void)
2277 struct frame *f;
2278 Lisp_Object lispy_dummy;
2279 Lisp_Object x, y, retval;
2281 f = SELECTED_FRAME ();
2282 x = y = Qnil;
2284 /* It's okay for the hook to refrain from storing anything. */
2285 if (FRAME_TERMINAL (f)->mouse_position_hook)
2287 enum scroll_bar_part party_dummy;
2288 Time time_dummy;
2289 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2290 &lispy_dummy, &party_dummy,
2291 &x, &y,
2292 &time_dummy);
2295 if (! NILP (x))
2297 int col = XINT (x);
2298 int row = XINT (y);
2299 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
2300 XSETINT (x, col);
2301 XSETINT (y, row);
2303 XSETFRAME (lispy_dummy, f);
2304 retval = Fcons (lispy_dummy, Fcons (x, y));
2305 if (!NILP (Vmouse_position_function))
2306 retval = call1 (Vmouse_position_function, retval);
2307 return retval;
2310 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
2311 Smouse_pixel_position, 0, 0, 0,
2312 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2313 The position is given in pixel units, where (0, 0) is the
2314 upper-left corner of the frame, X is the horizontal offset, and Y is
2315 the vertical offset.
2316 If Emacs is running on a mouseless terminal or hasn't been programmed
2317 to read the mouse position, it returns the selected frame for FRAME
2318 and nil for X and Y. */)
2319 (void)
2321 struct frame *f;
2322 Lisp_Object lispy_dummy;
2323 Lisp_Object x, y, retval;
2325 f = SELECTED_FRAME ();
2326 x = y = Qnil;
2328 /* It's okay for the hook to refrain from storing anything. */
2329 if (FRAME_TERMINAL (f)->mouse_position_hook)
2331 enum scroll_bar_part party_dummy;
2332 Time time_dummy;
2333 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2334 &lispy_dummy, &party_dummy,
2335 &x, &y,
2336 &time_dummy);
2339 XSETFRAME (lispy_dummy, f);
2340 retval = Fcons (lispy_dummy, Fcons (x, y));
2341 if (!NILP (Vmouse_position_function))
2342 retval = call1 (Vmouse_position_function, retval);
2343 return retval;
2346 #ifdef HAVE_WINDOW_SYSTEM
2348 /* On frame F, convert character coordinates X and Y to pixel
2349 coordinates *PIX_X and *PIX_Y. */
2351 static void
2352 frame_char_to_pixel_position (struct frame *f, int x, int y,
2353 int *pix_x, int *pix_y)
2355 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
2356 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
2358 if (*pix_x < 0)
2359 *pix_x = 0;
2360 if (*pix_x > FRAME_PIXEL_WIDTH (f))
2361 *pix_x = FRAME_PIXEL_WIDTH (f);
2363 if (*pix_y < 0)
2364 *pix_y = 0;
2365 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
2366 *pix_y = FRAME_PIXEL_HEIGHT (f);
2369 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
2371 static void
2372 frame_set_mouse_position (struct frame *f, int x, int y)
2374 int pix_x, pix_y;
2376 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
2377 frame_set_mouse_pixel_position (f, pix_x, pix_y);
2380 #endif /* HAVE_WINDOW_SYSTEM */
2382 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
2383 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
2384 Coordinates are relative to the frame, not a window,
2385 so the coordinates of the top left character in the frame
2386 may be nonzero due to left-hand scroll bars or the menu bar.
2388 The position is given in canonical character cells, where (0, 0) is
2389 the upper-left corner of the frame, X is the horizontal offset, and
2390 Y is the vertical offset, measured in units of the frame's default
2391 character size.
2393 This function is a no-op for an X frame that is not visible.
2394 If you have just created a frame, you must wait for it to become visible
2395 before calling this function on it, like this.
2396 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2397 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2399 CHECK_LIVE_FRAME (frame);
2400 CHECK_TYPE_RANGED_INTEGER (int, x);
2401 CHECK_TYPE_RANGED_INTEGER (int, y);
2403 /* I think this should be done with a hook. */
2404 #ifdef HAVE_WINDOW_SYSTEM
2405 if (FRAME_WINDOW_P (XFRAME (frame)))
2406 /* Warping the mouse will cause enternotify and focus events. */
2407 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
2408 #else
2409 #if defined (MSDOS)
2410 if (FRAME_MSDOS_P (XFRAME (frame)))
2412 Fselect_frame (frame, Qnil);
2413 mouse_moveto (XINT (x), XINT (y));
2415 #else
2416 #ifdef HAVE_GPM
2418 Fselect_frame (frame, Qnil);
2419 term_mouse_moveto (XINT (x), XINT (y));
2421 #endif
2422 #endif
2423 #endif
2425 return Qnil;
2428 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
2429 Sset_mouse_pixel_position, 3, 3, 0,
2430 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
2431 The position is given in pixels, where (0, 0) is the upper-left corner
2432 of the frame, X is the horizontal offset, and Y is the vertical offset.
2434 Note, this is a no-op for an X frame that is not visible.
2435 If you have just created a frame, you must wait for it to become visible
2436 before calling this function on it, like this.
2437 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2438 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2440 CHECK_LIVE_FRAME (frame);
2441 CHECK_TYPE_RANGED_INTEGER (int, x);
2442 CHECK_TYPE_RANGED_INTEGER (int, y);
2444 /* I think this should be done with a hook. */
2445 #ifdef HAVE_WINDOW_SYSTEM
2446 if (FRAME_WINDOW_P (XFRAME (frame)))
2447 /* Warping the mouse will cause enternotify and focus events. */
2448 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
2449 #else
2450 #if defined (MSDOS)
2451 if (FRAME_MSDOS_P (XFRAME (frame)))
2453 Fselect_frame (frame, Qnil);
2454 mouse_moveto (XINT (x), XINT (y));
2456 #else
2457 #ifdef HAVE_GPM
2459 Fselect_frame (frame, Qnil);
2460 term_mouse_moveto (XINT (x), XINT (y));
2462 #endif
2463 #endif
2464 #endif
2466 return Qnil;
2469 static void make_frame_visible_1 (Lisp_Object);
2471 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
2472 0, 1, "",
2473 doc: /* Make the frame FRAME visible (assuming it is an X window).
2474 If omitted, FRAME defaults to the currently selected frame. */)
2475 (Lisp_Object frame)
2477 struct frame *f = decode_live_frame (frame);
2479 /* I think this should be done with a hook. */
2480 #ifdef HAVE_WINDOW_SYSTEM
2481 if (FRAME_WINDOW_P (f))
2482 x_make_frame_visible (f);
2483 #endif
2485 make_frame_visible_1 (f->root_window);
2487 /* Make menu bar update for the Buffers and Frames menus. */
2488 /* windows_or_buffers_changed = 15; FIXME: Why? */
2490 XSETFRAME (frame, f);
2491 return frame;
2494 /* Update the display_time slot of the buffers shown in WINDOW
2495 and all its descendants. */
2497 static void
2498 make_frame_visible_1 (Lisp_Object window)
2500 struct window *w;
2502 for (; !NILP (window); window = w->next)
2504 w = XWINDOW (window);
2505 if (WINDOWP (w->contents))
2506 make_frame_visible_1 (w->contents);
2507 else
2508 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2512 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2513 0, 2, "",
2514 doc: /* Make the frame FRAME invisible.
2515 If omitted, FRAME defaults to the currently selected frame.
2516 On graphical displays, invisible frames are not updated and are
2517 usually not displayed at all, even in a window system's \"taskbar\".
2519 Normally you may not make FRAME invisible if all other frames are invisible,
2520 but if the second optional argument FORCE is non-nil, you may do so.
2522 This function has no effect on text terminal frames. Such frames are
2523 always considered visible, whether or not they are currently being
2524 displayed in the terminal. */)
2525 (Lisp_Object frame, Lisp_Object force)
2527 struct frame *f = decode_live_frame (frame);
2529 if (NILP (force) && !other_frames (f, true, false))
2530 error ("Attempt to make invisible the sole visible or iconified frame");
2532 /* Don't allow minibuf_window to remain on an invisible frame. */
2533 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2535 /* I think this should be done with a hook. */
2536 #ifdef HAVE_WINDOW_SYSTEM
2537 if (FRAME_WINDOW_P (f))
2538 x_make_frame_invisible (f);
2539 #endif
2541 /* Make menu bar update for the Buffers and Frames menus. */
2542 windows_or_buffers_changed = 16;
2544 return Qnil;
2547 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2548 0, 1, "",
2549 doc: /* Make the frame FRAME into an icon.
2550 If omitted, FRAME defaults to the currently selected frame.
2552 If FRAME is a child frame, consult the variable `iconify-child-frame'
2553 for how to proceed. */)
2554 (Lisp_Object frame)
2556 struct frame *f = decode_live_frame (frame);
2557 #ifdef HAVE_WINDOW_SYSTEM
2558 Lisp_Object parent = f->parent_frame;
2560 if (!NILP (parent))
2562 if (NILP (iconify_child_frame))
2563 /* Do nothing. */
2564 return Qnil;
2565 else if (EQ (iconify_child_frame, Qiconify_top_level))
2567 /* Iconify top level frame instead (the default). */
2568 Ficonify_frame (parent);
2569 return Qnil;
2571 else if (EQ (iconify_child_frame, Qmake_invisible))
2573 /* Make frame invisible instead. */
2574 Fmake_frame_invisible (frame, Qnil);
2575 return Qnil;
2578 #endif /* HAVE_WINDOW_SYSTEM */
2580 /* Don't allow minibuf_window to remain on an iconified frame. */
2581 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2583 /* I think this should be done with a hook. */
2584 if (FRAME_WINDOW_P (f))
2586 #ifdef HAVE_WINDOW_SYSTEM
2587 x_iconify_frame (f);
2588 #endif
2591 return Qnil;
2594 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2595 1, 1, 0,
2596 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2597 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2598 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2599 On graphical displays, invisible frames are not updated and are
2600 usually not displayed at all, even in a window system's \"taskbar\".
2602 If FRAME is a text terminal frame, this always returns t.
2603 Such frames are always considered visible, whether or not they are
2604 currently being displayed on the terminal. */)
2605 (Lisp_Object frame)
2607 CHECK_LIVE_FRAME (frame);
2609 if (FRAME_VISIBLE_P (XFRAME (frame)))
2610 return Qt;
2611 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2612 return Qicon;
2613 return Qnil;
2616 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2617 0, 0, 0,
2618 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2619 (void)
2621 Lisp_Object tail, frame, value = Qnil;
2623 FOR_EACH_FRAME (tail, frame)
2624 if (FRAME_VISIBLE_P (XFRAME (frame)))
2625 value = Fcons (frame, value);
2627 return value;
2631 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2632 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2633 If FRAME is invisible or iconified, make it visible.
2634 If you don't specify a frame, the selected frame is used.
2635 If Emacs is displaying on an ordinary terminal or some other device which
2636 doesn't support multiple overlapping frames, this function selects FRAME. */)
2637 (Lisp_Object frame)
2639 struct frame *f = decode_live_frame (frame);
2641 XSETFRAME (frame, f);
2643 if (FRAME_TERMCAP_P (f))
2644 /* On a text terminal select FRAME. */
2645 Fselect_frame (frame, Qnil);
2646 else
2647 /* Do like the documentation says. */
2648 Fmake_frame_visible (frame);
2650 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2651 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2653 return Qnil;
2656 /* Should we have a corresponding function called Flower_Power? */
2657 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2658 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2659 If you don't specify a frame, the selected frame is used.
2660 If Emacs is displaying on an ordinary terminal or some other device which
2661 doesn't support multiple overlapping frames, this function does nothing. */)
2662 (Lisp_Object frame)
2664 struct frame *f = decode_live_frame (frame);
2666 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2667 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2669 return Qnil;
2673 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2674 1, 2, 0,
2675 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2676 In other words, switch-frame events caused by events in FRAME will
2677 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2678 FOCUS-FRAME after reading an event typed at FRAME.
2680 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2681 frame again receives its own keystrokes.
2683 Focus redirection is useful for temporarily redirecting keystrokes to
2684 a surrogate minibuffer frame when a frame doesn't have its own
2685 minibuffer window.
2687 A frame's focus redirection can be changed by `select-frame'. If frame
2688 FOO is selected, and then a different frame BAR is selected, any
2689 frames redirecting their focus to FOO are shifted to redirect their
2690 focus to BAR. This allows focus redirection to work properly when the
2691 user switches from one frame to another using `select-window'.
2693 This means that a frame whose focus is redirected to itself is treated
2694 differently from a frame whose focus is redirected to nil; the former
2695 is affected by `select-frame', while the latter is not.
2697 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2698 (Lisp_Object frame, Lisp_Object focus_frame)
2700 /* Note that we don't check for a live frame here. It's reasonable
2701 to redirect the focus of a frame you're about to delete, if you
2702 know what other frame should receive those keystrokes. */
2703 struct frame *f = decode_any_frame (frame);
2705 if (! NILP (focus_frame))
2706 CHECK_LIVE_FRAME (focus_frame);
2708 fset_focus_frame (f, focus_frame);
2710 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2711 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2713 return Qnil;
2717 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2718 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2719 If FRAME is omitted or nil, the selected frame is used.
2720 Return nil if FRAME's focus is not redirected.
2721 See `redirect-frame-focus'. */)
2722 (Lisp_Object frame)
2724 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2727 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 2, 0,
2728 doc: /* Set the input focus to FRAME.
2729 FRAME nil means use the selected frame. Optional argument NOACTIVATE
2730 means do not activate FRAME.
2732 If there is no window system support, this function does nothing. */)
2733 (Lisp_Object frame, Lisp_Object noactivate)
2735 #ifdef HAVE_WINDOW_SYSTEM
2736 x_focus_frame (decode_window_system_frame (frame), !NILP (noactivate));
2737 #endif
2738 return Qnil;
2741 DEFUN ("frame-after-make-frame",
2742 Fframe_after_make_frame,
2743 Sframe_after_make_frame, 2, 2, 0,
2744 doc: /* Mark FRAME as made.
2745 FRAME nil means use the selected frame. Second argument MADE non-nil
2746 means functions on `window-configuration-change-hook' are called
2747 whenever the window configuration of FRAME changes. MADE nil means
2748 these functions are not called.
2750 This function is currently called by `make-frame' only and should be
2751 otherwise used with utter care to avoid that running functions on
2752 `window-configuration-change-hook' is impeded forever. */)
2753 (Lisp_Object frame, Lisp_Object made)
2755 struct frame *f = decode_live_frame (frame);
2756 f->after_make_frame = !NILP (made);
2757 f->inhibit_horizontal_resize = false;
2758 f->inhibit_vertical_resize = false;
2759 return made;
2763 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2765 void
2766 frames_discard_buffer (Lisp_Object buffer)
2768 Lisp_Object frame, tail;
2770 FOR_EACH_FRAME (tail, frame)
2772 fset_buffer_list
2773 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2774 fset_buried_buffer_list
2775 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2779 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2780 If the alist already has an element for PROP, we change it. */
2782 void
2783 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2785 register Lisp_Object tem;
2787 tem = Fassq (prop, *alistptr);
2788 if (EQ (tem, Qnil))
2789 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2790 else
2791 Fsetcdr (tem, val);
2794 static int
2795 frame_name_fnn_p (char *str, ptrdiff_t len)
2797 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2799 char *p = str + 2;
2800 while ('0' <= *p && *p <= '9')
2801 p++;
2802 if (p == str + len)
2803 return 1;
2805 return 0;
2808 /* Set the name of the terminal frame. Also used by MSDOS frames.
2809 Modeled after x_set_name which is used for WINDOW frames. */
2811 static void
2812 set_term_frame_name (struct frame *f, Lisp_Object name)
2814 f->explicit_name = ! NILP (name);
2816 /* If NAME is nil, set the name to F<num>. */
2817 if (NILP (name))
2819 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2821 /* Check for no change needed in this very common case
2822 before we do any consing. */
2823 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2824 return;
2826 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2828 else
2830 CHECK_STRING (name);
2832 /* Don't change the name if it's already NAME. */
2833 if (! NILP (Fstring_equal (name, f->name)))
2834 return;
2836 /* Don't allow the user to set the frame name to F<num>, so it
2837 doesn't clash with the names we generate for terminal frames. */
2838 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2839 error ("Frame names of the form F<num> are usurped by Emacs");
2842 fset_name (f, name);
2843 update_mode_lines = 16;
2846 void
2847 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2849 register Lisp_Object old_alist_elt;
2851 if (EQ (prop, Qminibuffer))
2853 if (WINDOWP (val))
2855 if (!MINI_WINDOW_P (XWINDOW (val)))
2856 error ("The `minibuffer' parameter does not specify a valid minibuffer window");
2857 else if (FRAME_MINIBUF_ONLY_P (f))
2859 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2860 val = Qonly;
2861 else
2862 error ("Can't change the minibuffer window of a minibuffer-only frame");
2864 else if (FRAME_HAS_MINIBUF_P (f))
2866 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2867 val = Qt;
2868 else
2869 error ("Can't change the minibuffer window of a frame with its own minibuffer");
2871 else
2872 /* Store the chosen minibuffer window. */
2873 fset_minibuffer_window (f, val);
2875 else
2877 Lisp_Object old_val = Fcdr (Fassq (Qminibuffer, f->param_alist));
2879 if (!NILP (old_val))
2881 if (WINDOWP (old_val) && NILP (val))
2882 /* Don't change the value for a minibuffer-less frame if
2883 only nil was specified as new value. */
2884 val = old_val;
2885 else if (!EQ (old_val, val))
2886 error ("Can't change the `minibuffer' parameter of this frame");
2891 /* Check each parent-frame and delete-before parameter for a
2892 circular dependency. Do not check between parameters, so you can
2893 still create circular dependencies with different properties, for
2894 example a chain of frames F1->F2->...Fn such that F1 is an ancestor
2895 frame of Fn and thus cannot be deleted before Fn and a second chain
2896 Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
2897 else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
2899 Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
2901 if (!EQ (oldval, val) && !NILP (val))
2903 Lisp_Object frame;
2904 Lisp_Object frame1 = val;
2906 if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
2907 error ("Invalid `%s' frame parameter",
2908 SSDATA (SYMBOL_NAME (prop)));
2910 XSETFRAME (frame, f);
2912 while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
2913 if (EQ (frame1, frame))
2914 error ("Circular specification of `%s' frame parameter",
2915 SSDATA (SYMBOL_NAME (prop)));
2916 else
2917 frame1 = get_frame_param (XFRAME (frame1), prop);
2921 /* The buffer-list parameters are stored in a special place and not
2922 in the alist. All buffers must be live. */
2923 else if (EQ (prop, Qbuffer_list))
2925 Lisp_Object list = Qnil;
2926 for (; CONSP (val); val = XCDR (val))
2927 if (!NILP (Fbuffer_live_p (XCAR (val))))
2928 list = Fcons (XCAR (val), list);
2929 fset_buffer_list (f, Fnreverse (list));
2930 return;
2932 else if (EQ (prop, Qburied_buffer_list))
2934 Lisp_Object list = Qnil;
2935 for (; CONSP (val); val = XCDR (val))
2936 if (!NILP (Fbuffer_live_p (XCAR (val))))
2937 list = Fcons (XCAR (val), list);
2938 fset_buried_buffer_list (f, Fnreverse (list));
2939 return;
2942 /* The tty color needed to be set before the frame's parameter
2943 alist was updated with the new value. This is not true any more,
2944 but we still do this test early on. */
2945 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2946 && f == FRAME_TTY (f)->previous_frame)
2947 /* Force redisplay of this tty. */
2948 FRAME_TTY (f)->previous_frame = NULL;
2950 /* Update the frame parameter alist. */
2951 old_alist_elt = Fassq (prop, f->param_alist);
2952 if (EQ (old_alist_elt, Qnil))
2953 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2954 else
2955 Fsetcdr (old_alist_elt, val);
2957 /* Update some other special parameters in their special places
2958 in addition to the alist. */
2960 if (EQ (prop, Qbuffer_predicate))
2961 fset_buffer_predicate (f, val);
2963 if (! FRAME_WINDOW_P (f))
2965 if (EQ (prop, Qmenu_bar_lines))
2966 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2967 else if (EQ (prop, Qname))
2968 set_term_frame_name (f, val);
2972 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2973 is not an unspecified foreground or background color. */
2975 static Lisp_Object
2976 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
2978 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
2979 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
2980 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
2981 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
2984 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
2985 doc: /* Return the parameters-alist of frame FRAME.
2986 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2987 The meaningful PARMs depend on the kind of frame.
2988 If FRAME is omitted or nil, return information on the currently selected frame. */)
2989 (Lisp_Object frame)
2991 Lisp_Object alist;
2992 struct frame *f = decode_any_frame (frame);
2993 int height, width;
2995 if (!FRAME_LIVE_P (f))
2996 return Qnil;
2998 alist = Fcopy_alist (f->param_alist);
3000 if (!FRAME_WINDOW_P (f))
3002 Lisp_Object elt;
3004 /* If the frame's parameter alist says the colors are
3005 unspecified and reversed, take the frame's background pixel
3006 for foreground and vice versa. */
3007 elt = Fassq (Qforeground_color, alist);
3008 if (CONSP (elt) && STRINGP (XCDR (elt)))
3010 elt = frame_unspecified_color (f, XCDR (elt));
3011 if (!NILP (elt))
3012 store_in_alist (&alist, Qforeground_color, elt);
3014 else
3015 store_in_alist (&alist, Qforeground_color,
3016 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
3017 elt = Fassq (Qbackground_color, alist);
3018 if (CONSP (elt) && STRINGP (XCDR (elt)))
3020 elt = frame_unspecified_color (f, XCDR (elt));
3021 if (!NILP (elt))
3022 store_in_alist (&alist, Qbackground_color, elt);
3024 else
3025 store_in_alist (&alist, Qbackground_color,
3026 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
3027 store_in_alist (&alist, Qfont,
3028 build_string (FRAME_MSDOS_P (f)
3029 ? "ms-dos"
3030 : FRAME_W32_P (f) ? "w32term"
3031 :"tty"));
3033 store_in_alist (&alist, Qname, f->name);
3034 height = (f->new_height
3035 ? (f->new_pixelwise
3036 ? (f->new_height / FRAME_LINE_HEIGHT (f))
3037 : f->new_height)
3038 : FRAME_LINES (f));
3039 store_in_alist (&alist, Qheight, make_number (height));
3040 width = (f->new_width
3041 ? (f->new_pixelwise
3042 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
3043 : f->new_width)
3044 : FRAME_COLS (f));
3045 store_in_alist (&alist, Qwidth, make_number (width));
3046 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
3047 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
3048 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
3049 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
3051 /* I think this should be done with a hook. */
3052 #ifdef HAVE_WINDOW_SYSTEM
3053 if (FRAME_WINDOW_P (f))
3054 x_report_frame_params (f, &alist);
3055 else
3056 #endif
3058 /* This ought to be correct in f->param_alist for an X frame. */
3059 Lisp_Object lines;
3060 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
3061 store_in_alist (&alist, Qmenu_bar_lines, lines);
3064 return alist;
3068 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
3069 doc: /* Return FRAME's value for parameter PARAMETER.
3070 If FRAME is nil, describe the currently selected frame. */)
3071 (Lisp_Object frame, Lisp_Object parameter)
3073 struct frame *f = decode_any_frame (frame);
3074 Lisp_Object value = Qnil;
3076 CHECK_SYMBOL (parameter);
3078 XSETFRAME (frame, f);
3080 if (FRAME_LIVE_P (f))
3082 /* Avoid consing in frequent cases. */
3083 if (EQ (parameter, Qname))
3084 value = f->name;
3085 #ifdef HAVE_WINDOW_SYSTEM
3086 /* These are used by vertical motion commands. */
3087 else if (EQ (parameter, Qvertical_scroll_bars))
3088 value = (f->vertical_scroll_bar_type == vertical_scroll_bar_none
3089 ? Qnil
3090 : (f->vertical_scroll_bar_type == vertical_scroll_bar_left
3091 ? Qleft : Qright));
3092 else if (EQ (parameter, Qhorizontal_scroll_bars))
3093 value = f->horizontal_scroll_bars ? Qt : Qnil;
3094 else if (EQ (parameter, Qline_spacing) && f->extra_line_spacing == 0)
3095 /* If this is non-zero, we can't determine whether the user specified
3096 an integer or float value without looking through 'param_alist'. */
3097 value = make_number (0);
3098 else if (EQ (parameter, Qfont) && FRAME_X_P (f))
3099 value = FRAME_FONT (f)->props[FONT_NAME_INDEX];
3100 #endif /* HAVE_WINDOW_SYSTEM */
3101 #ifdef HAVE_X_WINDOWS
3102 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
3103 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
3104 #endif /* HAVE_X_WINDOWS */
3105 else if (EQ (parameter, Qbackground_color)
3106 || EQ (parameter, Qforeground_color))
3108 value = Fassq (parameter, f->param_alist);
3109 if (CONSP (value))
3111 value = XCDR (value);
3112 /* Fframe_parameters puts the actual fg/bg color names,
3113 even if f->param_alist says otherwise. This is
3114 important when param_alist's notion of colors is
3115 "unspecified". We need to do the same here. */
3116 if (STRINGP (value) && !FRAME_WINDOW_P (f))
3118 Lisp_Object tem = frame_unspecified_color (f, value);
3120 if (!NILP (tem))
3121 value = tem;
3124 else
3125 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3127 else if (EQ (parameter, Qdisplay_type)
3128 || EQ (parameter, Qbackground_mode))
3129 value = Fcdr (Fassq (parameter, f->param_alist));
3130 else
3131 /* FIXME: Avoid this code path at all (as well as code duplication)
3132 by sharing more code with Fframe_parameters. */
3133 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3136 return value;
3140 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
3141 Smodify_frame_parameters, 2, 2, 0,
3142 doc: /* Modify FRAME according to new values of its parameters in ALIST.
3143 If FRAME is nil, it defaults to the selected frame.
3144 ALIST is an alist of parameters to change and their new values.
3145 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
3146 Which PARMs are meaningful depends on the kind of frame.
3147 The meaningful parameters are acted upon, i.e. the frame is changed
3148 according to their new values, and are also stored in the frame's
3149 parameter list so that `frame-parameters' will return them.
3150 PARMs that are not meaningful are still stored in the frame's parameter
3151 list, but are otherwise ignored. */)
3152 (Lisp_Object frame, Lisp_Object alist)
3154 struct frame *f = decode_live_frame (frame);
3155 Lisp_Object prop, val;
3157 /* I think this should be done with a hook. */
3158 #ifdef HAVE_WINDOW_SYSTEM
3159 if (FRAME_WINDOW_P (f))
3160 x_set_frame_parameters (f, alist);
3161 else
3162 #endif
3163 #ifdef MSDOS
3164 if (FRAME_MSDOS_P (f))
3165 IT_set_frame_parameters (f, alist);
3166 else
3167 #endif
3170 EMACS_INT length = XFASTINT (Flength (alist));
3171 ptrdiff_t i;
3172 Lisp_Object *parms;
3173 Lisp_Object *values;
3174 USE_SAFE_ALLOCA;
3175 SAFE_ALLOCA_LISP (parms, 2 * length);
3176 values = parms + length;
3178 /* Extract parm names and values into those vectors. */
3180 for (i = 0; CONSP (alist); alist = XCDR (alist))
3182 Lisp_Object elt;
3184 elt = XCAR (alist);
3185 parms[i] = Fcar (elt);
3186 values[i] = Fcdr (elt);
3187 i++;
3190 /* Now process them in reverse of specified order. */
3191 while (--i >= 0)
3193 prop = parms[i];
3194 val = values[i];
3195 store_frame_param (f, prop, val);
3197 if (EQ (prop, Qforeground_color)
3198 || EQ (prop, Qbackground_color))
3199 update_face_from_frame_parameter (f, prop, val);
3202 SAFE_FREE ();
3204 return Qnil;
3207 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
3208 0, 1, 0,
3209 doc: /* Height in pixels of a line in the font in frame FRAME.
3210 If FRAME is omitted or nil, the selected frame is used.
3211 For a terminal frame, the value is always 1. */)
3212 (Lisp_Object frame)
3214 #ifdef HAVE_WINDOW_SYSTEM
3215 struct frame *f = decode_any_frame (frame);
3217 if (FRAME_WINDOW_P (f))
3218 return make_number (FRAME_LINE_HEIGHT (f));
3219 else
3220 #endif
3221 return make_number (1);
3225 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
3226 0, 1, 0,
3227 doc: /* Width in pixels of characters in the font in frame FRAME.
3228 If FRAME is omitted or nil, the selected frame is used.
3229 On a graphical screen, the width is the standard width of the default font.
3230 For a terminal screen, the value is always 1. */)
3231 (Lisp_Object frame)
3233 #ifdef HAVE_WINDOW_SYSTEM
3234 struct frame *f = decode_any_frame (frame);
3236 if (FRAME_WINDOW_P (f))
3237 return make_number (FRAME_COLUMN_WIDTH (f));
3238 else
3239 #endif
3240 return make_number (1);
3243 DEFUN ("frame-native-width", Fframe_native_width,
3244 Sframe_native_width, 0, 1, 0,
3245 doc: /* Return FRAME's native width in pixels.
3246 For a terminal frame, the result really gives the width in characters.
3247 If FRAME is omitted or nil, the selected frame is used. */)
3248 (Lisp_Object frame)
3250 struct frame *f = decode_any_frame (frame);
3252 #ifdef HAVE_WINDOW_SYSTEM
3253 if (FRAME_WINDOW_P (f))
3254 return make_number (FRAME_PIXEL_WIDTH (f));
3255 else
3256 #endif
3257 return make_number (FRAME_TOTAL_COLS (f));
3260 DEFUN ("frame-native-height", Fframe_native_height,
3261 Sframe_native_height, 0, 1, 0,
3262 doc: /* Return FRAME's native height in pixels.
3263 If FRAME is omitted or nil, the selected frame is used. The exact value
3264 of the result depends on the window-system and toolkit in use:
3266 In the Gtk+ and NS versions, it includes only any window (including the
3267 minibuffer or echo area), mode line, and header line. It does not
3268 include the tool bar or menu bar. With other graphical versions, it may
3269 also include the tool bar and the menu bar.
3271 For a text terminal, it includes the menu bar. In this case, the
3272 result is really in characters rather than pixels (i.e., is identical
3273 to `frame-height'). */)
3274 (Lisp_Object frame)
3276 struct frame *f = decode_any_frame (frame);
3278 #ifdef HAVE_WINDOW_SYSTEM
3279 if (FRAME_WINDOW_P (f))
3280 return make_number (FRAME_PIXEL_HEIGHT (f));
3281 else
3282 #endif
3283 return make_number (FRAME_TOTAL_LINES (f));
3286 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
3287 Stool_bar_pixel_width, 0, 1, 0,
3288 doc: /* Return width in pixels of FRAME's tool bar.
3289 The result is greater than zero only when the tool bar is on the left
3290 or right side of FRAME. If FRAME is omitted or nil, the selected frame
3291 is used. */)
3292 (Lisp_Object frame)
3294 #ifdef FRAME_TOOLBAR_WIDTH
3295 struct frame *f = decode_any_frame (frame);
3297 if (FRAME_WINDOW_P (f))
3298 return make_number (FRAME_TOOLBAR_WIDTH (f));
3299 #endif
3300 return make_number (0);
3303 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
3304 doc: /* Return width in columns of FRAME's text area. */)
3305 (Lisp_Object frame)
3307 return make_number (FRAME_COLS (decode_any_frame (frame)));
3310 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
3311 doc: /* Return height in lines of FRAME's text area. */)
3312 (Lisp_Object frame)
3314 return make_number (FRAME_LINES (decode_any_frame (frame)));
3317 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
3318 doc: /* Return number of total columns of FRAME. */)
3319 (Lisp_Object frame)
3321 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
3324 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
3325 doc: /* Return number of total lines of FRAME. */)
3326 (Lisp_Object frame)
3328 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
3331 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
3332 doc: /* Return text area width of FRAME in pixels. */)
3333 (Lisp_Object frame)
3335 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
3338 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
3339 doc: /* Return text area height of FRAME in pixels. */)
3340 (Lisp_Object frame)
3342 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
3345 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
3346 doc: /* Return scroll bar width of FRAME in pixels. */)
3347 (Lisp_Object frame)
3349 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
3352 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
3353 doc: /* Return scroll bar height of FRAME in pixels. */)
3354 (Lisp_Object frame)
3356 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
3359 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
3360 doc: /* Return fringe width of FRAME in pixels. */)
3361 (Lisp_Object frame)
3363 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
3366 DEFUN ("frame-internal-border-width", Fframe_internal_border_width, Sframe_internal_border_width, 0, 1, 0,
3367 doc: /* Return width of FRAME's internal border in pixels. */)
3368 (Lisp_Object frame)
3370 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
3373 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
3374 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
3375 (Lisp_Object frame)
3377 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
3380 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
3381 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
3382 (Lisp_Object frame)
3384 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
3387 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
3388 doc: /* Set text height of frame FRAME to HEIGHT lines.
3389 Optional third arg PRETEND non-nil means that redisplay should use
3390 HEIGHT lines but that the idea of the actual height of the frame should
3391 not be changed.
3393 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3394 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
3395 window managers may refuse to honor a HEIGHT that is not an integer
3396 multiple of the default frame font height. */)
3397 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
3399 struct frame *f = decode_live_frame (frame);
3400 int pixel_height;
3402 CHECK_TYPE_RANGED_INTEGER (int, height);
3404 pixel_height = (!NILP (pixelwise)
3405 ? XINT (height)
3406 : XINT (height) * FRAME_LINE_HEIGHT (f));
3407 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
3409 return Qnil;
3412 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
3413 doc: /* Set text width of frame FRAME to WIDTH columns.
3414 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
3415 columns but that the idea of the actual width of the frame should not
3416 be changed.
3418 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3419 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
3420 window managers may refuse to honor a WIDTH that is not an integer
3421 multiple of the default frame font width. */)
3422 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
3424 struct frame *f = decode_live_frame (frame);
3425 int pixel_width;
3427 CHECK_TYPE_RANGED_INTEGER (int, width);
3429 pixel_width = (!NILP (pixelwise)
3430 ? XINT (width)
3431 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3432 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
3434 return Qnil;
3437 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
3438 doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
3439 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
3440 When `frame-resize-pixelwise' is nil, some window managers may refuse to
3441 honor a WIDTH that is not an integer multiple of the default frame font
3442 width or a HEIGHT that is not an integer multiple of the default frame
3443 font height. */)
3444 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
3446 struct frame *f = decode_live_frame (frame);
3447 int pixel_width, pixel_height;
3449 CHECK_TYPE_RANGED_INTEGER (int, width);
3450 CHECK_TYPE_RANGED_INTEGER (int, height);
3452 pixel_width = (!NILP (pixelwise)
3453 ? XINT (width)
3454 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3455 pixel_height = (!NILP (pixelwise)
3456 ? XINT (height)
3457 : XINT (height) * FRAME_LINE_HEIGHT (f));
3458 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
3460 return Qnil;
3463 DEFUN ("frame-position", Fframe_position,
3464 Sframe_position, 0, 1, 0,
3465 doc: /* Return top left corner of FRAME in pixels.
3466 FRAME must be a live frame and defaults to the selected one. The return
3467 value is a cons (x, y) of the coordinates of the top left corner of
3468 FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
3469 display. */)
3470 (Lisp_Object frame)
3472 register struct frame *f = decode_live_frame (frame);
3474 return Fcons (make_number (f->left_pos), make_number (f->top_pos));
3477 DEFUN ("set-frame-position", Fset_frame_position,
3478 Sset_frame_position, 3, 3, 0,
3479 doc: /* Set position of FRAME to (X, Y).
3480 FRAME must be a live frame and defaults to the selected one. X and Y,
3481 if positive, specify the coordinate of the left and top edge of FRAME's
3482 outer frame in pixels relative to an origin (0, 0) of FRAME's display.
3483 If any of X or Y is negative, it specifies the coordinates of the right
3484 or bottom edge of the outer frame of FRAME relative to the right or
3485 bottom edge of FRAME's display. */)
3486 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
3488 struct frame *f = decode_live_frame (frame);
3490 CHECK_TYPE_RANGED_INTEGER (int, x);
3491 CHECK_TYPE_RANGED_INTEGER (int, y);
3493 /* I think this should be done with a hook. */
3494 if (FRAME_WINDOW_P (f))
3496 #ifdef HAVE_WINDOW_SYSTEM
3497 x_set_offset (f, XINT (x), XINT (y), 1);
3498 #endif
3501 return Qt;
3504 /***********************************************************************
3505 Frame Parameters
3506 ***********************************************************************/
3508 /* Connect the frame-parameter names for X frames
3509 to the ways of passing the parameter values to the window system.
3511 The name of a parameter, as a Lisp symbol,
3512 has an `x-frame-parameter' property which is an integer in Lisp
3513 that is an index in this table. */
3515 struct frame_parm_table {
3516 const char *name;
3517 int sym;
3520 static const struct frame_parm_table frame_parms[] =
3522 {"auto-raise", SYMBOL_INDEX (Qauto_raise)},
3523 {"auto-lower", SYMBOL_INDEX (Qauto_lower)},
3524 {"background-color", -1},
3525 {"border-color", SYMBOL_INDEX (Qborder_color)},
3526 {"border-width", SYMBOL_INDEX (Qborder_width)},
3527 {"cursor-color", SYMBOL_INDEX (Qcursor_color)},
3528 {"cursor-type", SYMBOL_INDEX (Qcursor_type)},
3529 {"font", -1},
3530 {"foreground-color", -1},
3531 {"icon-name", SYMBOL_INDEX (Qicon_name)},
3532 {"icon-type", SYMBOL_INDEX (Qicon_type)},
3533 {"internal-border-width", SYMBOL_INDEX (Qinternal_border_width)},
3534 {"right-divider-width", SYMBOL_INDEX (Qright_divider_width)},
3535 {"bottom-divider-width", SYMBOL_INDEX (Qbottom_divider_width)},
3536 {"menu-bar-lines", SYMBOL_INDEX (Qmenu_bar_lines)},
3537 {"mouse-color", SYMBOL_INDEX (Qmouse_color)},
3538 {"name", SYMBOL_INDEX (Qname)},
3539 {"scroll-bar-width", SYMBOL_INDEX (Qscroll_bar_width)},
3540 {"scroll-bar-height", SYMBOL_INDEX (Qscroll_bar_height)},
3541 {"title", SYMBOL_INDEX (Qtitle)},
3542 {"unsplittable", SYMBOL_INDEX (Qunsplittable)},
3543 {"vertical-scroll-bars", SYMBOL_INDEX (Qvertical_scroll_bars)},
3544 {"horizontal-scroll-bars", SYMBOL_INDEX (Qhorizontal_scroll_bars)},
3545 {"visibility", SYMBOL_INDEX (Qvisibility)},
3546 {"tool-bar-lines", SYMBOL_INDEX (Qtool_bar_lines)},
3547 {"scroll-bar-foreground", SYMBOL_INDEX (Qscroll_bar_foreground)},
3548 {"scroll-bar-background", SYMBOL_INDEX (Qscroll_bar_background)},
3549 {"screen-gamma", SYMBOL_INDEX (Qscreen_gamma)},
3550 {"line-spacing", SYMBOL_INDEX (Qline_spacing)},
3551 {"left-fringe", SYMBOL_INDEX (Qleft_fringe)},
3552 {"right-fringe", SYMBOL_INDEX (Qright_fringe)},
3553 {"wait-for-wm", SYMBOL_INDEX (Qwait_for_wm)},
3554 {"fullscreen", SYMBOL_INDEX (Qfullscreen)},
3555 {"font-backend", SYMBOL_INDEX (Qfont_backend)},
3556 {"alpha", SYMBOL_INDEX (Qalpha)},
3557 {"sticky", SYMBOL_INDEX (Qsticky)},
3558 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3559 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3560 {"undecorated", SYMBOL_INDEX (Qundecorated)},
3561 {"parent-frame", SYMBOL_INDEX (Qparent_frame)},
3562 {"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
3563 {"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
3564 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3565 {"z-group", SYMBOL_INDEX (Qz_group)},
3566 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3567 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
3568 #ifdef NS_IMPL_COCOA
3569 {"ns-appearance", SYMBOL_INDEX (Qns_appearance)},
3570 {"ns-transparent-titlebar", SYMBOL_INDEX (Qns_transparent_titlebar)},
3571 #endif
3574 #ifdef HAVE_WINDOW_SYSTEM
3576 /* Enumeration type for switch in frame_float. */
3577 enum frame_float_type
3579 FRAME_FLOAT_WIDTH,
3580 FRAME_FLOAT_HEIGHT,
3581 FRAME_FLOAT_LEFT,
3582 FRAME_FLOAT_TOP
3586 * frame_float:
3588 * Process the value VAL of the float type frame parameter 'width',
3589 * 'height', 'left', or 'top' specified via a frame_float_type
3590 * enumeration type WHAT for frame F. Such parameters relate the outer
3591 * size or position of F to the size of the F's display or parent frame
3592 * which have to be both available in some way.
3594 * The return value is a size or position value in pixels. VAL must be
3595 * in the range 0.0 to 1.0 where a width/height of 0.0 means to return 0
3596 * and 1.0 means to return the full width/height of the display/parent.
3597 * For positions, 0.0 means position in the left/top corner of the
3598 * display/parent while 1.0 means to position at the right/bottom corner
3599 * of the display/parent frame.
3601 * Set PARENT_DONE and OUTER_DONE to avoid recalculation of the outer
3602 * size or parent or display attributes when more float parameters are
3603 * calculated in a row: -1 means not processed yet, 0 means processing
3604 * failed, 1 means processing succeeded.
3606 * Return DEFAULT_VALUE when processing fails for whatever reason with
3607 * one exception: When calculating F's outer edges fails (probably
3608 * because F has not been created yet) return the difference between F's
3609 * native and text size.
3611 static int
3612 frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
3613 int *parent_done, int *outer_done, int default_value)
3615 double d_val = XFLOAT_DATA (val);
3617 if (d_val < 0.0 || d_val > 1.0)
3618 /* Invalid VAL. */
3619 return default_value;
3620 else
3622 static unsigned parent_width, parent_height;
3623 static int parent_left, parent_top;
3624 static unsigned outer_minus_text_width, outer_minus_text_height;
3625 struct frame *p = FRAME_PARENT_FRAME (f);
3627 if (*parent_done == 1)
3629 else if (p)
3631 parent_width = FRAME_PIXEL_WIDTH (p);
3632 parent_height = FRAME_PIXEL_HEIGHT (p);
3633 *parent_done = 1;
3635 else
3637 if (*parent_done == 0)
3638 /* No workarea available. */
3639 return default_value;
3640 else if (*parent_done == -1)
3642 Lisp_Object monitor_attributes;
3643 Lisp_Object workarea;
3644 Lisp_Object frame;
3646 XSETFRAME (frame, f);
3647 monitor_attributes = Fcar (call1 (Qdisplay_monitor_attributes_list, frame));
3648 if (NILP (monitor_attributes))
3650 /* No monitor attributes available. */
3651 *parent_done = 0;
3653 return default_value;
3656 workarea = Fcdr (Fassq (Qworkarea, monitor_attributes));
3657 if (NILP (workarea))
3659 /* No workarea available. */
3660 *parent_done = 0;
3662 return default_value;
3665 /* Workarea available. */
3666 parent_left = XINT (Fnth (make_number (0), workarea));
3667 parent_top = XINT (Fnth (make_number (1), workarea));
3668 parent_width = XINT (Fnth (make_number (2), workarea));
3669 parent_height = XINT (Fnth (make_number (3), workarea));
3670 *parent_done = 1;
3674 if (*outer_done == 1)
3676 else if (FRAME_UNDECORATED (f))
3678 outer_minus_text_width
3679 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3680 outer_minus_text_height
3681 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3682 *outer_done = 1;
3684 else if (*outer_done == 0)
3685 /* No outer size available. */
3686 return default_value;
3687 else if (*outer_done == -1)
3689 Lisp_Object frame, outer_edges;
3691 XSETFRAME (frame, f);
3692 outer_edges = call2 (Qframe_edges, frame, Qouter_edges);
3694 if (!NILP (outer_edges))
3696 outer_minus_text_width
3697 = (XINT (Fnth (make_number (2), outer_edges))
3698 - XINT (Fnth (make_number (0), outer_edges))
3699 - FRAME_TEXT_WIDTH (f));
3700 outer_minus_text_height
3701 = (XINT (Fnth (make_number (3), outer_edges))
3702 - XINT (Fnth (make_number (1), outer_edges))
3703 - FRAME_TEXT_HEIGHT (f));
3705 else
3707 /* If we can't get any outer edges, proceed as if the frame
3708 were undecorated. */
3709 outer_minus_text_width
3710 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3711 outer_minus_text_height
3712 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3715 *outer_done = 1;
3718 switch (what)
3720 case FRAME_FLOAT_WIDTH:
3721 return parent_width * d_val - outer_minus_text_width;
3723 case FRAME_FLOAT_HEIGHT:
3724 return parent_height * d_val - outer_minus_text_height;
3726 case FRAME_FLOAT_LEFT:
3728 int rest_width = (parent_width
3729 - FRAME_TEXT_WIDTH (f)
3730 - outer_minus_text_width);
3732 if (p)
3733 return (rest_width <= 0 ? 0 : d_val * rest_width);
3734 else
3735 return (rest_width <= 0
3736 ? parent_left
3737 : parent_left + d_val * rest_width);
3739 case FRAME_FLOAT_TOP:
3741 int rest_height = (parent_height
3742 - FRAME_TEXT_HEIGHT (f)
3743 - outer_minus_text_height);
3745 if (p)
3746 return (rest_height <= 0 ? 0 : d_val * rest_height);
3747 else
3748 return (rest_height <= 0
3749 ? parent_top
3750 : parent_top + d_val * rest_height);
3752 default:
3753 emacs_abort ();
3758 /* Change the parameters of frame F as specified by ALIST.
3759 If a parameter is not specially recognized, do nothing special;
3760 otherwise call the `x_set_...' function for that parameter.
3761 Except for certain geometry properties, always call store_frame_param
3762 to store the new value in the parameter alist. */
3764 void
3765 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3767 Lisp_Object tail, frame;
3770 /* If both of these parameters are present, it's more efficient to
3771 set them both at once. So we wait until we've looked at the
3772 entire list before we set them. */
3773 int width = -1, height = -1; /* -1 denotes they were not changed. */
3775 /* Same here. */
3776 Lisp_Object left, top;
3778 /* Same with these. */
3779 Lisp_Object icon_left, icon_top;
3781 /* And with this. */
3782 Lisp_Object fullscreen;
3783 bool fullscreen_change = false;
3785 /* Record in these vectors all the parms specified. */
3786 Lisp_Object *parms;
3787 Lisp_Object *values;
3788 ptrdiff_t i, j, size;
3789 bool left_no_change = 0, top_no_change = 0;
3790 #ifdef HAVE_X_WINDOWS
3791 bool icon_left_no_change = 0, icon_top_no_change = 0;
3792 #endif
3793 int parent_done = -1, outer_done = -1;
3795 XSETFRAME (frame, f);
3796 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
3797 size++;
3798 CHECK_LIST_END (tail, alist);
3800 USE_SAFE_ALLOCA;
3801 SAFE_ALLOCA_LISP (parms, 2 * size);
3802 values = parms + size;
3804 /* Extract parm names and values into those vectors. */
3806 i = 0, j = size - 1;
3807 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3809 Lisp_Object elt = XCAR (tail), prop = Fcar (elt), val = Fcdr (elt);
3811 /* Some properties are independent of other properties, but other
3812 properties are dependent upon them. These special properties
3813 are foreground_color, background_color (affects cursor_color)
3814 and font (affects fringe widths); they're recorded starting
3815 from the end of PARMS and VALUES to process them first by using
3816 reverse iteration. */
3818 if (EQ (prop, Qforeground_color)
3819 || EQ (prop, Qbackground_color)
3820 || EQ (prop, Qfont))
3822 parms[j] = prop;
3823 values[j] = val;
3824 j--;
3826 else
3828 parms[i] = prop;
3829 values[i] = val;
3830 i++;
3834 /* TAIL and ALIST are not used again below here. */
3835 alist = tail = Qnil;
3837 top = left = Qunbound;
3838 icon_left = icon_top = Qunbound;
3840 /* Reverse order is used to make sure that special
3841 properties noticed above are processed first. */
3842 for (i = size - 1; i >= 0; i--)
3844 Lisp_Object prop, val;
3846 prop = parms[i];
3847 val = values[i];
3849 if (EQ (prop, Qwidth))
3851 if (RANGED_INTEGERP (0, val, INT_MAX))
3852 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3853 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3854 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3855 width = XFASTINT (XCDR (val));
3856 else if (FLOATP (val))
3857 width = frame_float (f, val, FRAME_FLOAT_WIDTH, &parent_done,
3858 &outer_done, -1);
3860 else if (EQ (prop, Qheight))
3862 if (RANGED_INTEGERP (0, val, INT_MAX))
3863 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3864 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3865 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3866 height = XFASTINT (XCDR (val));
3867 else if (FLOATP (val))
3868 height = frame_float (f, val, FRAME_FLOAT_HEIGHT, &parent_done,
3869 &outer_done, -1);
3871 else if (EQ (prop, Qtop))
3872 top = val;
3873 else if (EQ (prop, Qleft))
3874 left = val;
3875 else if (EQ (prop, Qicon_top))
3876 icon_top = val;
3877 else if (EQ (prop, Qicon_left))
3878 icon_left = val;
3879 else if (EQ (prop, Qfullscreen))
3881 fullscreen = val;
3882 fullscreen_change = true;
3884 else
3886 register Lisp_Object param_index, old_value;
3888 old_value = get_frame_param (f, prop);
3890 store_frame_param (f, prop, val);
3892 param_index = Fget (prop, Qx_frame_parameter);
3893 if (NATNUMP (param_index)
3894 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3895 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3896 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3900 /* Don't die if just one of these was set. */
3901 if (EQ (left, Qunbound))
3903 left_no_change = 1;
3904 if (f->left_pos < 0)
3905 left = list2 (Qplus, make_number (f->left_pos));
3906 else
3907 XSETINT (left, f->left_pos);
3909 if (EQ (top, Qunbound))
3911 top_no_change = 1;
3912 if (f->top_pos < 0)
3913 top = list2 (Qplus, make_number (f->top_pos));
3914 else
3915 XSETINT (top, f->top_pos);
3918 /* If one of the icon positions was not set, preserve or default it. */
3919 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3921 #ifdef HAVE_X_WINDOWS
3922 icon_left_no_change = 1;
3923 #endif
3924 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3925 if (NILP (icon_left))
3926 XSETINT (icon_left, 0);
3928 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3930 #ifdef HAVE_X_WINDOWS
3931 icon_top_no_change = 1;
3932 #endif
3933 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3934 if (NILP (icon_top))
3935 XSETINT (icon_top, 0);
3938 /* Don't set these parameters unless they've been explicitly
3939 specified. The window might be mapped or resized while we're in
3940 this function, and we don't want to override that unless the lisp
3941 code has asked for it.
3943 Don't set these parameters unless they actually differ from the
3944 window's current parameters; the window may not actually exist
3945 yet. */
3946 if ((width != -1 && width != FRAME_TEXT_WIDTH (f))
3947 || (height != -1 && height != FRAME_TEXT_HEIGHT (f)))
3948 /* We could consider checking f->after_make_frame here, but I
3949 don't have the faintest idea why the following is needed at
3950 all. With the old setting it can get a Heisenbug when
3951 EmacsFrameResize intermittently provokes a delayed
3952 change_frame_size in the middle of adjust_frame_size. */
3953 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
3954 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters);
3956 if ((!NILP (left) || !NILP (top))
3957 && ! (left_no_change && top_no_change)
3958 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3959 && NUMBERP (top) && XINT (top) == f->top_pos))
3961 int leftpos = 0;
3962 int toppos = 0;
3964 /* Record the signs. */
3965 f->size_hint_flags &= ~ (XNegative | YNegative);
3966 if (EQ (left, Qminus))
3967 f->size_hint_flags |= XNegative;
3968 else if (TYPE_RANGED_INTEGERP (int, left))
3970 leftpos = XINT (left);
3971 if (leftpos < 0)
3972 f->size_hint_flags |= XNegative;
3974 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3975 && CONSP (XCDR (left))
3976 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3978 leftpos = - XINT (XCAR (XCDR (left)));
3979 f->size_hint_flags |= XNegative;
3981 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3982 && CONSP (XCDR (left))
3983 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3984 leftpos = XINT (XCAR (XCDR (left)));
3985 else if (FLOATP (left))
3986 leftpos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
3987 &outer_done, 0);
3989 if (EQ (top, Qminus))
3990 f->size_hint_flags |= YNegative;
3991 else if (TYPE_RANGED_INTEGERP (int, top))
3993 toppos = XINT (top);
3994 if (toppos < 0)
3995 f->size_hint_flags |= YNegative;
3997 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3998 && CONSP (XCDR (top))
3999 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
4001 toppos = - XINT (XCAR (XCDR (top)));
4002 f->size_hint_flags |= YNegative;
4004 else if (CONSP (top) && EQ (XCAR (top), Qplus)
4005 && CONSP (XCDR (top))
4006 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
4007 toppos = XINT (XCAR (XCDR (top)));
4008 else if (FLOATP (top))
4009 toppos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
4010 &outer_done, 0);
4012 /* Store the numeric value of the position. */
4013 f->top_pos = toppos;
4014 f->left_pos = leftpos;
4016 f->win_gravity = NorthWestGravity;
4018 /* Actually set that position, and convert to absolute. */
4019 x_set_offset (f, leftpos, toppos, -1);
4022 if (fullscreen_change)
4024 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
4026 frame_size_history_add
4027 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
4029 store_frame_param (f, Qfullscreen, fullscreen);
4030 if (!EQ (fullscreen, old_value))
4031 x_set_fullscreen (f, fullscreen, old_value);
4035 #ifdef HAVE_X_WINDOWS
4036 if ((!NILP (icon_left) || !NILP (icon_top))
4037 && ! (icon_left_no_change && icon_top_no_change))
4038 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
4039 #endif /* HAVE_X_WINDOWS */
4041 SAFE_FREE ();
4045 /* Insert a description of internally-recorded parameters of frame X
4046 into the parameter alist *ALISTPTR that is to be given to the user.
4047 Only parameters that are specific to the X window system
4048 and whose values are not correctly recorded in the frame's
4049 param_alist need to be considered here. */
4051 void
4052 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
4054 Lisp_Object tem;
4055 uprintmax_t w;
4056 char buf[INT_BUFSIZE_BOUND (w)];
4058 /* Represent negative positions (off the top or left screen edge)
4059 in a way that Fmodify_frame_parameters will understand correctly. */
4060 XSETINT (tem, f->left_pos);
4061 if (f->left_pos >= 0)
4062 store_in_alist (alistptr, Qleft, tem);
4063 else
4064 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
4066 XSETINT (tem, f->top_pos);
4067 if (f->top_pos >= 0)
4068 store_in_alist (alistptr, Qtop, tem);
4069 else
4070 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
4072 store_in_alist (alistptr, Qborder_width,
4073 make_number (f->border_width));
4074 store_in_alist (alistptr, Qinternal_border_width,
4075 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
4076 store_in_alist (alistptr, Qright_divider_width,
4077 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
4078 store_in_alist (alistptr, Qbottom_divider_width,
4079 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
4080 store_in_alist (alistptr, Qleft_fringe,
4081 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
4082 store_in_alist (alistptr, Qright_fringe,
4083 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
4084 store_in_alist (alistptr, Qscroll_bar_width,
4085 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4086 ? make_number (0)
4087 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
4088 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4089 /* nil means "use default width"
4090 for non-toolkit scroll bar.
4091 ruler-mode.el depends on this. */
4092 : Qnil));
4093 store_in_alist (alistptr, Qscroll_bar_height,
4094 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
4095 ? make_number (0)
4096 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
4097 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4098 /* nil means "use default height"
4099 for non-toolkit scroll bar. */
4100 : Qnil));
4101 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
4102 MS-Windows it returns a value whose type is HANDLE, which is
4103 actually a pointer. Explicit casting avoids compiler
4104 warnings. */
4105 w = (uintptr_t) FRAME_X_WINDOW (f);
4106 store_in_alist (alistptr, Qwindow_id,
4107 make_formatted_string (buf, "%"pMu, w));
4108 #ifdef HAVE_X_WINDOWS
4109 #ifdef USE_X_TOOLKIT
4110 /* Tooltip frame may not have this widget. */
4111 if (FRAME_X_OUTPUT (f)->widget)
4112 #endif
4113 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
4114 store_in_alist (alistptr, Qouter_window_id,
4115 make_formatted_string (buf, "%"pMu, w));
4116 #endif
4117 store_in_alist (alistptr, Qicon_name, f->icon_name);
4118 store_in_alist (alistptr, Qvisibility,
4119 (FRAME_VISIBLE_P (f) ? Qt
4120 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
4121 store_in_alist (alistptr, Qdisplay,
4122 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
4124 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
4125 tem = Qnil;
4126 else
4127 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
4128 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
4129 store_in_alist (alistptr, Qparent_id, tem);
4130 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
4134 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
4135 the previous value of that parameter, NEW_VALUE is the new value. */
4137 void
4138 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4140 if (NILP (new_value))
4141 f->want_fullscreen = FULLSCREEN_NONE;
4142 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
4143 f->want_fullscreen = FULLSCREEN_BOTH;
4144 else if (EQ (new_value, Qfullwidth))
4145 f->want_fullscreen = FULLSCREEN_WIDTH;
4146 else if (EQ (new_value, Qfullheight))
4147 f->want_fullscreen = FULLSCREEN_HEIGHT;
4148 else if (EQ (new_value, Qmaximized))
4149 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
4151 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
4152 FRAME_TERMINAL (f)->fullscreen_hook (f);
4156 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
4157 the previous value of that parameter, NEW_VALUE is the new value. */
4159 void
4160 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4162 if (NILP (new_value))
4163 f->extra_line_spacing = 0;
4164 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
4165 f->extra_line_spacing = XFASTINT (new_value);
4166 else if (FLOATP (new_value))
4168 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
4170 if (new_spacing >= 0)
4171 f->extra_line_spacing = new_spacing;
4172 else
4173 signal_error ("Invalid line-spacing", new_value);
4175 else
4176 signal_error ("Invalid line-spacing", new_value);
4177 if (FRAME_VISIBLE_P (f))
4178 redraw_frame (f);
4182 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
4183 the previous value of that parameter, NEW_VALUE is the new value. */
4185 void
4186 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4188 Lisp_Object bgcolor;
4190 if (NILP (new_value))
4191 f->gamma = 0;
4192 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
4193 /* The value 0.4545 is the normal viewing gamma. */
4194 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
4195 else
4196 signal_error ("Invalid screen-gamma", new_value);
4198 /* Apply the new gamma value to the frame background. */
4199 bgcolor = Fassq (Qbackground_color, f->param_alist);
4200 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
4202 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
4203 if (NATNUMP (parm_index)
4204 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
4205 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4206 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4207 (f, bgcolor, Qnil);
4210 clear_face_cache (true); /* FIXME: Why of all frames? */
4211 fset_redisplay (f);
4215 void
4216 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4218 Lisp_Object font_object;
4219 int fontset = -1;
4220 #ifdef HAVE_X_WINDOWS
4221 Lisp_Object font_param = arg;
4222 #endif
4224 /* Set the frame parameter back to the old value because we may
4225 fail to use ARG as the new parameter value. */
4226 store_frame_param (f, Qfont, oldval);
4228 /* ARG is a fontset name, a font name, a cons of fontset name and a
4229 font object, or a font object. In the last case, this function
4230 never fail. */
4231 if (STRINGP (arg))
4233 fontset = fs_query_fontset (arg, 0);
4234 if (fontset < 0)
4236 font_object = font_open_by_name (f, arg);
4237 if (NILP (font_object))
4238 error ("Font `%s' is not defined", SSDATA (arg));
4239 arg = AREF (font_object, FONT_NAME_INDEX);
4241 else if (fontset > 0)
4243 font_object = font_open_by_name (f, fontset_ascii (fontset));
4244 if (NILP (font_object))
4245 error ("Font `%s' is not defined", SDATA (arg));
4246 arg = AREF (font_object, FONT_NAME_INDEX);
4248 else
4249 error ("The default fontset can't be used for a frame font");
4251 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
4253 /* This is the case that the ASCII font of F's fontset XCAR
4254 (arg) is changed to the font XCDR (arg) by
4255 `set-fontset-font'. */
4256 fontset = fs_query_fontset (XCAR (arg), 0);
4257 if (fontset < 0)
4258 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
4259 font_object = XCDR (arg);
4260 arg = AREF (font_object, FONT_NAME_INDEX);
4261 #ifdef HAVE_X_WINDOWS
4262 font_param = Ffont_get (font_object, QCname);
4263 #endif
4265 else if (FONT_OBJECT_P (arg))
4267 font_object = arg;
4268 #ifdef HAVE_X_WINDOWS
4269 font_param = Ffont_get (font_object, QCname);
4270 #endif
4271 /* This is to store the XLFD font name in the frame parameter for
4272 backward compatibility. We should store the font-object
4273 itself in the future. */
4274 arg = AREF (font_object, FONT_NAME_INDEX);
4275 fontset = FRAME_FONTSET (f);
4276 /* Check if we can use the current fontset. If not, set FONTSET
4277 to -1 to generate a new fontset from FONT-OBJECT. */
4278 if (fontset >= 0)
4280 Lisp_Object ascii_font = fontset_ascii (fontset);
4281 Lisp_Object spec = font_spec_from_name (ascii_font);
4283 /* SPEC might be nil because ASCII_FONT's name doesn't parse
4284 according to stupid XLFD rules, which, for example,
4285 disallow font names that include a dash followed by a
4286 number. So in those cases we simply request x_new_font
4287 below to generate a new fontset. */
4288 if (NILP (spec) || ! font_match_p (spec, font_object))
4289 fontset = -1;
4292 else
4293 signal_error ("Invalid font", arg);
4295 if (! NILP (Fequal (font_object, oldval)))
4296 return;
4298 x_new_font (f, font_object, fontset);
4299 store_frame_param (f, Qfont, arg);
4300 #ifdef HAVE_X_WINDOWS
4301 store_frame_param (f, Qfont_parameter, font_param);
4302 #endif
4303 /* Recalculate toolbar height. */
4304 f->n_tool_bar_rows = 0;
4306 /* Ensure we redraw it. */
4307 clear_current_matrices (f);
4309 /* Attempt to hunt down bug#16028. */
4310 SET_FRAME_GARBAGED (f);
4312 /* This is important if we are called by some Lisp as part of
4313 redisplaying the frame, see redisplay_internal. */
4314 f->fonts_changed = true;
4316 recompute_basic_faces (f);
4318 do_pending_window_change (0);
4320 /* We used to call face-set-after-frame-default here, but it leads to
4321 recursive calls (since that function can set the `default' face's
4322 font which in turns changes the frame's `font' parameter).
4323 Also I don't know what this call is meant to do, but it seems the
4324 wrong way to do it anyway (it does a lot more work than what seems
4325 reasonable in response to a change to `font'). */
4329 void
4330 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4332 if (! NILP (new_value)
4333 && !CONSP (new_value))
4335 char *p0, *p1;
4337 CHECK_STRING (new_value);
4338 p0 = p1 = SSDATA (new_value);
4339 new_value = Qnil;
4340 while (*p0)
4342 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
4343 if (p0 < p1)
4344 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
4345 new_value);
4346 if (*p1)
4348 int c;
4350 while ((c = *++p1) && c_isspace (c));
4352 p0 = p1;
4354 new_value = Fnreverse (new_value);
4357 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
4358 return;
4360 if (FRAME_FONT (f))
4361 free_all_realized_faces (Qnil);
4363 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
4364 if (NILP (new_value))
4366 if (NILP (old_value))
4367 error ("No font backend available");
4368 font_update_drivers (f, old_value);
4369 error ("None of specified font backends are available");
4371 store_frame_param (f, Qfont_backend, new_value);
4373 if (FRAME_FONT (f))
4375 Lisp_Object frame;
4377 XSETFRAME (frame, f);
4378 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
4379 face_change = true;
4380 windows_or_buffers_changed = 18;
4384 void
4385 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4387 int unit = FRAME_COLUMN_WIDTH (f);
4388 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
4389 int new_width;
4391 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4392 ? eabs (XINT (new_value)) : 8);
4394 if (new_width != old_width)
4396 f->left_fringe_width = new_width;
4397 f->fringe_cols /* Round up. */
4398 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
4400 if (FRAME_X_WINDOW (f) != 0)
4401 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
4403 SET_FRAME_GARBAGED (f);
4408 void
4409 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4411 int unit = FRAME_COLUMN_WIDTH (f);
4412 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
4413 int new_width;
4415 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4416 ? eabs (XINT (new_value)) : 8);
4418 if (new_width != old_width)
4420 f->right_fringe_width = new_width;
4421 f->fringe_cols /* Round up. */
4422 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
4424 if (FRAME_X_WINDOW (f) != 0)
4425 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
4427 SET_FRAME_GARBAGED (f);
4432 void
4433 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4435 CHECK_TYPE_RANGED_INTEGER (int, arg);
4437 if (XINT (arg) == f->border_width)
4438 return;
4440 if (FRAME_X_WINDOW (f) != 0)
4441 error ("Cannot change the border width of a frame");
4443 f->border_width = XINT (arg);
4446 void
4447 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4449 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
4450 CHECK_TYPE_RANGED_INTEGER (int, arg);
4451 int new = max (0, XINT (arg));
4452 if (new != old)
4454 f->right_divider_width = new;
4455 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
4456 adjust_frame_glyphs (f);
4457 SET_FRAME_GARBAGED (f);
4461 void
4462 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4464 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
4465 CHECK_TYPE_RANGED_INTEGER (int, arg);
4466 int new = max (0, XINT (arg));
4467 if (new != old)
4469 f->bottom_divider_width = new;
4470 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
4471 adjust_frame_glyphs (f);
4472 SET_FRAME_GARBAGED (f);
4476 void
4477 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
4479 Lisp_Object frame;
4480 XSETFRAME (frame, f);
4482 if (NILP (value))
4483 Fmake_frame_invisible (frame, Qt);
4484 else if (EQ (value, Qicon))
4485 Ficonify_frame (frame);
4486 else
4487 Fmake_frame_visible (frame);
4490 void
4491 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4493 f->auto_raise = !EQ (Qnil, arg);
4496 void
4497 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4499 f->auto_lower = !EQ (Qnil, arg);
4502 void
4503 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4505 f->no_split = !NILP (arg);
4508 void
4509 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4511 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4512 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
4513 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4514 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
4516 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
4517 = (NILP (arg)
4518 ? vertical_scroll_bar_none
4519 : EQ (Qleft, arg)
4520 ? vertical_scroll_bar_left
4521 : EQ (Qright, arg)
4522 ? vertical_scroll_bar_right
4523 : EQ (Qleft, Vdefault_frame_scroll_bars)
4524 ? vertical_scroll_bar_left
4525 : EQ (Qright, Vdefault_frame_scroll_bars)
4526 ? vertical_scroll_bar_right
4527 : vertical_scroll_bar_none);
4529 /* We set this parameter before creating the X window for the
4530 frame, so we can get the geometry right from the start.
4531 However, if the window hasn't been created yet, we shouldn't
4532 call x_set_window_size. */
4533 if (FRAME_X_WINDOW (f))
4534 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
4536 SET_FRAME_GARBAGED (f);
4540 void
4541 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4543 #if USE_HORIZONTAL_SCROLL_BARS
4544 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
4545 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
4547 f->horizontal_scroll_bars = NILP (arg) ? false : true;
4549 /* We set this parameter before creating the X window for the
4550 frame, so we can get the geometry right from the start.
4551 However, if the window hasn't been created yet, we shouldn't
4552 call x_set_window_size. */
4553 if (FRAME_X_WINDOW (f))
4554 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
4556 SET_FRAME_GARBAGED (f);
4558 #endif
4561 void
4562 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4564 int unit = FRAME_COLUMN_WIDTH (f);
4566 if (NILP (arg))
4568 x_set_scroll_bar_default_width (f);
4570 if (FRAME_X_WINDOW (f))
4571 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4573 SET_FRAME_GARBAGED (f);
4575 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4576 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4578 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
4579 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
4580 if (FRAME_X_WINDOW (f))
4581 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4583 SET_FRAME_GARBAGED (f);
4586 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
4587 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
4590 void
4591 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4593 #if USE_HORIZONTAL_SCROLL_BARS
4594 int unit = FRAME_LINE_HEIGHT (f);
4596 if (NILP (arg))
4598 x_set_scroll_bar_default_height (f);
4600 if (FRAME_X_WINDOW (f))
4601 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4603 SET_FRAME_GARBAGED (f);
4605 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4606 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4608 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
4609 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
4610 if (FRAME_X_WINDOW (f))
4611 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4613 SET_FRAME_GARBAGED (f);
4616 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
4617 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
4618 #endif
4621 void
4622 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4624 double alpha = 1.0;
4625 double newval[2];
4626 int i;
4627 Lisp_Object item;
4629 for (i = 0; i < 2; i++)
4631 newval[i] = 1.0;
4632 if (CONSP (arg))
4634 item = CAR (arg);
4635 arg = CDR (arg);
4637 else
4638 item = arg;
4640 if (NILP (item))
4641 alpha = - 1.0;
4642 else if (FLOATP (item))
4644 alpha = XFLOAT_DATA (item);
4645 if (! (0 <= alpha && alpha <= 1.0))
4646 args_out_of_range (make_float (0.0), make_float (1.0));
4648 else if (INTEGERP (item))
4650 EMACS_INT ialpha = XINT (item);
4651 if (! (0 <= ialpha && ialpha <= 100))
4652 args_out_of_range (make_number (0), make_number (100));
4653 alpha = ialpha / 100.0;
4655 else
4656 wrong_type_argument (Qnumberp, item);
4657 newval[i] = alpha;
4660 for (i = 0; i < 2; i++)
4661 f->alpha[i] = newval[i];
4663 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
4664 block_input ();
4665 x_set_frame_alpha (f);
4666 unblock_input ();
4667 #endif
4669 return;
4674 * x_set_no_special_glyphs:
4676 * Set frame F's `no-special-glyphs' parameter which, if non-nil,
4677 * suppresses the display of truncation and continuation glyphs
4678 * outside fringes.
4680 void
4681 x_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4683 if (!EQ (new_value, old_value))
4684 FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (new_value);
4688 #ifndef HAVE_NS
4690 /* Non-zero if mouse is grabbed on DPYINFO
4691 and we know the frame where it is. */
4693 bool x_mouse_grabbed (Display_Info *dpyinfo)
4695 return (dpyinfo->grabbed
4696 && dpyinfo->last_mouse_frame
4697 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
4700 /* Re-highlight something with mouse-face properties
4701 on DPYINFO using saved frame and mouse position. */
4703 void
4704 x_redo_mouse_highlight (Display_Info *dpyinfo)
4706 if (dpyinfo->last_mouse_motion_frame
4707 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
4708 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
4709 dpyinfo->last_mouse_motion_x,
4710 dpyinfo->last_mouse_motion_y);
4713 #endif /* HAVE_NS */
4715 /* Subroutines of creating an X frame. */
4717 /* Make sure that Vx_resource_name is set to a reasonable value.
4718 Fix it up, or set it to `emacs' if it is too hopeless. */
4720 void
4721 validate_x_resource_name (void)
4723 ptrdiff_t len = 0;
4724 /* Number of valid characters in the resource name. */
4725 ptrdiff_t good_count = 0;
4726 /* Number of invalid characters in the resource name. */
4727 ptrdiff_t bad_count = 0;
4728 Lisp_Object new;
4729 ptrdiff_t i;
4731 if (!STRINGP (Vx_resource_class))
4732 Vx_resource_class = build_string (EMACS_CLASS);
4734 if (STRINGP (Vx_resource_name))
4736 unsigned char *p = SDATA (Vx_resource_name);
4738 len = SBYTES (Vx_resource_name);
4740 /* Only letters, digits, - and _ are valid in resource names.
4741 Count the valid characters and count the invalid ones. */
4742 for (i = 0; i < len; i++)
4744 int c = p[i];
4745 if (! ((c >= 'a' && c <= 'z')
4746 || (c >= 'A' && c <= 'Z')
4747 || (c >= '0' && c <= '9')
4748 || c == '-' || c == '_'))
4749 bad_count++;
4750 else
4751 good_count++;
4754 else
4755 /* Not a string => completely invalid. */
4756 bad_count = 5, good_count = 0;
4758 /* If name is valid already, return. */
4759 if (bad_count == 0)
4760 return;
4762 /* If name is entirely invalid, or nearly so, or is so implausibly
4763 large that alloca might not work, use `emacs'. */
4764 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
4766 Vx_resource_name = build_string ("emacs");
4767 return;
4770 /* Name is partly valid. Copy it and replace the invalid characters
4771 with underscores. */
4773 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
4775 for (i = 0; i < len; i++)
4777 int c = SREF (new, i);
4778 if (! ((c >= 'a' && c <= 'z')
4779 || (c >= 'A' && c <= 'Z')
4780 || (c >= '0' && c <= '9')
4781 || c == '-' || c == '_'))
4782 SSET (new, i, '_');
4786 /* Get specified attribute from resource database RDB.
4787 See Fx_get_resource below for other parameters. */
4789 static Lisp_Object
4790 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
4792 CHECK_STRING (attribute);
4793 CHECK_STRING (class);
4795 if (!NILP (component))
4796 CHECK_STRING (component);
4797 if (!NILP (subclass))
4798 CHECK_STRING (subclass);
4799 if (NILP (component) != NILP (subclass))
4800 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
4802 validate_x_resource_name ();
4804 /* Allocate space for the components, the dots which separate them,
4805 and the final '\0'. Make them big enough for the worst case. */
4806 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4807 + (STRINGP (component)
4808 ? SBYTES (component) : 0)
4809 + SBYTES (attribute)
4810 + 3);
4812 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4813 + SBYTES (class)
4814 + (STRINGP (subclass)
4815 ? SBYTES (subclass) : 0)
4816 + 3);
4817 USE_SAFE_ALLOCA;
4818 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4819 char *class_key = name_key + name_keysize;
4821 /* Start with emacs.FRAMENAME for the name (the specific one)
4822 and with `Emacs' for the class key (the general one). */
4823 char *nz = lispstpcpy (name_key, Vx_resource_name);
4824 char *cz = lispstpcpy (class_key, Vx_resource_class);
4826 *cz++ = '.';
4827 cz = lispstpcpy (cz, class);
4829 if (!NILP (component))
4831 *cz++ = '.';
4832 lispstpcpy (cz, subclass);
4834 *nz++ = '.';
4835 nz = lispstpcpy (nz, component);
4838 *nz++ = '.';
4839 lispstpcpy (nz, attribute);
4841 char *value = x_get_string_resource (rdb, name_key, class_key);
4842 SAFE_FREE();
4844 if (value && *value)
4845 return build_string (value);
4846 else
4847 return Qnil;
4851 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4852 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4853 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4854 class, where INSTANCE is the name under which Emacs was invoked, or
4855 the name specified by the `-name' or `-rn' command-line arguments.
4857 The optional arguments COMPONENT and SUBCLASS add to the key and the
4858 class, respectively. You must specify both of them or neither.
4859 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4860 and the class is `Emacs.CLASS.SUBCLASS'. */)
4861 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4862 Lisp_Object subclass)
4864 check_window_system (NULL);
4866 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4867 attribute, class, component, subclass);
4870 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4872 Lisp_Object
4873 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4874 Lisp_Object class, Lisp_Object component,
4875 Lisp_Object subclass)
4877 return xrdb_get_resource (dpyinfo->xrdb,
4878 attribute, class, component, subclass);
4881 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
4882 /* Used when C code wants a resource value. */
4883 /* Called from oldXMenu/Create.c. */
4884 char *
4885 x_get_resource_string (const char *attribute, const char *class)
4887 char *result;
4888 struct frame *sf = SELECTED_FRAME ();
4889 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4890 USE_SAFE_ALLOCA;
4892 /* Allocate space for the components, the dots which separate them,
4893 and the final '\0'. */
4894 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4895 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4896 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4897 char *class_key = name_key + name_keysize;
4899 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4900 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4902 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4903 name_key, class_key);
4904 SAFE_FREE ();
4905 return result;
4907 #endif
4909 /* Return the value of parameter PARAM.
4911 First search ALIST, then Vdefault_frame_alist, then the X defaults
4912 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4914 Convert the resource to the type specified by desired_type.
4916 If no default is specified, return Qunbound. If you call
4917 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4918 and don't let it get stored in any Lisp-visible variables! */
4920 Lisp_Object
4921 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4922 const char *attribute, const char *class, enum resource_types type)
4924 Lisp_Object tem;
4926 tem = Fassq (param, alist);
4928 if (!NILP (tem))
4930 /* If we find this parm in ALIST, clear it out
4931 so that it won't be "left over" at the end. */
4932 Lisp_Object tail;
4933 XSETCAR (tem, Qnil);
4934 /* In case the parameter appears more than once in the alist,
4935 clear it out. */
4936 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4937 if (CONSP (XCAR (tail))
4938 && EQ (XCAR (XCAR (tail)), param))
4939 XSETCAR (XCAR (tail), Qnil);
4941 else
4942 tem = Fassq (param, Vdefault_frame_alist);
4944 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4945 look in the X resources. */
4946 if (EQ (tem, Qnil))
4948 if (attribute && dpyinfo)
4950 AUTO_STRING (at, attribute);
4951 AUTO_STRING (cl, class);
4952 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4954 if (NILP (tem))
4955 return Qunbound;
4957 switch (type)
4959 case RES_TYPE_NUMBER:
4960 return make_number (atoi (SSDATA (tem)));
4962 case RES_TYPE_BOOLEAN_NUMBER:
4963 if (!strcmp (SSDATA (tem), "on")
4964 || !strcmp (SSDATA (tem), "true"))
4965 return make_number (1);
4966 return make_number (atoi (SSDATA (tem)));
4967 break;
4969 case RES_TYPE_FLOAT:
4970 return make_float (atof (SSDATA (tem)));
4972 case RES_TYPE_BOOLEAN:
4973 tem = Fdowncase (tem);
4974 if (!strcmp (SSDATA (tem), "on")
4975 #ifdef HAVE_NS
4976 || !strcmp (SSDATA (tem), "yes")
4977 #endif
4978 || !strcmp (SSDATA (tem), "true"))
4979 return Qt;
4980 else
4981 return Qnil;
4983 case RES_TYPE_STRING:
4984 return tem;
4986 case RES_TYPE_SYMBOL:
4987 /* As a special case, we map the values `true' and `on'
4988 to Qt, and `false' and `off' to Qnil. */
4990 Lisp_Object lower;
4991 lower = Fdowncase (tem);
4992 if (!strcmp (SSDATA (lower), "on")
4993 #ifdef HAVE_NS
4994 || !strcmp (SSDATA (lower), "yes")
4995 #endif
4996 || !strcmp (SSDATA (lower), "true"))
4997 return Qt;
4998 else if (!strcmp (SSDATA (lower), "off")
4999 #ifdef HAVE_NS
5000 || !strcmp (SSDATA (lower), "no")
5001 #endif
5002 || !strcmp (SSDATA (lower), "false"))
5003 return Qnil;
5004 else
5005 return Fintern (tem, Qnil);
5008 default:
5009 emacs_abort ();
5012 else
5013 return Qunbound;
5015 return Fcdr (tem);
5018 static Lisp_Object
5019 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
5020 const char *attribute, const char *class,
5021 enum resource_types type)
5023 return x_get_arg (FRAME_DISPLAY_INFO (f),
5024 alist, param, attribute, class, type);
5027 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
5029 Lisp_Object
5030 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
5031 Lisp_Object param,
5032 const char *attribute, const char *class,
5033 enum resource_types type)
5035 Lisp_Object value;
5037 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
5038 attribute, class, type);
5039 if (! NILP (value) && ! EQ (value, Qunbound))
5040 store_frame_param (f, param, value);
5042 return value;
5046 /* Record in frame F the specified or default value according to ALIST
5047 of the parameter named PROP (a Lisp symbol).
5048 If no value is specified for PROP, look for an X default for XPROP
5049 on the frame named NAME.
5050 If that is not found either, use the value DEFLT. */
5052 Lisp_Object
5053 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
5054 Lisp_Object deflt, const char *xprop, const char *xclass,
5055 enum resource_types type)
5057 Lisp_Object tem;
5059 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
5060 if (EQ (tem, Qunbound))
5061 tem = deflt;
5062 AUTO_FRAME_ARG (arg, prop, tem);
5063 x_set_frame_parameters (f, arg);
5064 return tem;
5068 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
5071 * XParseGeometry parses strings of the form
5072 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5073 * width, height, xoffset, and yoffset are unsigned integers.
5074 * Example: "=80x24+300-49"
5075 * The equal sign is optional.
5076 * It returns a bitmask that indicates which of the four values
5077 * were actually found in the string. For each value found,
5078 * the corresponding argument is updated; for each value
5079 * not found, the corresponding argument is left unchanged.
5082 static int
5083 XParseGeometry (char *string,
5084 int *x, int *y,
5085 unsigned int *width, unsigned int *height)
5087 int mask = NoValue;
5088 char *strind;
5089 unsigned long tempWidth UNINIT, tempHeight UNINIT;
5090 long int tempX UNINIT, tempY UNINIT;
5091 char *nextCharacter;
5093 if (string == NULL || *string == '\0')
5094 return mask;
5095 if (*string == '=')
5096 string++; /* ignore possible '=' at beg of geometry spec */
5098 strind = string;
5099 if (*strind != '+' && *strind != '-' && *strind != 'x')
5101 tempWidth = strtoul (strind, &nextCharacter, 10);
5102 if (strind == nextCharacter)
5103 return 0;
5104 strind = nextCharacter;
5105 mask |= WidthValue;
5108 if (*strind == 'x' || *strind == 'X')
5110 strind++;
5111 tempHeight = strtoul (strind, &nextCharacter, 10);
5112 if (strind == nextCharacter)
5113 return 0;
5114 strind = nextCharacter;
5115 mask |= HeightValue;
5118 if (*strind == '+' || *strind == '-')
5120 if (*strind == '-')
5121 mask |= XNegative;
5122 tempX = strtol (strind, &nextCharacter, 10);
5123 if (strind == nextCharacter)
5124 return 0;
5125 strind = nextCharacter;
5126 mask |= XValue;
5127 if (*strind == '+' || *strind == '-')
5129 if (*strind == '-')
5130 mask |= YNegative;
5131 tempY = strtol (strind, &nextCharacter, 10);
5132 if (strind == nextCharacter)
5133 return 0;
5134 strind = nextCharacter;
5135 mask |= YValue;
5139 /* If strind isn't at the end of the string then it's an invalid
5140 geometry specification. */
5142 if (*strind != '\0')
5143 return 0;
5145 if (mask & XValue)
5146 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
5147 if (mask & YValue)
5148 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
5149 if (mask & WidthValue)
5150 *width = min (tempWidth, UINT_MAX);
5151 if (mask & HeightValue)
5152 *height = min (tempHeight, UINT_MAX);
5153 return mask;
5156 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
5159 /* NS used to define x-parse-geometry in ns-win.el, but that confused
5160 make-docfile: the documentation string in ns-win.el was used for
5161 x-parse-geometry even in non-NS builds.
5163 With two definitions of x-parse-geometry in this file, various
5164 things still get confused (eg M-x apropos documentation), so that
5165 it is best if the two definitions just share the same doc-string.
5167 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
5168 doc: /* Parse a display geometry string STRING.
5169 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
5170 The properties returned may include `top', `left', `height', and `width'.
5171 For X, the value of `left' or `top' may be an integer,
5172 or a list (+ N) meaning N pixels relative to top/left corner,
5173 or a list (- N) meaning -N pixels relative to bottom/right corner.
5174 On Nextstep, this just calls `ns-parse-geometry'. */)
5175 (Lisp_Object string)
5177 int geometry, x, y;
5178 unsigned int width, height;
5179 Lisp_Object result;
5181 CHECK_STRING (string);
5183 #ifdef HAVE_NS
5184 if (strchr (SSDATA (string), ' ') != NULL)
5185 return call1 (Qns_parse_geometry, string);
5186 #endif
5187 geometry = XParseGeometry (SSDATA (string),
5188 &x, &y, &width, &height);
5189 result = Qnil;
5190 if (geometry & XValue)
5192 Lisp_Object element;
5194 if (x >= 0 && (geometry & XNegative))
5195 element = list3 (Qleft, Qminus, make_number (-x));
5196 else if (x < 0 && ! (geometry & XNegative))
5197 element = list3 (Qleft, Qplus, make_number (x));
5198 else
5199 element = Fcons (Qleft, make_number (x));
5200 result = Fcons (element, result);
5203 if (geometry & YValue)
5205 Lisp_Object element;
5207 if (y >= 0 && (geometry & YNegative))
5208 element = list3 (Qtop, Qminus, make_number (-y));
5209 else if (y < 0 && ! (geometry & YNegative))
5210 element = list3 (Qtop, Qplus, make_number (y));
5211 else
5212 element = Fcons (Qtop, make_number (y));
5213 result = Fcons (element, result);
5216 if (geometry & WidthValue)
5217 result = Fcons (Fcons (Qwidth, make_number (width)), result);
5218 if (geometry & HeightValue)
5219 result = Fcons (Fcons (Qheight, make_number (height)), result);
5221 return result;
5225 /* Calculate the desired size and position of frame F.
5226 Return the flags saying which aspects were specified.
5228 Also set the win_gravity and size_hint_flags of F.
5230 Adjust height for toolbar if TOOLBAR_P is 1.
5232 This function does not make the coordinates positive. */
5234 #define DEFAULT_ROWS 36
5235 #define DEFAULT_COLS 80
5237 long
5238 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x_width, int *x_height)
5240 Lisp_Object height, width, user_size, top, left, user_position;
5241 long window_prompting = 0;
5242 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
5243 int parent_done = -1, outer_done = -1;
5245 /* Default values if we fall through.
5246 Actually, if that happens we should get
5247 window manager prompting. */
5248 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
5249 SET_FRAME_COLS (f, DEFAULT_COLS);
5250 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
5251 SET_FRAME_LINES (f, DEFAULT_ROWS);
5253 /* Window managers expect that if program-specified
5254 positions are not (0,0), they're intentional, not defaults. */
5255 f->top_pos = 0;
5256 f->left_pos = 0;
5258 /* Calculate a tool bar height so that the user gets a text display
5259 area of the size he specified with -g or via .Xdefaults. Later
5260 changes of the tool bar height don't change the frame size. This
5261 is done so that users can create tall Emacs frames without having
5262 to guess how tall the tool bar will get. */
5263 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
5265 if (frame_default_tool_bar_height)
5266 FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
5267 else
5269 int margin, relief;
5271 relief = (tool_bar_button_relief >= 0
5272 ? tool_bar_button_relief
5273 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
5275 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
5276 margin = XFASTINT (Vtool_bar_button_margin);
5277 else if (CONSP (Vtool_bar_button_margin)
5278 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
5279 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
5280 else
5281 margin = 0;
5283 FRAME_TOOL_BAR_HEIGHT (f)
5284 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5288 /* Ensure that earlier new_width and new_height settings won't
5289 override what we specify below. */
5290 f->new_width = f->new_height = 0;
5292 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
5293 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
5294 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
5296 if (!EQ (width, Qunbound))
5298 if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
5300 CHECK_NUMBER (XCDR (width));
5301 if ((XINT (XCDR (width)) < 0 || XINT (XCDR (width)) > INT_MAX))
5302 xsignal1 (Qargs_out_of_range, XCDR (width));
5304 SET_FRAME_WIDTH (f, XINT (XCDR (width)));
5305 f->inhibit_horizontal_resize = true;
5306 *x_width = XINT (XCDR (width));
5308 else if (FLOATP (width))
5310 double d_width = XFLOAT_DATA (width);
5312 if (d_width < 0.0 || d_width > 1.0)
5313 xsignal1 (Qargs_out_of_range, width);
5314 else
5316 int new_width = frame_float (f, width, FRAME_FLOAT_WIDTH,
5317 &parent_done, &outer_done, -1);
5319 if (new_width > -1)
5320 SET_FRAME_WIDTH (f, new_width);
5323 else
5325 CHECK_NUMBER (width);
5326 if ((XINT (width) < 0 || XINT (width) > INT_MAX))
5327 xsignal1 (Qargs_out_of_range, width);
5329 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
5333 if (!EQ (height, Qunbound))
5335 if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
5337 CHECK_NUMBER (XCDR (height));
5338 if ((XINT (XCDR (height)) < 0 || XINT (XCDR (height)) > INT_MAX))
5339 xsignal1 (Qargs_out_of_range, XCDR (height));
5341 SET_FRAME_HEIGHT (f, XINT (XCDR (height)));
5342 f->inhibit_vertical_resize = true;
5343 *x_height = XINT (XCDR (height));
5345 else if (FLOATP (height))
5347 double d_height = XFLOAT_DATA (height);
5349 if (d_height < 0.0 || d_height > 1.0)
5350 xsignal1 (Qargs_out_of_range, height);
5351 else
5353 int new_height = frame_float (f, height, FRAME_FLOAT_HEIGHT,
5354 &parent_done, &outer_done, -1);
5356 if (new_height > -1)
5357 SET_FRAME_HEIGHT (f, new_height);
5360 else
5362 CHECK_NUMBER (height);
5363 if ((XINT (height) < 0) || (XINT (height) > INT_MAX))
5364 xsignal1 (Qargs_out_of_range, height);
5366 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
5370 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
5371 if (!NILP (user_size) && !EQ (user_size, Qunbound))
5372 window_prompting |= USSize;
5373 else
5374 window_prompting |= PSize;
5377 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
5378 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
5379 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
5380 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
5382 if (EQ (top, Qminus))
5384 f->top_pos = 0;
5385 window_prompting |= YNegative;
5387 else if (CONSP (top) && EQ (XCAR (top), Qminus)
5388 && CONSP (XCDR (top))
5389 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
5391 f->top_pos = - XINT (XCAR (XCDR (top)));
5392 window_prompting |= YNegative;
5394 else if (CONSP (top) && EQ (XCAR (top), Qplus)
5395 && CONSP (XCDR (top))
5396 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
5398 f->top_pos = XINT (XCAR (XCDR (top)));
5400 else if (FLOATP (top))
5401 f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
5402 &outer_done, 0);
5403 else if (EQ (top, Qunbound))
5404 f->top_pos = 0;
5405 else
5407 CHECK_TYPE_RANGED_INTEGER (int, top);
5408 f->top_pos = XINT (top);
5409 if (f->top_pos < 0)
5410 window_prompting |= YNegative;
5413 if (EQ (left, Qminus))
5415 f->left_pos = 0;
5416 window_prompting |= XNegative;
5418 else if (CONSP (left) && EQ (XCAR (left), Qminus)
5419 && CONSP (XCDR (left))
5420 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
5422 f->left_pos = - XINT (XCAR (XCDR (left)));
5423 window_prompting |= XNegative;
5425 else if (CONSP (left) && EQ (XCAR (left), Qplus)
5426 && CONSP (XCDR (left))
5427 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
5429 f->left_pos = XINT (XCAR (XCDR (left)));
5431 else if (FLOATP (left))
5432 f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
5433 &outer_done, 0);
5434 else if (EQ (left, Qunbound))
5435 f->left_pos = 0;
5436 else
5438 CHECK_TYPE_RANGED_INTEGER (int, left);
5439 f->left_pos = XINT (left);
5440 if (f->left_pos < 0)
5441 window_prompting |= XNegative;
5444 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
5445 window_prompting |= USPosition;
5446 else
5447 window_prompting |= PPosition;
5450 if (window_prompting & XNegative)
5452 if (window_prompting & YNegative)
5453 f->win_gravity = SouthEastGravity;
5454 else
5455 f->win_gravity = NorthEastGravity;
5457 else
5459 if (window_prompting & YNegative)
5460 f->win_gravity = SouthWestGravity;
5461 else
5462 f->win_gravity = NorthWestGravity;
5465 f->size_hint_flags = window_prompting;
5467 return window_prompting;
5472 #endif /* HAVE_WINDOW_SYSTEM */
5474 void
5475 frame_make_pointer_invisible (struct frame *f)
5477 if (! NILP (Vmake_pointer_invisible))
5479 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
5480 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5482 f->mouse_moved = 0;
5483 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
5484 f->pointer_invisible = 1;
5489 void
5490 frame_make_pointer_visible (struct frame *f)
5492 /* We don't check Vmake_pointer_invisible here in case the
5493 pointer was invisible when Vmake_pointer_invisible was set to nil. */
5494 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
5495 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5497 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
5498 f->pointer_invisible = 0;
5502 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
5503 Sframe_pointer_visible_p, 0, 1, 0,
5504 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
5505 Otherwise it returns nil. FRAME omitted or nil means the
5506 selected frame. This is useful when `make-pointer-invisible' is set. */)
5507 (Lisp_Object frame)
5509 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
5514 /***********************************************************************
5515 Multimonitor data
5516 ***********************************************************************/
5518 #ifdef HAVE_WINDOW_SYSTEM
5520 # if (defined HAVE_NS \
5521 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
5522 void
5523 free_monitors (struct MonitorInfo *monitors, int n_monitors)
5525 int i;
5526 for (i = 0; i < n_monitors; ++i)
5527 xfree (monitors[i].name);
5528 xfree (monitors);
5530 # endif
5532 Lisp_Object
5533 make_monitor_attribute_list (struct MonitorInfo *monitors,
5534 int n_monitors,
5535 int primary_monitor,
5536 Lisp_Object monitor_frames,
5537 const char *source)
5539 Lisp_Object attributes_list = Qnil;
5540 Lisp_Object primary_monitor_attributes = Qnil;
5541 int i;
5543 for (i = 0; i < n_monitors; ++i)
5545 Lisp_Object geometry, workarea, attributes = Qnil;
5546 struct MonitorInfo *mi = &monitors[i];
5548 if (mi->geom.width == 0) continue;
5550 workarea = list4i (mi->work.x, mi->work.y,
5551 mi->work.width, mi->work.height);
5552 geometry = list4i (mi->geom.x, mi->geom.y,
5553 mi->geom.width, mi->geom.height);
5554 attributes = Fcons (Fcons (Qsource, build_string (source)),
5555 attributes);
5556 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
5557 attributes);
5558 attributes = Fcons (Fcons (Qmm_size,
5559 list2i (mi->mm_width, mi->mm_height)),
5560 attributes);
5561 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5562 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5563 if (mi->name)
5564 attributes = Fcons (Fcons (Qname, make_string (mi->name,
5565 strlen (mi->name))),
5566 attributes);
5568 if (i == primary_monitor)
5569 primary_monitor_attributes = attributes;
5570 else
5571 attributes_list = Fcons (attributes, attributes_list);
5574 if (!NILP (primary_monitor_attributes))
5575 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
5576 return attributes_list;
5579 #endif /* HAVE_WINDOW_SYSTEM */
5582 /***********************************************************************
5583 Initialization
5584 ***********************************************************************/
5586 void
5587 syms_of_frame (void)
5589 DEFSYM (Qframep, "framep");
5590 DEFSYM (Qframe_live_p, "frame-live-p");
5591 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
5592 DEFSYM (Qdisplay_monitor_attributes_list, "display-monitor-attributes-list");
5593 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
5594 DEFSYM (Qexplicit_name, "explicit-name");
5595 DEFSYM (Qheight, "height");
5596 DEFSYM (Qicon, "icon");
5597 DEFSYM (Qminibuffer, "minibuffer");
5598 DEFSYM (Qundecorated, "undecorated");
5599 DEFSYM (Qno_special_glyphs, "no-special-glyphs");
5600 DEFSYM (Qparent_frame, "parent-frame");
5601 DEFSYM (Qskip_taskbar, "skip-taskbar");
5602 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
5603 DEFSYM (Qno_accept_focus, "no-accept-focus");
5604 DEFSYM (Qz_group, "z-group");
5605 DEFSYM (Qoverride_redirect, "override-redirect");
5606 DEFSYM (Qdelete_before, "delete-before");
5607 DEFSYM (Qmodeline, "modeline");
5608 DEFSYM (Qonly, "only");
5609 DEFSYM (Qnone, "none");
5610 DEFSYM (Qwidth, "width");
5611 DEFSYM (Qtext_pixels, "text-pixels");
5612 DEFSYM (Qgeometry, "geometry");
5613 DEFSYM (Qicon_left, "icon-left");
5614 DEFSYM (Qicon_top, "icon-top");
5615 DEFSYM (Qtooltip, "tooltip");
5616 DEFSYM (Quser_position, "user-position");
5617 DEFSYM (Quser_size, "user-size");
5618 DEFSYM (Qwindow_id, "window-id");
5619 #ifdef HAVE_X_WINDOWS
5620 DEFSYM (Qouter_window_id, "outer-window-id");
5621 #endif
5622 DEFSYM (Qparent_id, "parent-id");
5623 DEFSYM (Qx, "x");
5624 DEFSYM (Qw32, "w32");
5625 DEFSYM (Qpc, "pc");
5626 DEFSYM (Qns, "ns");
5627 DEFSYM (Qvisible, "visible");
5628 DEFSYM (Qbuffer_predicate, "buffer-predicate");
5629 DEFSYM (Qbuffer_list, "buffer-list");
5630 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
5631 DEFSYM (Qdisplay_type, "display-type");
5632 DEFSYM (Qbackground_mode, "background-mode");
5633 DEFSYM (Qnoelisp, "noelisp");
5634 DEFSYM (Qtty_color_mode, "tty-color-mode");
5635 DEFSYM (Qtty, "tty");
5636 DEFSYM (Qtty_type, "tty-type");
5638 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
5640 DEFSYM (Qfullwidth, "fullwidth");
5641 DEFSYM (Qfullheight, "fullheight");
5642 DEFSYM (Qfullboth, "fullboth");
5643 DEFSYM (Qmaximized, "maximized");
5644 DEFSYM (Qx_resource_name, "x-resource-name");
5645 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
5647 DEFSYM (Qworkarea, "workarea");
5648 DEFSYM (Qmm_size, "mm-size");
5649 DEFSYM (Qframes, "frames");
5650 DEFSYM (Qsource, "source");
5652 DEFSYM (Qframe_edges, "frame-edges");
5653 DEFSYM (Qouter_edges, "outer-edges");
5654 DEFSYM (Qouter_position, "outer-position");
5655 DEFSYM (Qouter_size, "outer-size");
5656 DEFSYM (Qnative_edges, "native-edges");
5657 DEFSYM (Qinner_edges, "inner-edges");
5658 DEFSYM (Qexternal_border_size, "external-border-size");
5659 DEFSYM (Qtitle_bar_size, "title-bar-size");
5660 DEFSYM (Qmenu_bar_external, "menu-bar-external");
5661 DEFSYM (Qmenu_bar_size, "menu-bar-size");
5662 DEFSYM (Qtool_bar_external, "tool-bar-external");
5663 DEFSYM (Qtool_bar_size, "tool-bar-size");
5664 /* The following are used for frame_size_history. */
5665 DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
5666 DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
5667 DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
5668 DEFSYM (Qx_set_frame_parameters, "x-set-frame-parameters");
5669 DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
5670 DEFSYM (Qset_frame_size, "set-frame-size");
5671 DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
5672 DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
5673 DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
5674 DEFSYM (Qxg_frame_resized, "xg-frame-resized");
5675 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
5676 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
5677 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
5678 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
5679 DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
5680 DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
5681 DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
5682 DEFSYM (Qx_net_wm_state, "x-net-wm-state");
5683 DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
5684 DEFSYM (Qtb_size_cb, "tb-size-cb");
5685 DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
5686 DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
5687 DEFSYM (Qx_set_menu_bar_lines, "x-set-menu-bar-lines");
5688 DEFSYM (Qchange_frame_size, "change-frame-size");
5689 DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
5690 DEFSYM (Qset_window_configuration, "set-window-configuration");
5691 DEFSYM (Qx_create_frame_1, "x-create-frame-1");
5692 DEFSYM (Qx_create_frame_2, "x-create-frame-2");
5693 DEFSYM (Qterminal_frame, "terminal-frame");
5695 #ifdef HAVE_NS
5696 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
5697 #endif
5698 #ifdef NS_IMPL_COCOA
5699 DEFSYM (Qns_appearance, "ns-appearance");
5700 DEFSYM (Qns_transparent_titlebar, "ns-transparent-titlebar");
5701 #endif
5703 DEFSYM (Qalpha, "alpha");
5704 DEFSYM (Qauto_lower, "auto-lower");
5705 DEFSYM (Qauto_raise, "auto-raise");
5706 DEFSYM (Qborder_color, "border-color");
5707 DEFSYM (Qborder_width, "border-width");
5708 DEFSYM (Qouter_border_width, "outer-border-width");
5709 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
5710 DEFSYM (Qcursor_color, "cursor-color");
5711 DEFSYM (Qcursor_type, "cursor-type");
5712 DEFSYM (Qfont_backend, "font-backend");
5713 DEFSYM (Qfullscreen, "fullscreen");
5714 DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
5715 DEFSYM (Qicon_name, "icon-name");
5716 DEFSYM (Qicon_type, "icon-type");
5717 DEFSYM (Qinternal_border_width, "internal-border-width");
5718 DEFSYM (Qleft_fringe, "left-fringe");
5719 DEFSYM (Qline_spacing, "line-spacing");
5720 DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
5721 DEFSYM (Qupdate_frame_menubar, "update-frame-menubar");
5722 DEFSYM (Qfree_frame_menubar_1, "free-frame-menubar-1");
5723 DEFSYM (Qfree_frame_menubar_2, "free-frame-menubar-2");
5724 DEFSYM (Qmouse_color, "mouse-color");
5725 DEFSYM (Qname, "name");
5726 DEFSYM (Qright_divider_width, "right-divider-width");
5727 DEFSYM (Qright_fringe, "right-fringe");
5728 DEFSYM (Qscreen_gamma, "screen-gamma");
5729 DEFSYM (Qscroll_bar_background, "scroll-bar-background");
5730 DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
5731 DEFSYM (Qscroll_bar_height, "scroll-bar-height");
5732 DEFSYM (Qscroll_bar_width, "scroll-bar-width");
5733 DEFSYM (Qsticky, "sticky");
5734 DEFSYM (Qtitle, "title");
5735 DEFSYM (Qtool_bar_lines, "tool-bar-lines");
5736 DEFSYM (Qtool_bar_position, "tool-bar-position");
5737 DEFSYM (Qunsplittable, "unsplittable");
5738 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
5739 DEFSYM (Qvisibility, "visibility");
5740 DEFSYM (Qwait_for_wm, "wait-for-wm");
5741 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5742 DEFSYM (Qno_other_frame, "no-other-frame");
5743 DEFSYM (Qbelow, "below");
5744 DEFSYM (Qabove_suspended, "above-suspended");
5745 DEFSYM (Qmin_width, "min-width");
5746 DEFSYM (Qmin_height, "min-height");
5747 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
5748 DEFSYM (Qkeep_ratio, "keep-ratio");
5749 DEFSYM (Qwidth_only, "width-only");
5750 DEFSYM (Qheight_only, "height-only");
5751 DEFSYM (Qleft_only, "left-only");
5752 DEFSYM (Qtop_only, "top-only");
5753 DEFSYM (Qiconify_top_level, "iconify-top-level");
5754 DEFSYM (Qmake_invisible, "make-invisible");
5757 int i;
5759 for (i = 0; i < ARRAYELTS (frame_parms); i++)
5761 Lisp_Object v = (frame_parms[i].sym < 0
5762 ? intern_c_string (frame_parms[i].name)
5763 : builtin_lisp_symbol (frame_parms[i].sym));
5764 Fput (v, Qx_frame_parameter, make_number (i));
5768 #ifdef HAVE_WINDOW_SYSTEM
5769 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
5770 doc: /* The name Emacs uses to look up X resources.
5771 `x-get-resource' uses this as the first component of the instance name
5772 when requesting resource values.
5773 Emacs initially sets `x-resource-name' to the name under which Emacs
5774 was invoked, or to the value specified with the `-name' or `-rn'
5775 switches, if present.
5777 It may be useful to bind this variable locally around a call
5778 to `x-get-resource'. See also the variable `x-resource-class'. */);
5779 Vx_resource_name = Qnil;
5781 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
5782 doc: /* The class Emacs uses to look up X resources.
5783 `x-get-resource' uses this as the first component of the instance class
5784 when requesting resource values.
5786 Emacs initially sets `x-resource-class' to "Emacs".
5788 Setting this variable permanently is not a reasonable thing to do,
5789 but binding this variable locally around a call to `x-get-resource'
5790 is a reasonable practice. See also the variable `x-resource-name'. */);
5791 Vx_resource_class = build_string (EMACS_CLASS);
5793 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
5794 doc: /* The lower limit of the frame opacity (alpha transparency).
5795 The value should range from 0 (invisible) to 100 (completely opaque).
5796 You can also use a floating number between 0.0 and 1.0. */);
5797 Vframe_alpha_lower_limit = make_number (20);
5798 #endif
5800 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
5801 doc: /* Alist of default values for frame creation.
5802 These may be set in your init file, like this:
5803 (setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
5804 These override values given in window system configuration data,
5805 including X Windows' defaults database.
5806 For values specific to the first Emacs frame, see `initial-frame-alist'.
5807 For window-system specific values, see `window-system-default-frame-alist'.
5808 For values specific to the separate minibuffer frame, see
5809 `minibuffer-frame-alist'.
5810 The `menu-bar-lines' element of the list controls whether new frames
5811 have menu bars; `menu-bar-mode' works by altering this element.
5812 Setting this variable does not affect existing frames, only new ones. */);
5813 Vdefault_frame_alist = Qnil;
5815 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
5816 doc: /* Default position of vertical scroll bars on this window-system. */);
5817 #ifdef HAVE_WINDOW_SYSTEM
5818 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
5819 /* MS-Windows, macOS, and GTK have scroll bars on the right by
5820 default. */
5821 Vdefault_frame_scroll_bars = Qright;
5822 #else
5823 Vdefault_frame_scroll_bars = Qleft;
5824 #endif
5825 #else
5826 Vdefault_frame_scroll_bars = Qnil;
5827 #endif
5829 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
5830 scroll_bar_adjust_thumb_portion_p,
5831 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
5832 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
5833 even if the end of the buffer is shown (i.e. overscrolling).
5834 Set to nil if you want the thumb to be at the bottom when the end of the buffer
5835 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
5836 is visible. In this case you can not overscroll. */);
5837 scroll_bar_adjust_thumb_portion_p = 1;
5839 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
5840 doc: /* The initial frame-object, which represents Emacs's stdout. */);
5842 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
5843 doc: /* If non-nil, function to transform normal value of `mouse-position'.
5844 `mouse-position' and `mouse-pixel-position' call this function, passing their
5845 usual return value as argument, and return whatever this function returns.
5846 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
5847 which need to do mouse handling at the Lisp level. */);
5848 Vmouse_position_function = Qnil;
5850 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
5851 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
5852 If the value is an integer, highlighting is only shown after moving the
5853 mouse, while keyboard input turns off the highlight even when the mouse
5854 is over the clickable text. However, the mouse shape still indicates
5855 when the mouse is over clickable text. */);
5856 Vmouse_highlight = Qt;
5858 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
5859 doc: /* If non-nil, make pointer invisible while typing.
5860 The pointer becomes visible again when the mouse is moved. */);
5861 Vmake_pointer_invisible = Qt;
5863 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
5864 doc: /* Normal hook run when a frame gains input focus.
5865 The frame gaining focus is selected at the time this hook is run. */);
5866 Vfocus_in_hook = Qnil;
5868 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
5869 doc: /* Normal hook run when all frames lost input focus. */);
5870 Vfocus_out_hook = Qnil;
5872 DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
5873 doc: /* Functions run after a frame was moved.
5874 The functions are run with one arg, the frame that moved. */);
5875 Vmove_frame_functions = Qnil;
5877 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
5878 doc: /* Functions run before deleting a frame.
5879 The functions are run with one arg, the frame to be deleted.
5880 See `delete-frame'.
5882 Note that functions in this list may be called just before the frame is
5883 actually deleted, or some time later (or even both when an earlier function
5884 in `delete-frame-functions' (indirectly) calls `delete-frame'
5885 recursively). */);
5886 Vdelete_frame_functions = Qnil;
5887 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
5889 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
5890 doc: /* Non-nil if Menu-Bar mode is enabled.
5891 See the command `menu-bar-mode' for a description of this minor mode.
5892 Setting this variable directly does not take effect;
5893 either customize it (see the info node `Easy Customization')
5894 or call the function `menu-bar-mode'. */);
5895 Vmenu_bar_mode = Qt;
5897 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
5898 doc: /* Non-nil if Tool-Bar mode is enabled.
5899 See the command `tool-bar-mode' for a description of this minor mode.
5900 Setting this variable directly does not take effect;
5901 either customize it (see the info node `Easy Customization')
5902 or call the function `tool-bar-mode'. */);
5903 #ifdef HAVE_WINDOW_SYSTEM
5904 Vtool_bar_mode = Qt;
5905 #else
5906 Vtool_bar_mode = Qnil;
5907 #endif
5909 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
5910 doc: /* Minibuffer-less frames by default use this frame's minibuffer.
5911 Emacs consults this variable only when creating a minibuffer-less frame
5912 and no explicit minibuffer window has been specified for that frame via
5913 the `minibuffer' frame parameter. Once such a frame has been created,
5914 setting this variable does not change that frame's previous association.
5916 This variable is local to the current terminal and cannot be buffer-local. */);
5918 DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
5919 doc: /* Non-nil if window system changes focus when you move the mouse.
5920 You should set this variable to tell Emacs how your window manager
5921 handles focus, since there is no way in general for Emacs to find out
5922 automatically.
5924 There are three meaningful values:
5926 - The default nil should be used when your window manager follows a
5927 "click-to-focus" policy where you have to click the mouse inside of a
5928 frame in order for that frame to get focus.
5930 - The value t should be used when your window manager has the focus
5931 automatically follow the position of the mouse pointer but a window
5932 that gains focus is not raised automatically.
5934 - The value `auto-raise' should be used when your window manager has the
5935 focus automatically follow the position of the mouse pointer and a
5936 window that gains focus is raised automatically.
5938 If this option is non-nil, Emacs moves the mouse pointer to the frame
5939 selected by `select-frame-set-input-focus'. This function is used by a
5940 number of commands like, for example, `other-frame' and `pop-to-buffer'.
5941 If this option is nil and your focus follows mouse window manager does
5942 not autonomously move the mouse pointer to the newly selected frame, the
5943 previously selected window manager window might get reselected instead
5944 immediately.
5946 The distinction between the values t and `auto-raise' is not needed for
5947 "normal" frames because the window manager takes care of raising them.
5948 Setting this to `auto-raise' will, however, override the standard
5949 behavior of a window manager that does not automatically raise the frame
5950 that gets focus. Setting this to `auto-raise' is also necessary to
5951 automatically raise child frames which are usually left alone by the
5952 window manager.
5954 Note that this option does not distinguish "sloppy" focus (where the
5955 frame that previously had focus retains focus as long as the mouse
5956 pointer does not move into another window manager window) from "strict"
5957 focus (where a frame immediately loses focus when it's left by the mouse
5958 pointer).
5960 In order to extend a "focus follows mouse" policy to individual Emacs
5961 windows, customize the variable `mouse-autoselect-window'. */);
5962 focus_follows_mouse = Qnil;
5964 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5965 doc: /* Non-nil means resize frames pixelwise.
5966 If this option is nil, resizing a frame rounds its sizes to the frame's
5967 current values of `frame-char-height' and `frame-char-width'. If this
5968 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5969 by one pixel.
5971 With some window managers you may have to set this to non-nil in order
5972 to set the size of a frame in pixels, to maximize frames or to make them
5973 fullscreen. To resize your initial frame pixelwise, set this option to
5974 a non-nil value in your init file. */);
5975 frame_resize_pixelwise = 0;
5977 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
5978 doc: /* Whether frames should be resized implicitly.
5979 If this option is nil, setting font, menu bar, tool bar, internal
5980 borders, fringes or scroll bars of a specific frame may resize the frame
5981 in order to preserve the number of columns or lines it displays. If
5982 this option is t, no such resizing is done. Note that the size of
5983 fullscreen and maximized frames, the height of fullheight frames and the
5984 width of fullwidth frames never change implicitly.
5986 The value of this option can be also be a list of frame parameters. In
5987 this case, resizing is inhibited when changing a parameter that appears
5988 in that list. The parameters currently handled by this option include
5989 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
5990 `tool-bar-lines'.
5992 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
5993 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
5994 `right-fringe' is handled as if the frame contained just one live
5995 window. This means, for example, that removing vertical scroll bars on
5996 a frame containing several side by side windows will shrink the frame
5997 width by the width of one scroll bar provided this option is nil and
5998 keep it unchanged if this option is either t or a list containing
5999 `vertical-scroll-bars'.
6001 The default value is \\='(tool-bar-lines) on Lucid, Motif and Windows
6002 \(which means that adding/removing a tool bar does not change the frame
6003 height), nil on all other window systems including GTK+ (which means
6004 that changing any of the parameters listed above may change the size of
6005 the frame), and t otherwise (which means the frame size never changes
6006 implicitly when there's no window system support).
6008 Note that when a frame is not large enough to accommodate a change of
6009 any of the parameters listed above, Emacs may try to enlarge the frame
6010 even if this option is non-nil. */);
6011 #if defined (HAVE_WINDOW_SYSTEM)
6012 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
6013 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
6014 #else
6015 frame_inhibit_implied_resize = Qnil;
6016 #endif
6017 #else
6018 frame_inhibit_implied_resize = Qt;
6019 #endif
6021 DEFVAR_LISP ("frame-size-history", frame_size_history,
6022 doc: /* History of frame size adjustments.
6023 If non-nil, list recording frame size adjustment. Adjustments are
6024 recorded only if the first element of this list is a positive number.
6025 Adding an adjustment decrements that number by one.
6027 The remaining elements are the adjustments. Each adjustment is a list
6028 of four elements `frame', `function', `sizes' and `more'. `frame' is
6029 the affected frame and `function' the invoking function. `sizes' is
6030 usually a list of four elements `old-width', `old-height', `new-width'
6031 and `new-height' representing the old and new sizes recorded/requested
6032 by `function'. `more' is a list with additional information.
6034 The function `frame--size-history' displays the value of this variable
6035 in a more readable form. */);
6036 frame_size_history = Qnil;
6038 DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame,
6039 doc: /* Non-nil means reuse hidden tooltip frames.
6040 When this is nil, delete a tooltip frame when hiding the associated
6041 tooltip. When this is non-nil, make the tooltip frame invisible only,
6042 so it can be reused when the next tooltip is shown.
6044 Setting this to non-nil may drastically reduce the consing overhead
6045 incurred by creating new tooltip frames. However, a value of non-nil
6046 means also that intermittent changes of faces or `default-frame-alist'
6047 are not applied when showing a tooltip in a reused frame.
6049 This variable is effective only with the X toolkit (and there only when
6050 Gtk+ tooltips are not used) and on Windows. */);
6051 tooltip_reuse_hidden_frame = false;
6053 DEFVAR_LISP ("iconify-child-frame", iconify_child_frame,
6054 doc: /* How to handle iconification of child frames.
6055 This variable tells Emacs how to proceed when it is asked to iconify a
6056 child frame. If it is nil, `iconify-frame' will do nothing when invoked
6057 on a child frame. If it is `iconify-top-level', Emacs will try to
6058 iconify the top level frame associated with this child frame instead.
6059 If it is `make-invisible', Emacs will try to make this child frame
6060 invisible instead.
6062 Any other value means to try iconifying the child frame. Since such an
6063 attempt is not honored by all window managers and may even lead to
6064 making the child frame unresponsive to user actions, the default is to
6065 iconify the top level frame instead. */);
6066 iconify_child_frame = Qiconify_top_level;
6068 staticpro (&Vframe_list);
6070 defsubr (&Sframep);
6071 defsubr (&Sframe_live_p);
6072 defsubr (&Swindow_system);
6073 defsubr (&Sframe_windows_min_size);
6074 defsubr (&Smake_terminal_frame);
6075 defsubr (&Shandle_switch_frame);
6076 defsubr (&Sselect_frame);
6077 defsubr (&Sselected_frame);
6078 defsubr (&Sframe_list);
6079 defsubr (&Sframe_parent);
6080 defsubr (&Sframe_ancestor_p);
6081 defsubr (&Snext_frame);
6082 defsubr (&Sprevious_frame);
6083 defsubr (&Slast_nonminibuf_frame);
6084 defsubr (&Sdelete_frame);
6085 defsubr (&Smouse_position);
6086 defsubr (&Smouse_pixel_position);
6087 defsubr (&Sset_mouse_position);
6088 defsubr (&Sset_mouse_pixel_position);
6089 #if 0
6090 defsubr (&Sframe_configuration);
6091 defsubr (&Srestore_frame_configuration);
6092 #endif
6093 defsubr (&Smake_frame_visible);
6094 defsubr (&Smake_frame_invisible);
6095 defsubr (&Siconify_frame);
6096 defsubr (&Sframe_visible_p);
6097 defsubr (&Svisible_frame_list);
6098 defsubr (&Sraise_frame);
6099 defsubr (&Slower_frame);
6100 defsubr (&Sx_focus_frame);
6101 defsubr (&Sframe_after_make_frame);
6102 defsubr (&Sredirect_frame_focus);
6103 defsubr (&Sframe_focus);
6104 defsubr (&Sframe_parameters);
6105 defsubr (&Sframe_parameter);
6106 defsubr (&Smodify_frame_parameters);
6107 defsubr (&Sframe_char_height);
6108 defsubr (&Sframe_char_width);
6109 defsubr (&Sframe_native_height);
6110 defsubr (&Sframe_native_width);
6111 defsubr (&Sframe_text_cols);
6112 defsubr (&Sframe_text_lines);
6113 defsubr (&Sframe_total_cols);
6114 defsubr (&Sframe_total_lines);
6115 defsubr (&Sframe_text_width);
6116 defsubr (&Sframe_text_height);
6117 defsubr (&Sscroll_bar_width);
6118 defsubr (&Sscroll_bar_height);
6119 defsubr (&Sfringe_width);
6120 defsubr (&Sframe_internal_border_width);
6121 defsubr (&Sright_divider_width);
6122 defsubr (&Sbottom_divider_width);
6123 defsubr (&Stool_bar_pixel_width);
6124 defsubr (&Sset_frame_height);
6125 defsubr (&Sset_frame_width);
6126 defsubr (&Sset_frame_size);
6127 defsubr (&Sframe_position);
6128 defsubr (&Sset_frame_position);
6129 defsubr (&Sframe_pointer_visible_p);
6131 #ifdef HAVE_WINDOW_SYSTEM
6132 defsubr (&Sx_get_resource);
6133 defsubr (&Sx_parse_geometry);
6134 #endif