; Add further traces to tramp-tests.el
[emacs.git] / src / frame.c
blob1e5e4bbdb48d3ac23ffd97a453856c344da1b147
1 /* Generic frame functions.
3 Copyright (C) 1993-1995, 1997, 1999-2017 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <limits.h>
27 #include <c-ctype.h>
29 #include "lisp.h"
31 #ifdef HAVE_WINDOW_SYSTEM
32 #include TERM_HEADER
33 #endif /* HAVE_WINDOW_SYSTEM */
35 #include "buffer.h"
36 /* These help us bind and responding to switch-frame events. */
37 #include "keyboard.h"
38 #include "frame.h"
39 #include "blockinput.h"
40 #include "termchar.h"
41 #include "termhooks.h"
42 #include "dispextern.h"
43 #include "window.h"
44 #ifdef HAVE_WINDOW_SYSTEM
45 #include "fontset.h"
46 #endif
47 #include "cm.h"
48 #ifdef MSDOS
49 #include "msdos.h"
50 #include "dosfns.h"
51 #endif
52 #ifdef USE_X_TOOLKIT
53 #include "widget.h"
54 #endif
56 /* The currently selected frame. */
58 Lisp_Object selected_frame;
60 /* A frame which is not just a mini-buffer, or NULL if there are no such
61 frames. This is usually the most recent such frame that was selected. */
63 static struct frame *last_nonminibuf_frame;
65 /* False means there are no visible garbaged frames. */
66 bool frame_garbaged;
68 /* The default tool bar height for future frames. */
69 #if defined USE_GTK || defined HAVE_NS
70 enum { frame_default_tool_bar_height = 0 };
71 #else
72 int frame_default_tool_bar_height;
73 #endif
75 #ifdef HAVE_WINDOW_SYSTEM
76 static void x_report_frame_params (struct frame *, Lisp_Object *);
77 #endif
79 /* These setters are used only in this file, so they can be private. */
80 static void
81 fset_buffer_predicate (struct frame *f, Lisp_Object val)
83 f->buffer_predicate = val;
85 static void
86 fset_minibuffer_window (struct frame *f, Lisp_Object val)
88 f->minibuffer_window = val;
91 struct frame *
92 decode_live_frame (register Lisp_Object frame)
94 if (NILP (frame))
95 frame = selected_frame;
96 CHECK_LIVE_FRAME (frame);
97 return XFRAME (frame);
100 struct frame *
101 decode_any_frame (register Lisp_Object frame)
103 if (NILP (frame))
104 frame = selected_frame;
105 CHECK_FRAME (frame);
106 return XFRAME (frame);
109 #ifdef HAVE_WINDOW_SYSTEM
110 bool
111 display_available (void)
113 return x_display_list != NULL;
115 #endif
117 struct frame *
118 decode_window_system_frame (Lisp_Object frame)
120 struct frame *f = decode_live_frame (frame);
121 check_window_system (f);
122 #ifdef HAVE_WINDOW_SYSTEM
123 return f;
124 #endif
127 void
128 check_window_system (struct frame *f)
130 #ifdef HAVE_WINDOW_SYSTEM
131 if (window_system_available (f))
132 return;
133 #endif
134 error (f ? "Window system frame should be used"
135 : "Window system is not in use or not initialized");
138 /* Return the value of frame parameter PROP in frame FRAME. */
140 Lisp_Object
141 get_frame_param (register struct frame *frame, Lisp_Object prop)
143 register Lisp_Object tem;
145 tem = Fassq (prop, frame->param_alist);
146 if (EQ (tem, Qnil))
147 return tem;
148 return Fcdr (tem);
152 void
153 frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
154 int width, int height, Lisp_Object rest)
156 Lisp_Object frame;
158 XSETFRAME (frame, f);
159 if (CONSP (frame_size_history)
160 && INTEGERP (XCAR (frame_size_history))
161 && 0 < XINT (XCAR (frame_size_history)))
162 frame_size_history =
163 Fcons (make_number (XINT (XCAR (frame_size_history)) - 1),
164 Fcons (list4
165 (frame, fun_symbol,
166 ((width > 0)
167 ? list4 (make_number (FRAME_TEXT_WIDTH (f)),
168 make_number (FRAME_TEXT_HEIGHT (f)),
169 make_number (width),
170 make_number (height))
171 : Qnil),
172 rest),
173 XCDR (frame_size_history)));
177 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
178 state of frame F would be affected by a vertical (horizontal if
179 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
180 parameter that is changed. */
181 bool
182 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
184 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
185 bool inhibit
186 = (f->after_make_frame
187 ? (EQ (frame_inhibit_implied_resize, Qt)
188 || (CONSP (frame_inhibit_implied_resize)
189 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
190 || (horizontal
191 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullheight))
192 || (!horizontal
193 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullwidth))
194 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
195 : ((horizontal && f->inhibit_horizontal_resize)
196 || (!horizontal && f->inhibit_vertical_resize)));
197 if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
198 frame_size_history_add
199 (f, Qframe_inhibit_resize, 0, 0,
200 list5 (horizontal ? Qt : Qnil, parameter,
201 f->after_make_frame ? Qt : Qnil,
202 frame_inhibit_implied_resize,
203 fullscreen));
205 return inhibit;
208 static void
209 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
211 int nlines;
212 int olines = FRAME_MENU_BAR_LINES (f);
214 /* Right now, menu bars don't work properly in minibuf-only frames;
215 most of the commands try to apply themselves to the minibuffer
216 frame itself, and get an error because you can't switch buffers
217 in or split the minibuffer window. */
218 if (FRAME_MINIBUF_ONLY_P (f))
219 return;
221 if (TYPE_RANGED_INTEGERP (int, value))
222 nlines = XINT (value);
223 else
224 nlines = 0;
226 if (nlines != olines)
228 windows_or_buffers_changed = 14;
229 FRAME_MENU_BAR_LINES (f) = nlines;
230 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
231 change_frame_size (f, FRAME_COLS (f),
232 FRAME_LINES (f) + olines - nlines,
233 0, 1, 0, 0);
237 Lisp_Object Vframe_list;
240 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
241 doc: /* Return non-nil if OBJECT is a frame.
242 Value is:
243 t for a termcap frame (a character-only terminal),
244 `x' for an Emacs frame that is really an X window,
245 `w32' for an Emacs frame that is a window on MS-Windows display,
246 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
247 `pc' for a direct-write MS-DOS frame.
248 See also `frame-live-p'. */)
249 (Lisp_Object object)
251 if (!FRAMEP (object))
252 return Qnil;
253 switch (XFRAME (object)->output_method)
255 case output_initial: /* The initial frame is like a termcap frame. */
256 case output_termcap:
257 return Qt;
258 case output_x_window:
259 return Qx;
260 case output_w32:
261 return Qw32;
262 case output_msdos_raw:
263 return Qpc;
264 case output_ns:
265 return Qns;
266 default:
267 emacs_abort ();
271 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
272 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
273 Value is nil if OBJECT is not a live frame. If object is a live
274 frame, the return value indicates what sort of terminal device it is
275 displayed on. See the documentation of `framep' for possible
276 return values. */)
277 (Lisp_Object object)
279 return ((FRAMEP (object)
280 && FRAME_LIVE_P (XFRAME (object)))
281 ? Fframep (object)
282 : Qnil);
285 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
286 doc: /* The name of the window system that FRAME is displaying through.
287 The value is a symbol:
288 nil for a termcap frame (a character-only terminal),
289 `x' for an Emacs frame that is really an X window,
290 `w32' for an Emacs frame that is a window on MS-Windows display,
291 `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
292 `pc' for a direct-write MS-DOS frame.
294 FRAME defaults to the currently selected frame.
296 Use of this function as a predicate is deprecated. Instead,
297 use `display-graphic-p' or any of the other `display-*-p'
298 predicates which report frame's specific UI-related capabilities. */)
299 (Lisp_Object frame)
301 Lisp_Object type;
302 if (NILP (frame))
303 frame = selected_frame;
305 type = Fframep (frame);
307 if (NILP (type))
308 wrong_type_argument (Qframep, frame);
310 if (EQ (type, Qt))
311 return Qnil;
312 else
313 return type;
316 /* Placeholder used by temacs -nw before window.el is loaded. */
317 DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
318 Sframe_windows_min_size, 4, 4, 0,
319 doc: /* */
320 attributes: const)
321 (Lisp_Object frame, Lisp_Object horizontal,
322 Lisp_Object ignore, Lisp_Object pixelwise)
324 return make_number (0);
328 * frame_windows_min_size:
330 * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
331 * of FRAME. If PIXELWISE is non-nil, return the minimum 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 #endif
839 root_window = make_window ();
840 rw = XWINDOW (root_window);
841 if (mini_p)
843 mini_window = make_window ();
844 mw = XWINDOW (mini_window);
845 wset_next (rw, mini_window);
846 wset_prev (mw, root_window);
847 mw->mini = 1;
848 wset_frame (mw, frame);
849 fset_minibuffer_window (f, mini_window);
850 store_frame_param (f, Qminibuffer, Qt);
852 else
854 mini_window = Qnil;
855 wset_next (rw, Qnil);
856 fset_minibuffer_window (f, Qnil);
859 wset_frame (rw, frame);
861 /* 10 is arbitrary,
862 just so that there is "something there."
863 Correct size will be set up later with adjust_frame_size. */
865 SET_FRAME_COLS (f, 10);
866 SET_FRAME_LINES (f, 10);
867 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
868 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
870 rw->total_cols = 10;
871 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
872 rw->total_lines = mini_p ? 9 : 10;
873 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
875 if (mini_p)
877 mw->top_line = rw->total_lines;
878 mw->pixel_top = rw->pixel_height;
879 mw->total_cols = rw->total_cols;
880 mw->pixel_width = rw->pixel_width;
881 mw->total_lines = 1;
882 mw->pixel_height = FRAME_LINE_HEIGHT (f);
885 /* Choose a buffer for the frame's root window. */
887 Lisp_Object buf = Fcurrent_buffer ();
889 /* If current buffer is hidden, try to find another one. */
890 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
891 buf = other_buffer_safely (buf);
893 /* Use set_window_buffer, not Fset_window_buffer, and don't let
894 hooks be run by it. The reason is that the whole frame/window
895 arrangement is not yet fully initialized at this point. Windows
896 don't have the right size, glyph matrices aren't initialized
897 etc. Running Lisp functions at this point surely ends in a
898 SEGV. */
899 set_window_buffer (root_window, buf, 0, 0);
900 fset_buffer_list (f, list1 (buf));
903 if (mini_p)
905 set_window_buffer (mini_window,
906 (NILP (Vminibuffer_list)
907 ? get_minibuffer (0)
908 : Fcar (Vminibuffer_list)),
909 0, 0);
910 /* No horizontal scroll bars in minibuffers. */
911 wset_horizontal_scroll_bar (mw, Qnil);
914 fset_root_window (f, root_window);
915 fset_selected_window (f, root_window);
916 /* Make sure this window seems more recently used than
917 a newly-created, never-selected window. */
918 XWINDOW (f->selected_window)->use_time = ++window_select_count;
920 return f;
923 #ifdef HAVE_WINDOW_SYSTEM
924 /* Make a frame using a separate minibuffer window on another frame.
925 MINI_WINDOW is the minibuffer window to use. nil means use the
926 default (the global minibuffer). */
928 struct frame *
929 make_frame_without_minibuffer (Lisp_Object mini_window, KBOARD *kb,
930 Lisp_Object display)
932 struct frame *f;
934 if (!NILP (mini_window))
935 CHECK_LIVE_WINDOW (mini_window);
937 if (!NILP (mini_window)
938 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
939 error ("Frame and minibuffer must be on the same terminal");
941 /* Make a frame containing just a root window. */
942 f = make_frame (0);
944 if (NILP (mini_window))
946 /* Use default-minibuffer-frame if possible. */
947 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
948 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
950 Lisp_Object frame_dummy;
952 XSETFRAME (frame_dummy, f);
953 /* If there's no minibuffer frame to use, create one. */
954 kset_default_minibuffer_frame
955 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
958 mini_window
959 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
962 fset_minibuffer_window (f, mini_window);
963 store_frame_param (f, Qminibuffer, mini_window);
965 /* Make the chosen minibuffer window display the proper minibuffer,
966 unless it is already showing a minibuffer. */
967 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
968 /* Use set_window_buffer instead of Fset_window_buffer (see
969 discussion of bug#11984, bug#12025, bug#12026). */
970 set_window_buffer (mini_window,
971 (NILP (Vminibuffer_list)
972 ? get_minibuffer (0)
973 : Fcar (Vminibuffer_list)), 0, 0);
974 return f;
977 /* Make a frame containing only a minibuffer window. */
979 struct frame *
980 make_minibuffer_frame (void)
982 /* First make a frame containing just a root window, no minibuffer. */
984 register struct frame *f = make_frame (0);
985 register Lisp_Object mini_window;
986 register Lisp_Object frame;
988 XSETFRAME (frame, f);
990 f->auto_raise = 0;
991 f->auto_lower = 0;
992 f->no_split = 1;
993 f->wants_modeline = 0;
995 /* Now label the root window as also being the minibuffer.
996 Avoid infinite looping on the window chain by marking next pointer
997 as nil. */
999 mini_window = f->root_window;
1000 fset_minibuffer_window (f, mini_window);
1001 store_frame_param (f, Qminibuffer, Qonly);
1002 XWINDOW (mini_window)->mini = 1;
1003 wset_next (XWINDOW (mini_window), Qnil);
1004 wset_prev (XWINDOW (mini_window), Qnil);
1005 wset_frame (XWINDOW (mini_window), frame);
1007 /* Put the proper buffer in that window. */
1009 /* Use set_window_buffer instead of Fset_window_buffer (see
1010 discussion of bug#11984, bug#12025, bug#12026). */
1011 set_window_buffer (mini_window,
1012 (NILP (Vminibuffer_list)
1013 ? get_minibuffer (0)
1014 : Fcar (Vminibuffer_list)), 0, 0);
1015 return f;
1017 #endif /* HAVE_WINDOW_SYSTEM */
1019 /* Construct a frame that refers to a terminal. */
1021 static printmax_t tty_frame_count;
1023 struct frame *
1024 make_initial_frame (void)
1026 struct frame *f;
1027 struct terminal *terminal;
1028 Lisp_Object frame;
1030 eassert (initial_kboard);
1032 /* The first call must initialize Vframe_list. */
1033 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
1034 Vframe_list = Qnil;
1036 terminal = init_initial_terminal ();
1038 f = make_frame (1);
1039 XSETFRAME (frame, f);
1041 Vframe_list = Fcons (frame, Vframe_list);
1043 tty_frame_count = 1;
1044 fset_name (f, build_pure_c_string ("F1"));
1046 SET_FRAME_VISIBLE (f, 1);
1048 f->output_method = terminal->type;
1049 f->terminal = terminal;
1050 f->terminal->reference_count++;
1051 f->output_data.nothing = 0;
1053 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1054 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1056 #ifdef HAVE_WINDOW_SYSTEM
1057 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1058 f->horizontal_scroll_bars = false;
1059 #endif
1061 /* The default value of menu-bar-mode is t. */
1062 set_menu_bar_lines (f, make_number (1), Qnil);
1064 /* Allocate glyph matrices. */
1065 adjust_frame_glyphs (f);
1067 if (!noninteractive)
1068 init_frame_faces (f);
1070 last_nonminibuf_frame = f;
1072 f->can_x_set_window_size = true;
1073 f->after_make_frame = true;
1075 return f;
1079 static struct frame *
1080 make_terminal_frame (struct terminal *terminal)
1082 register struct frame *f;
1083 Lisp_Object frame;
1084 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
1086 if (!terminal->name)
1087 error ("Terminal is not live, can't create new frames on it");
1089 f = make_frame (1);
1091 XSETFRAME (frame, f);
1092 Vframe_list = Fcons (frame, Vframe_list);
1094 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
1096 SET_FRAME_VISIBLE (f, 1);
1098 f->terminal = terminal;
1099 f->terminal->reference_count++;
1100 #ifdef MSDOS
1101 f->output_data.tty->display_info = &the_only_display_info;
1102 if (!inhibit_window_system
1103 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
1104 || XFRAME (selected_frame)->output_method == output_msdos_raw))
1105 f->output_method = output_msdos_raw;
1106 else
1107 f->output_method = output_termcap;
1108 #else /* not MSDOS */
1109 f->output_method = output_termcap;
1110 create_tty_output (f);
1111 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
1112 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
1113 #endif /* not MSDOS */
1115 #ifdef HAVE_WINDOW_SYSTEM
1116 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
1117 f->horizontal_scroll_bars = false;
1118 #endif
1120 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
1121 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
1122 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
1123 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
1125 /* Set the top frame to the newly created frame. */
1126 if (FRAMEP (FRAME_TTY (f)->top_frame)
1127 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
1128 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
1130 FRAME_TTY (f)->top_frame = frame;
1132 if (!noninteractive)
1133 init_frame_faces (f);
1135 return f;
1138 /* Get a suitable value for frame parameter PARAMETER for a newly
1139 created frame, based on (1) the user-supplied frame parameter
1140 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
1142 static Lisp_Object
1143 get_future_frame_param (Lisp_Object parameter,
1144 Lisp_Object supplied_parms,
1145 char *current_value)
1147 Lisp_Object result;
1149 result = Fassq (parameter, supplied_parms);
1150 if (NILP (result))
1151 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
1152 if (NILP (result) && current_value != NULL)
1153 result = build_string (current_value);
1154 if (!NILP (result) && !STRINGP (result))
1155 result = XCDR (result);
1156 if (NILP (result) || !STRINGP (result))
1157 result = Qnil;
1159 return result;
1162 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
1163 1, 1, 0,
1164 doc: /* Create an additional terminal frame, possibly on another terminal.
1165 This function takes one argument, an alist specifying frame parameters.
1167 You can create multiple frames on a single text terminal, but only one
1168 of them (the selected terminal frame) is actually displayed.
1170 In practice, generally you don't need to specify any parameters,
1171 except when you want to create a new frame on another terminal.
1172 In that case, the `tty' parameter specifies the device file to open,
1173 and the `tty-type' parameter specifies the terminal type. Example:
1175 (make-terminal-frame \\='((tty . "/dev/pts/5") (tty-type . "xterm")))
1177 Note that changing the size of one terminal frame automatically
1178 affects all frames on the same terminal device. */)
1179 (Lisp_Object parms)
1181 struct frame *f;
1182 struct terminal *t = NULL;
1183 Lisp_Object frame, tem;
1184 struct frame *sf = SELECTED_FRAME ();
1186 #ifdef MSDOS
1187 if (sf->output_method != output_msdos_raw
1188 && sf->output_method != output_termcap)
1189 emacs_abort ();
1190 #else /* not MSDOS */
1192 #ifdef WINDOWSNT /* This should work now! */
1193 if (sf->output_method != output_termcap)
1194 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
1195 #endif
1196 #endif /* not MSDOS */
1199 Lisp_Object terminal;
1201 terminal = Fassq (Qterminal, parms);
1202 if (CONSP (terminal))
1204 terminal = XCDR (terminal);
1205 t = decode_live_terminal (terminal);
1207 #ifdef MSDOS
1208 if (t && t != the_only_display_info.terminal)
1209 /* msdos.c assumes a single tty_display_info object. */
1210 error ("Multiple terminals are not supported on this platform");
1211 if (!t)
1212 t = the_only_display_info.terminal;
1213 #endif
1216 if (!t)
1218 char *name = 0, *type = 0;
1219 Lisp_Object tty, tty_type;
1220 USE_SAFE_ALLOCA;
1222 tty = get_future_frame_param
1223 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1224 ? FRAME_TTY (XFRAME (selected_frame))->name
1225 : NULL));
1226 if (!NILP (tty))
1227 SAFE_ALLOCA_STRING (name, tty);
1229 tty_type = get_future_frame_param
1230 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1231 ? FRAME_TTY (XFRAME (selected_frame))->type
1232 : NULL));
1233 if (!NILP (tty_type))
1234 SAFE_ALLOCA_STRING (type, tty_type);
1236 t = init_tty (name, type, 0); /* Errors are not fatal. */
1237 SAFE_FREE ();
1240 f = make_terminal_frame (t);
1243 int width, height;
1244 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1245 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
1246 5, 0, Qterminal_frame);
1249 adjust_frame_glyphs (f);
1250 calculate_costs (f);
1251 XSETFRAME (frame, f);
1253 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
1254 store_in_alist (&parms, Qtty,
1255 (t->display_info.tty->name
1256 ? build_string (t->display_info.tty->name)
1257 : Qnil));
1258 /* On terminal frames the `minibuffer' frame parameter is always
1259 virtually t. Avoid that a different value in parms causes
1260 complaints, see Bug#24758. */
1261 store_in_alist (&parms, Qminibuffer, Qt);
1262 Fmodify_frame_parameters (frame, parms);
1264 /* Make the frame face alist be frame-specific, so that each
1265 frame could change its face definitions independently. */
1266 fset_face_alist (f, Fcopy_alist (sf->face_alist));
1267 /* Simple Fcopy_alist isn't enough, because we need the contents of
1268 the vectors which are the CDRs of associations in face_alist to
1269 be copied as well. */
1270 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
1271 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
1273 f->can_x_set_window_size = true;
1274 f->after_make_frame = true;
1276 return frame;
1280 /* Perform the switch to frame FRAME.
1282 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
1283 FRAME1 as frame.
1285 If TRACK is non-zero and the frame that currently has the focus
1286 redirects its focus to the selected frame, redirect that focused
1287 frame's focus to FRAME instead.
1289 FOR_DELETION non-zero means that the selected frame is being
1290 deleted, which includes the possibility that the frame's terminal
1291 is dead.
1293 The value of NORECORD is passed as argument to Fselect_window. */
1295 Lisp_Object
1296 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1298 struct frame *sf = SELECTED_FRAME (), *f;
1300 /* If FRAME is a switch-frame event, extract the frame we should
1301 switch to. */
1302 if (CONSP (frame)
1303 && EQ (XCAR (frame), Qswitch_frame)
1304 && CONSP (XCDR (frame)))
1305 frame = XCAR (XCDR (frame));
1307 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1308 a switch-frame event to arrive after a frame is no longer live,
1309 especially when deleting the initial frame during startup. */
1310 CHECK_FRAME (frame);
1311 f = XFRAME (frame);
1312 if (!FRAME_LIVE_P (f))
1313 return Qnil;
1314 else if (f == sf)
1315 return frame;
1317 /* If a frame's focus has been redirected toward the currently
1318 selected frame, we should change the redirection to point to the
1319 newly selected frame. This means that if the focus is redirected
1320 from a minibufferless frame to a surrogate minibuffer frame, we
1321 can use `other-window' to switch between all the frames using
1322 that minibuffer frame, and the focus redirection will follow us
1323 around. */
1324 #if 0
1325 /* This is too greedy; it causes inappropriate focus redirection
1326 that's hard to get rid of. */
1327 if (track)
1329 Lisp_Object tail;
1331 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1333 Lisp_Object focus;
1335 if (!FRAMEP (XCAR (tail)))
1336 emacs_abort ();
1338 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1340 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1341 Fredirect_frame_focus (XCAR (tail), frame);
1344 #else /* ! 0 */
1345 /* Instead, apply it only to the frame we're pointing to. */
1346 #ifdef HAVE_WINDOW_SYSTEM
1347 if (track && FRAME_WINDOW_P (f))
1349 Lisp_Object focus, xfocus;
1351 xfocus = x_get_focus_frame (f);
1352 if (FRAMEP (xfocus))
1354 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1355 if ((FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1356 /* Redirect frame focus also when FRAME has its minibuffer
1357 window on the selected frame (see Bug#24500). */
1358 || (NILP (focus)
1359 && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))
1360 Fredirect_frame_focus (xfocus, frame);
1363 #endif /* HAVE_X_WINDOWS */
1364 #endif /* ! 0 */
1366 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1367 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1369 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
1371 struct tty_display_info *tty = FRAME_TTY (f);
1372 Lisp_Object top_frame = tty->top_frame;
1374 /* Don't mark the frame garbaged and/or obscured if we are
1375 switching to the frame that is already the top frame of that
1376 TTY. */
1377 if (!EQ (frame, top_frame))
1379 if (FRAMEP (top_frame))
1380 /* Mark previously displayed frame as now obscured. */
1381 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1382 SET_FRAME_VISIBLE (f, 1);
1383 /* If the new TTY frame changed dimensions, we need to
1384 resync term.c's idea of the frame size with the new
1385 frame's data. */
1386 if (FRAME_COLS (f) != FrameCols (tty))
1387 FrameCols (tty) = FRAME_COLS (f);
1388 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1389 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1391 tty->top_frame = frame;
1394 selected_frame = frame;
1395 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1396 last_nonminibuf_frame = XFRAME (selected_frame);
1398 Fselect_window (f->selected_window, norecord);
1400 /* We want to make sure that the next event generates a frame-switch
1401 event to the appropriate frame. This seems kludgy to me, but
1402 before you take it out, make sure that evaluating something like
1403 (select-window (frame-root-window (new-frame))) doesn't end up
1404 with your typing being interpreted in the new frame instead of
1405 the one you're actually typing in. */
1406 #ifdef HAVE_WINDOW_SYSTEM
1407 if (!frame_ancestor_p (f, sf))
1408 #endif
1409 internal_last_event_frame = Qnil;
1411 return frame;
1414 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1415 doc: /* Select FRAME.
1416 Subsequent editing commands apply to its selected window.
1417 Optional argument NORECORD means to neither change the order of
1418 recently selected windows nor the buffer list.
1420 The selection of FRAME lasts until the next time the user does
1421 something to select a different frame, or until the next time
1422 this function is called. If you are using a window system, the
1423 previously selected frame may be restored as the selected frame
1424 when returning to the command loop, because it still may have
1425 the window system's input focus. On a text terminal, the next
1426 redisplay will display FRAME.
1428 This function returns FRAME, or nil if FRAME has been deleted. */)
1429 (Lisp_Object frame, Lisp_Object norecord)
1431 return do_switch_frame (frame, 1, 0, norecord);
1434 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1435 doc: /* Handle a switch-frame event EVENT.
1436 Switch-frame events are usually bound to this function.
1437 A switch-frame event tells Emacs that the window manager has requested
1438 that the user's events be directed to the frame mentioned in the event.
1439 This function selects the selected window of the frame of EVENT.
1441 If EVENT is frame object, handle it as if it were a switch-frame event
1442 to that frame. */)
1443 (Lisp_Object event)
1445 Lisp_Object value;
1447 /* Preserve prefix arg that the command loop just cleared. */
1448 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1449 run_hook (Qmouse_leave_buffer_hook);
1450 /* `switch-frame' implies a focus in. */
1451 value = do_switch_frame (event, 0, 0, Qnil);
1452 call1 (intern ("handle-focus-in"), event);
1453 return value;
1456 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1457 doc: /* Return the frame that is now selected. */)
1458 (void)
1460 return selected_frame;
1463 DEFUN ("frame-list", Fframe_list, Sframe_list,
1464 0, 0, 0,
1465 doc: /* Return a list of all live frames. */)
1466 (void)
1468 Lisp_Object frames;
1469 frames = Fcopy_sequence (Vframe_list);
1470 #ifdef HAVE_WINDOW_SYSTEM
1471 if (FRAMEP (tip_frame))
1472 frames = Fdelq (tip_frame, frames);
1473 #endif
1474 return frames;
1477 DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
1478 0, 1, 0,
1479 doc: /* Return the parent frame of FRAME.
1480 The parent frame of FRAME is the Emacs frame whose window-system window
1481 is the parent window of FRAME's window-system window. When such a frame
1482 exists, FRAME is considered a child frame of that frame.
1484 Return nil if FRAME has no parent frame. This means that FRAME's
1485 window-system window is either a "top-level" window (a window whose
1486 parent window is the window-system's root window) or an embedded window
1487 \(a window whose parent window is owned by some other application). */)
1488 (Lisp_Object frame)
1490 struct frame *f = decode_live_frame (frame);
1491 struct frame *p = FRAME_PARENT_FRAME (f);
1492 Lisp_Object parent;
1494 /* Can't return f->parent_frame directly since it might not be defined
1495 for this platform. */
1496 if (p)
1498 XSETFRAME (parent, p);
1500 return parent;
1502 else
1503 return Qnil;
1506 #ifdef HAVE_WINDOW_SYSTEM
1507 bool
1508 frame_ancestor_p (struct frame *af, struct frame *df)
1510 struct frame *pf = FRAME_PARENT_FRAME (df);
1512 while (pf)
1514 if (pf == af)
1515 return true;
1516 else
1517 pf = FRAME_PARENT_FRAME (pf);
1520 return false;
1522 #endif
1524 DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1525 2, 2, 0,
1526 doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
1527 ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
1528 parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
1529 ANCESTOR and DESCENDANT must be live frames and default to the selected
1530 frame. */)
1531 (Lisp_Object ancestor, Lisp_Object descendant)
1533 #ifdef HAVE_WINDOW_SYSTEM
1534 struct frame *af = decode_live_frame (ancestor);
1535 struct frame *df = decode_live_frame (descendant);
1537 return frame_ancestor_p (af, df) ? Qt : Qnil;
1538 #else
1539 return Qnil;
1540 #endif
1543 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1544 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1545 If MINIBUF is nil, do not consider minibuffer-only candidate.
1546 If MINIBUF is `visible', do not consider an invisible candidate.
1547 If MINIBUF is a window, consider only its own frame and candidate now
1548 using that window as the minibuffer.
1549 If MINIBUF is 0, consider candidate if it is visible or iconified.
1550 Otherwise consider any candidate and return nil if CANDIDATE is not
1551 acceptable. */
1553 static Lisp_Object
1554 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1556 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1558 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1559 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1560 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1561 && FRAME_TTY (c) == FRAME_TTY (f)))
1563 if (!NILP (get_frame_param (c, Qno_other_frame)))
1564 return Qnil;
1565 else if (NILP (minibuf))
1567 if (!FRAME_MINIBUF_ONLY_P (c))
1568 return candidate;
1570 else if (EQ (minibuf, Qvisible))
1572 if (FRAME_VISIBLE_P (c))
1573 return candidate;
1575 else if (WINDOWP (minibuf))
1577 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1578 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1579 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1580 FRAME_FOCUS_FRAME (c)))
1581 return candidate;
1583 else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
1585 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1586 return candidate;
1588 else
1589 return candidate;
1591 return Qnil;
1594 /* Return the next frame in the frame list after FRAME. */
1596 static Lisp_Object
1597 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1599 Lisp_Object f, tail;
1600 int passed = 0;
1602 while (passed < 2)
1603 FOR_EACH_FRAME (tail, f)
1605 if (passed)
1607 f = candidate_frame (f, frame, minibuf);
1608 if (!NILP (f))
1609 return f;
1611 if (EQ (frame, f))
1612 passed++;
1614 return frame;
1617 /* Return the previous frame in the frame list before FRAME. */
1619 static Lisp_Object
1620 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1622 Lisp_Object f, tail, prev = Qnil;
1624 FOR_EACH_FRAME (tail, f)
1626 if (EQ (frame, f) && !NILP (prev))
1627 return prev;
1628 f = candidate_frame (f, frame, minibuf);
1629 if (!NILP (f))
1630 prev = f;
1633 /* We've scanned the entire list. */
1634 if (NILP (prev))
1635 /* We went through the whole frame list without finding a single
1636 acceptable frame. Return the original frame. */
1637 return frame;
1638 else
1639 /* There were no acceptable frames in the list before FRAME; otherwise,
1640 we would have returned directly from the loop. Since PREV is the last
1641 acceptable frame in the list, return it. */
1642 return prev;
1646 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1647 doc: /* Return the next frame in the frame list after FRAME.
1648 It considers only frames on the same terminal as FRAME.
1649 By default, skip minibuffer-only frames.
1650 If omitted, FRAME defaults to the selected frame.
1651 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1652 If MINIFRAME is a window, include only its own frame
1653 and any frame now using that window as the minibuffer.
1654 If MINIFRAME is `visible', include all visible frames.
1655 If MINIFRAME is 0, include all visible and iconified frames.
1656 Otherwise, include all frames. */)
1657 (Lisp_Object frame, Lisp_Object miniframe)
1659 if (NILP (frame))
1660 frame = selected_frame;
1661 CHECK_LIVE_FRAME (frame);
1662 return next_frame (frame, miniframe);
1665 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1666 doc: /* Return the previous frame in the frame list before FRAME.
1667 It considers only frames on the same terminal as FRAME.
1668 By default, skip minibuffer-only frames.
1669 If omitted, FRAME defaults to the selected frame.
1670 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1671 If MINIFRAME is a window, include only its own frame
1672 and any frame now using that window as the minibuffer.
1673 If MINIFRAME is `visible', include all visible frames.
1674 If MINIFRAME is 0, include all visible and iconified frames.
1675 Otherwise, include all frames. */)
1676 (Lisp_Object frame, Lisp_Object miniframe)
1678 if (NILP (frame))
1679 frame = selected_frame;
1680 CHECK_LIVE_FRAME (frame);
1681 return prev_frame (frame, miniframe);
1684 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1685 Slast_nonminibuf_frame, 0, 0, 0,
1686 doc: /* Return last non-minibuffer frame selected. */)
1687 (void)
1689 Lisp_Object frame = Qnil;
1691 if (last_nonminibuf_frame)
1692 XSETFRAME (frame, last_nonminibuf_frame);
1694 return frame;
1698 * other_frames:
1700 * Return true if there exists at least one visible or iconified frame
1701 * but F. Return false otherwise.
1703 * INVISIBLE true means we are called from make_frame_invisible where
1704 * such a frame must be visible or iconified. INVISIBLE nil means we
1705 * are called from delete_frame. In that case FORCE true means that the
1706 * visibility status of such a frame can be ignored.
1708 * If F is the terminal frame and we are using X, return true if at
1709 * least one X frame exists.
1711 static bool
1712 other_frames (struct frame *f, bool invisible, bool force)
1714 Lisp_Object frames, frame, frame1;
1715 struct frame *f1;
1716 Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
1718 XSETFRAME (frame, f);
1719 if (WINDOWP (minibuffer_window)
1720 && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
1721 minibuffer_window = Qnil;
1723 FOR_EACH_FRAME (frames, frame1)
1725 f1 = XFRAME (frame1);
1726 if (f != f1)
1728 /* Verify that we can still talk to the frame's X window, and
1729 note any recent change in visibility. */
1730 #ifdef HAVE_X_WINDOWS
1731 if (FRAME_WINDOW_P (f1))
1732 x_sync (f1);
1733 #endif
1734 if (NILP (Fframe_parameter (frame1, Qtooltip))
1735 /* Tooltips and child frames count neither for
1736 invisibility nor for deletions. */
1737 && !FRAME_PARENT_FRAME (f1)
1738 /* Frames with a non-nil `delete-before' parameter don't
1739 count for deletions. */
1740 && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
1741 /* For invisibility and normal deletions, at least one
1742 visible or iconified frame must remain (Bug#26682). */
1743 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
1744 || (!invisible
1745 && (force
1746 /* Allow deleting the terminal frame when at
1747 least one X frame exists. */
1748 || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))))
1749 return true;
1753 return false;
1756 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1757 window. Preferably use the selected frame's minibuffer window
1758 instead. If the selected frame doesn't have one, get some other
1759 frame's minibuffer window. SELECT non-zero means select the new
1760 minibuffer window. */
1761 static void
1762 check_minibuf_window (Lisp_Object frame, int select)
1764 struct frame *f = decode_live_frame (frame);
1766 XSETFRAME (frame, f);
1768 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1770 Lisp_Object frames, this, window = make_number (0);
1772 if (!EQ (frame, selected_frame)
1773 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1774 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1775 else
1776 FOR_EACH_FRAME (frames, this)
1778 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1780 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1781 break;
1785 /* Don't abort if no window was found (Bug#15247). */
1786 if (WINDOWP (window))
1788 /* Use set_window_buffer instead of Fset_window_buffer (see
1789 discussion of bug#11984, bug#12025, bug#12026). */
1790 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1791 minibuf_window = window;
1793 /* SELECT non-zero usually means that FRAME's minibuffer
1794 window was selected; select the new one. */
1795 if (select)
1796 Fselect_window (minibuf_window, Qnil);
1803 * delete_frame:
1805 * Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1806 * unconditionally. x_connection_closed and delete_terminal use this.
1807 * Any other value of FORCE implements the semantics described for
1808 * Fdelete_frame. */
1809 Lisp_Object
1810 delete_frame (Lisp_Object frame, Lisp_Object force)
1812 struct frame *f = decode_any_frame (frame);
1813 struct frame *sf;
1814 struct kboard *kb;
1815 Lisp_Object frames, frame1;
1816 int minibuffer_selected, is_tooltip_frame;
1817 bool nochild = !FRAME_PARENT_FRAME (f);
1819 if (!FRAME_LIVE_P (f))
1820 return Qnil;
1821 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1823 if (NILP (force))
1824 error ("Attempt to delete the sole visible or iconified frame");
1825 else
1826 error ("Attempt to delete the only frame");
1829 XSETFRAME (frame, f);
1831 /* Softly delete all frames with this frame as their parent frame or
1832 as their `delete-before' frame parameter value. */
1833 FOR_EACH_FRAME (frames, frame1)
1834 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
1835 /* Process `delete-before' parameter iff FRAME is not a child
1836 frame. This avoids that we enter an infinite chain of mixed
1837 dependencies. */
1838 || (nochild
1839 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
1840 delete_frame (frame1, Qnil);
1842 /* Does this frame have a minibuffer, and is it the surrogate
1843 minibuffer for any other frame? */
1844 if (FRAME_HAS_MINIBUF_P (f))
1846 FOR_EACH_FRAME (frames, frame1)
1848 Lisp_Object fminiw;
1850 if (EQ (frame1, frame))
1851 continue;
1853 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
1855 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1857 /* If we MUST delete this frame, delete the other first.
1858 But do this only if FORCE equals `noelisp'. */
1859 if (EQ (force, Qnoelisp))
1860 delete_frame (frame1, Qnoelisp);
1861 else
1862 error ("Attempt to delete a surrogate minibuffer frame");
1867 is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
1869 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1870 frame is a tooltip. FORCE is set to `noelisp' when handling
1871 a disconnect from the terminal, so we don't dare call Lisp
1872 code. */
1873 if (NILP (Vrun_hooks) || is_tooltip_frame)
1875 else if (EQ (force, Qnoelisp))
1876 pending_funcalls
1877 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1878 pending_funcalls);
1879 else
1881 #ifdef HAVE_X_WINDOWS
1882 /* Also, save clipboard to the clipboard manager. */
1883 x_clipboard_manager_save_frame (frame);
1884 #endif
1886 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1889 /* delete_frame_functions may have deleted any frame, including this
1890 one. */
1891 if (!FRAME_LIVE_P (f))
1892 return Qnil;
1893 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1895 if (NILP (force))
1896 error ("Attempt to delete the sole visible or iconified frame");
1897 else
1898 error ("Attempt to delete the only frame");
1901 /* At this point, we are committed to deleting the frame.
1902 There is no more chance for errors to prevent it. */
1903 minibuffer_selected = EQ (minibuf_window, selected_window);
1904 sf = SELECTED_FRAME ();
1905 /* Don't let the frame remain selected. */
1906 if (f == sf)
1908 Lisp_Object tail;
1910 /* Look for another visible frame on the same terminal.
1911 Do not call next_frame here because it may loop forever.
1912 See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1913 FOR_EACH_FRAME (tail, frame1)
1914 if (!EQ (frame, frame1)
1915 && (FRAME_TERMINAL (XFRAME (frame))
1916 == FRAME_TERMINAL (XFRAME (frame1)))
1917 && FRAME_VISIBLE_P (XFRAME (frame1)))
1918 break;
1920 /* If there is none, find *some* other frame. */
1921 if (NILP (frame1) || EQ (frame1, frame))
1923 FOR_EACH_FRAME (tail, frame1)
1925 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
1927 /* Do not change a text terminal's top-frame. */
1928 struct frame *f1 = XFRAME (frame1);
1929 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1931 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1932 if (!EQ (top_frame, frame))
1933 frame1 = top_frame;
1935 break;
1939 #ifdef NS_IMPL_COCOA
1940 else
1941 /* Under NS, there is no system mechanism for choosing a new
1942 window to get focus -- it is left to application code.
1943 So the portion of THIS application interfacing with NS
1944 needs to know about it. We call Fraise_frame, but the
1945 purpose is really to transfer focus. */
1946 Fraise_frame (frame1);
1947 #endif
1949 do_switch_frame (frame1, 0, 1, Qnil);
1950 sf = SELECTED_FRAME ();
1953 /* Don't allow minibuf_window to remain on a deleted frame. */
1954 check_minibuf_window (frame, minibuffer_selected);
1956 /* Don't let echo_area_window to remain on a deleted frame. */
1957 if (EQ (f->minibuffer_window, echo_area_window))
1958 echo_area_window = sf->minibuffer_window;
1960 /* Clear any X selections for this frame. */
1961 #ifdef HAVE_X_WINDOWS
1962 if (FRAME_X_P (f))
1963 x_clear_frame_selections (f);
1964 #endif
1966 /* Free glyphs.
1967 This function must be called before the window tree of the
1968 frame is deleted because windows contain dynamically allocated
1969 memory. */
1970 free_glyphs (f);
1972 #ifdef HAVE_WINDOW_SYSTEM
1973 /* Give chance to each font driver to free a frame specific data. */
1974 font_update_drivers (f, Qnil);
1975 #endif
1977 /* Mark all the windows that used to be on FRAME as deleted, and then
1978 remove the reference to them. */
1979 delete_all_child_windows (f->root_window);
1980 fset_root_window (f, Qnil);
1982 Vframe_list = Fdelq (frame, Vframe_list);
1983 SET_FRAME_VISIBLE (f, 0);
1985 /* Allow the vector of menu bar contents to be freed in the next
1986 garbage collection. The frame object itself may not be garbage
1987 collected until much later, because recent_keys and other data
1988 structures can still refer to it. */
1989 fset_menu_bar_vector (f, Qnil);
1991 /* If FRAME's buffer lists contains killed
1992 buffers, this helps GC to reclaim them. */
1993 fset_buffer_list (f, Qnil);
1994 fset_buried_buffer_list (f, Qnil);
1996 free_font_driver_list (f);
1997 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1998 xfree (f->namebuf);
1999 #endif
2000 xfree (f->decode_mode_spec_buffer);
2001 xfree (FRAME_INSERT_COST (f));
2002 xfree (FRAME_DELETEN_COST (f));
2003 xfree (FRAME_INSERTN_COST (f));
2004 xfree (FRAME_DELETE_COST (f));
2006 /* Since some events are handled at the interrupt level, we may get
2007 an event for f at any time; if we zero out the frame's terminal
2008 now, then we may trip up the event-handling code. Instead, we'll
2009 promise that the terminal of the frame must be valid until we
2010 have called the window-system-dependent frame destruction
2011 routine. */
2013 struct terminal *terminal;
2014 block_input ();
2015 if (FRAME_TERMINAL (f)->delete_frame_hook)
2016 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
2017 terminal = FRAME_TERMINAL (f);
2018 f->output_data.nothing = 0;
2019 f->terminal = 0; /* Now the frame is dead. */
2020 unblock_input ();
2022 /* If needed, delete the terminal that this frame was on.
2023 (This must be done after the frame is killed.) */
2024 terminal->reference_count--;
2025 #ifdef USE_GTK
2026 /* FIXME: Deleting the terminal crashes emacs because of a GTK
2027 bug.
2028 http://lists.gnu.org/archive/html/emacs-devel/2011-10/msg00363.html */
2029 if (terminal->reference_count == 0 && terminal->type == output_x_window)
2030 terminal->reference_count = 1;
2031 #endif /* USE_GTK */
2032 if (terminal->reference_count == 0)
2034 Lisp_Object tmp;
2035 XSETTERMINAL (tmp, terminal);
2037 kb = NULL;
2038 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
2040 else
2041 kb = terminal->kboard;
2044 /* If we've deleted the last_nonminibuf_frame, then try to find
2045 another one. */
2046 if (f == last_nonminibuf_frame)
2048 last_nonminibuf_frame = 0;
2050 FOR_EACH_FRAME (frames, frame1)
2052 struct frame *f1 = XFRAME (frame1);
2054 if (!FRAME_MINIBUF_ONLY_P (f1))
2056 last_nonminibuf_frame = f1;
2057 break;
2062 /* If there's no other frame on the same kboard, get out of
2063 single-kboard state if we're in it for this kboard. */
2064 if (kb != NULL)
2066 /* Some frame we found on the same kboard, or nil if there are none. */
2067 Lisp_Object frame_on_same_kboard = Qnil;
2069 FOR_EACH_FRAME (frames, frame1)
2070 if (kb == FRAME_KBOARD (XFRAME (frame1)))
2071 frame_on_same_kboard = frame1;
2073 if (NILP (frame_on_same_kboard))
2074 not_single_kboard_state (kb);
2078 /* If we've deleted this keyboard's default_minibuffer_frame, try to
2079 find another one. Prefer minibuffer-only frames, but also notice
2080 frames with other windows. */
2081 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
2083 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
2084 Lisp_Object frame_with_minibuf = Qnil;
2085 /* Some frame we found on the same kboard, or nil if there are none. */
2086 Lisp_Object frame_on_same_kboard = Qnil;
2088 FOR_EACH_FRAME (frames, frame1)
2090 struct frame *f1 = XFRAME (frame1);
2092 /* Consider only frames on the same kboard
2093 and only those with minibuffers. */
2094 if (kb == FRAME_KBOARD (f1)
2095 && FRAME_HAS_MINIBUF_P (f1))
2097 frame_with_minibuf = frame1;
2098 if (FRAME_MINIBUF_ONLY_P (f1))
2099 break;
2102 if (kb == FRAME_KBOARD (f1))
2103 frame_on_same_kboard = frame1;
2106 if (!NILP (frame_on_same_kboard))
2108 /* We know that there must be some frame with a minibuffer out
2109 there. If this were not true, all of the frames present
2110 would have to be minibufferless, which implies that at some
2111 point their minibuffer frames must have been deleted, but
2112 that is prohibited at the top; you can't delete surrogate
2113 minibuffer frames. */
2114 if (NILP (frame_with_minibuf))
2115 emacs_abort ();
2117 kset_default_minibuffer_frame (kb, frame_with_minibuf);
2119 else
2120 /* No frames left on this kboard--say no minibuffer either. */
2121 kset_default_minibuffer_frame (kb, Qnil);
2124 /* Cause frame titles to update--necessary if we now have just one frame. */
2125 if (!is_tooltip_frame)
2126 update_mode_lines = 15;
2128 return Qnil;
2131 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
2132 doc: /* Delete FRAME, permanently eliminating it from use.
2133 FRAME must be a live frame and defaults to the selected one.
2135 A frame may not be deleted if its minibuffer serves as surrogate
2136 minibuffer for another frame. Normally, you may not delete a frame if
2137 all other frames are invisible, but if the second optional argument
2138 FORCE is non-nil, you may do so.
2140 This function runs `delete-frame-functions' before actually
2141 deleting the frame, unless the frame is a tooltip.
2142 The functions are run with one argument, the frame to be deleted. */)
2143 (Lisp_Object frame, Lisp_Object force)
2145 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
2148 #ifdef HAVE_WINDOW_SYSTEM
2150 * frame_internal_border_part:
2152 * Return part of internal border the coordinates X and Y relative to
2153 * frame F are on. Return nil if the coordinates are not on the
2154 * internal border of F.
2156 * Return one of INTERNAL_BORDER_LEFT_EDGE, INTERNAL_BORDER_TOP_EDGE,
2157 * INTERNAL_BORDER_RIGHT_EDGE or INTERNAL_BORDER_BOTTOM_EDGE when the
2158 * mouse cursor is on the corresponding border with an offset of at
2159 * least one canonical character height from that border's edges.
2161 * If no border part could be found this way, return one of
2162 * INTERNAL_BORDER_TOP_LEFT_CORNER, INTERNAL_BORDER_TOP_RIGHT_CORNER,
2163 * INTERNAL_BORDER_BOTTOM_LEFT_CORNER or
2164 * INTERNAL_BORDER_BOTTOM_RIGHT_CORNER to indicate that the mouse is in
2165 * one of the corresponding corners. This means that for very small
2166 * frames an `edge' return value is preferred.
2168 enum internal_border_part
2169 frame_internal_border_part (struct frame *f, int x, int y)
2171 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
2172 int offset = FRAME_LINE_HEIGHT (f);
2173 int width = FRAME_PIXEL_WIDTH (f);
2174 int height = FRAME_PIXEL_HEIGHT (f);
2175 enum internal_border_part part = INTERNAL_BORDER_NONE;
2177 if (offset < border)
2178 /* For very wide borders make offset at least as large as
2179 border. */
2180 offset = border;
2182 if (offset < x && x < width - offset)
2183 /* Top or bottom border. */
2185 if (0 <= y && y <= border)
2186 part = INTERNAL_BORDER_TOP_EDGE;
2187 else if (height - border <= y && y <= height)
2188 part = INTERNAL_BORDER_BOTTOM_EDGE;
2190 else if (offset < y && y < height - offset)
2191 /* Left or right border. */
2193 if (0 <= x && x <= border)
2194 part = INTERNAL_BORDER_LEFT_EDGE;
2195 else if (width - border <= x && x <= width)
2196 part = INTERNAL_BORDER_RIGHT_EDGE;
2198 else
2200 /* An edge. */
2201 int half_width = width / 2;
2202 int half_height = height / 2;
2204 if (0 <= x && x <= border)
2206 /* A left edge. */
2207 if (0 <= y && y <= half_height)
2208 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2209 else if (half_height < y && y <= height)
2210 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2212 else if (width - border <= x && x <= width)
2214 /* A right edge. */
2215 if (0 <= y && y <= half_height)
2216 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2217 else if (half_height < y && y <= height)
2218 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2220 else if (0 <= y && y <= border)
2222 /* A top edge. */
2223 if (0 <= x && x <= half_width)
2224 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2225 else if (half_width < x && x <= width)
2226 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2228 else if (height - border <= y && y <= height)
2230 /* A bottom edge. */
2231 if (0 <= x && x <= half_width)
2232 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2233 else if (half_width < x && x <= width)
2234 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2238 return part;
2240 #endif
2242 /* Return mouse position in character cell units. */
2244 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
2245 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2246 The position is given in canonical character cells, where (0, 0) is the
2247 upper-left corner of the frame, X is the horizontal offset, and Y is the
2248 vertical offset, measured in units of the frame's default character size.
2249 If Emacs is running on a mouseless terminal or hasn't been programmed
2250 to read the mouse position, it returns the selected frame for FRAME
2251 and nil for X and Y.
2252 If `mouse-position-function' is non-nil, `mouse-position' calls it,
2253 passing the normal return value to that function as an argument,
2254 and returns whatever that function returns. */)
2255 (void)
2257 struct frame *f;
2258 Lisp_Object lispy_dummy;
2259 Lisp_Object x, y, retval;
2261 f = SELECTED_FRAME ();
2262 x = y = Qnil;
2264 /* It's okay for the hook to refrain from storing anything. */
2265 if (FRAME_TERMINAL (f)->mouse_position_hook)
2267 enum scroll_bar_part party_dummy;
2268 Time time_dummy;
2269 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2270 &lispy_dummy, &party_dummy,
2271 &x, &y,
2272 &time_dummy);
2275 if (! NILP (x))
2277 int col = XINT (x);
2278 int row = XINT (y);
2279 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
2280 XSETINT (x, col);
2281 XSETINT (y, row);
2283 XSETFRAME (lispy_dummy, f);
2284 retval = Fcons (lispy_dummy, Fcons (x, y));
2285 if (!NILP (Vmouse_position_function))
2286 retval = call1 (Vmouse_position_function, retval);
2287 return retval;
2290 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
2291 Smouse_pixel_position, 0, 0, 0,
2292 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
2293 The position is given in pixel units, where (0, 0) is the
2294 upper-left corner of the frame, X is the horizontal offset, and Y is
2295 the vertical offset.
2296 If Emacs is running on a mouseless terminal or hasn't been programmed
2297 to read the mouse position, it returns the selected frame for FRAME
2298 and nil for X and Y. */)
2299 (void)
2301 struct frame *f;
2302 Lisp_Object lispy_dummy;
2303 Lisp_Object x, y, retval;
2305 f = SELECTED_FRAME ();
2306 x = y = Qnil;
2308 /* It's okay for the hook to refrain from storing anything. */
2309 if (FRAME_TERMINAL (f)->mouse_position_hook)
2311 enum scroll_bar_part party_dummy;
2312 Time time_dummy;
2313 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
2314 &lispy_dummy, &party_dummy,
2315 &x, &y,
2316 &time_dummy);
2319 XSETFRAME (lispy_dummy, f);
2320 retval = Fcons (lispy_dummy, Fcons (x, y));
2321 if (!NILP (Vmouse_position_function))
2322 retval = call1 (Vmouse_position_function, retval);
2323 return retval;
2326 #ifdef HAVE_WINDOW_SYSTEM
2328 /* On frame F, convert character coordinates X and Y to pixel
2329 coordinates *PIX_X and *PIX_Y. */
2331 static void
2332 frame_char_to_pixel_position (struct frame *f, int x, int y,
2333 int *pix_x, int *pix_y)
2335 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
2336 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
2338 if (*pix_x < 0)
2339 *pix_x = 0;
2340 if (*pix_x > FRAME_PIXEL_WIDTH (f))
2341 *pix_x = FRAME_PIXEL_WIDTH (f);
2343 if (*pix_y < 0)
2344 *pix_y = 0;
2345 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
2346 *pix_y = FRAME_PIXEL_HEIGHT (f);
2349 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
2351 static void
2352 frame_set_mouse_position (struct frame *f, int x, int y)
2354 int pix_x, pix_y;
2356 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
2357 frame_set_mouse_pixel_position (f, pix_x, pix_y);
2360 #endif /* HAVE_WINDOW_SYSTEM */
2362 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
2363 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
2364 Coordinates are relative to the frame, not a window,
2365 so the coordinates of the top left character in the frame
2366 may be nonzero due to left-hand scroll bars or the menu bar.
2368 The position is given in canonical character cells, where (0, 0) is
2369 the upper-left corner of the frame, X is the horizontal offset, and
2370 Y is the vertical offset, measured in units of the frame's default
2371 character size.
2373 This function is a no-op for an X frame that is not visible.
2374 If you have just created a frame, you must wait for it to become visible
2375 before calling this function on it, like this.
2376 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2377 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2379 CHECK_LIVE_FRAME (frame);
2380 CHECK_TYPE_RANGED_INTEGER (int, x);
2381 CHECK_TYPE_RANGED_INTEGER (int, y);
2383 /* I think this should be done with a hook. */
2384 #ifdef HAVE_WINDOW_SYSTEM
2385 if (FRAME_WINDOW_P (XFRAME (frame)))
2386 /* Warping the mouse will cause enternotify and focus events. */
2387 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
2388 #else
2389 #if defined (MSDOS)
2390 if (FRAME_MSDOS_P (XFRAME (frame)))
2392 Fselect_frame (frame, Qnil);
2393 mouse_moveto (XINT (x), XINT (y));
2395 #else
2396 #ifdef HAVE_GPM
2398 Fselect_frame (frame, Qnil);
2399 term_mouse_moveto (XINT (x), XINT (y));
2401 #endif
2402 #endif
2403 #endif
2405 return Qnil;
2408 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
2409 Sset_mouse_pixel_position, 3, 3, 0,
2410 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
2411 The position is given in pixels, where (0, 0) is the upper-left corner
2412 of the frame, X is the horizontal offset, and Y is the vertical offset.
2414 Note, this is a no-op for an X frame that is not visible.
2415 If you have just created a frame, you must wait for it to become visible
2416 before calling this function on it, like this.
2417 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
2418 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
2420 CHECK_LIVE_FRAME (frame);
2421 CHECK_TYPE_RANGED_INTEGER (int, x);
2422 CHECK_TYPE_RANGED_INTEGER (int, y);
2424 /* I think this should be done with a hook. */
2425 #ifdef HAVE_WINDOW_SYSTEM
2426 if (FRAME_WINDOW_P (XFRAME (frame)))
2427 /* Warping the mouse will cause enternotify and focus events. */
2428 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
2429 #else
2430 #if defined (MSDOS)
2431 if (FRAME_MSDOS_P (XFRAME (frame)))
2433 Fselect_frame (frame, Qnil);
2434 mouse_moveto (XINT (x), XINT (y));
2436 #else
2437 #ifdef HAVE_GPM
2439 Fselect_frame (frame, Qnil);
2440 term_mouse_moveto (XINT (x), XINT (y));
2442 #endif
2443 #endif
2444 #endif
2446 return Qnil;
2449 static void make_frame_visible_1 (Lisp_Object);
2451 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
2452 0, 1, "",
2453 doc: /* Make the frame FRAME visible (assuming it is an X window).
2454 If omitted, FRAME defaults to the currently selected frame. */)
2455 (Lisp_Object frame)
2457 struct frame *f = decode_live_frame (frame);
2459 /* I think this should be done with a hook. */
2460 #ifdef HAVE_WINDOW_SYSTEM
2461 if (FRAME_WINDOW_P (f))
2462 x_make_frame_visible (f);
2463 #endif
2465 make_frame_visible_1 (f->root_window);
2467 /* Make menu bar update for the Buffers and Frames menus. */
2468 /* windows_or_buffers_changed = 15; FIXME: Why? */
2470 XSETFRAME (frame, f);
2471 return frame;
2474 /* Update the display_time slot of the buffers shown in WINDOW
2475 and all its descendants. */
2477 static void
2478 make_frame_visible_1 (Lisp_Object window)
2480 struct window *w;
2482 for (; !NILP (window); window = w->next)
2484 w = XWINDOW (window);
2485 if (WINDOWP (w->contents))
2486 make_frame_visible_1 (w->contents);
2487 else
2488 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2492 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2493 0, 2, "",
2494 doc: /* Make the frame FRAME invisible.
2495 If omitted, FRAME defaults to the currently selected frame.
2496 On graphical displays, invisible frames are not updated and are
2497 usually not displayed at all, even in a window system's \"taskbar\".
2499 Normally you may not make FRAME invisible if all other frames are invisible,
2500 but if the second optional argument FORCE is non-nil, you may do so.
2502 This function has no effect on text terminal frames. Such frames are
2503 always considered visible, whether or not they are currently being
2504 displayed in the terminal. */)
2505 (Lisp_Object frame, Lisp_Object force)
2507 struct frame *f = decode_live_frame (frame);
2509 if (NILP (force) && !other_frames (f, true, false))
2510 error ("Attempt to make invisible the sole visible or iconified frame");
2512 /* Don't allow minibuf_window to remain on an invisible frame. */
2513 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2515 /* I think this should be done with a hook. */
2516 #ifdef HAVE_WINDOW_SYSTEM
2517 if (FRAME_WINDOW_P (f))
2518 x_make_frame_invisible (f);
2519 #endif
2521 /* Make menu bar update for the Buffers and Frames menus. */
2522 windows_or_buffers_changed = 16;
2524 return Qnil;
2527 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2528 0, 1, "",
2529 doc: /* Make the frame FRAME into an icon.
2530 If omitted, FRAME defaults to the currently selected frame. */)
2531 (Lisp_Object frame)
2533 struct frame *f = decode_live_frame (frame);
2535 /* Don't allow minibuf_window to remain on an iconified frame. */
2536 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2538 /* I think this should be done with a hook. */
2539 if (FRAME_WINDOW_P (f))
2541 #ifdef HAVE_WINDOW_SYSTEM
2542 x_iconify_frame (f);
2543 #endif
2546 return Qnil;
2549 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2550 1, 1, 0,
2551 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2552 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2553 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2554 On graphical displays, invisible frames are not updated and are
2555 usually not displayed at all, even in a window system's \"taskbar\".
2557 If FRAME is a text terminal frame, this always returns t.
2558 Such frames are always considered visible, whether or not they are
2559 currently being displayed on the terminal. */)
2560 (Lisp_Object frame)
2562 CHECK_LIVE_FRAME (frame);
2564 if (FRAME_VISIBLE_P (XFRAME (frame)))
2565 return Qt;
2566 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2567 return Qicon;
2568 return Qnil;
2571 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2572 0, 0, 0,
2573 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2574 (void)
2576 Lisp_Object tail, frame, value = Qnil;
2578 FOR_EACH_FRAME (tail, frame)
2579 if (FRAME_VISIBLE_P (XFRAME (frame)))
2580 value = Fcons (frame, value);
2582 return value;
2586 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2587 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2588 If FRAME is invisible or iconified, make it visible.
2589 If you don't specify a frame, the selected frame is used.
2590 If Emacs is displaying on an ordinary terminal or some other device which
2591 doesn't support multiple overlapping frames, this function selects FRAME. */)
2592 (Lisp_Object frame)
2594 struct frame *f = decode_live_frame (frame);
2596 XSETFRAME (frame, f);
2598 if (FRAME_TERMCAP_P (f))
2599 /* On a text terminal select FRAME. */
2600 Fselect_frame (frame, Qnil);
2601 else
2602 /* Do like the documentation says. */
2603 Fmake_frame_visible (frame);
2605 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2606 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2608 return Qnil;
2611 /* Should we have a corresponding function called Flower_Power? */
2612 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2613 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2614 If you don't specify a frame, the selected frame is used.
2615 If Emacs is displaying on an ordinary terminal or some other device which
2616 doesn't support multiple overlapping frames, this function does nothing. */)
2617 (Lisp_Object frame)
2619 struct frame *f = decode_live_frame (frame);
2621 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2622 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2624 return Qnil;
2628 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2629 1, 2, 0,
2630 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2631 In other words, switch-frame events caused by events in FRAME will
2632 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2633 FOCUS-FRAME after reading an event typed at FRAME.
2635 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2636 frame again receives its own keystrokes.
2638 Focus redirection is useful for temporarily redirecting keystrokes to
2639 a surrogate minibuffer frame when a frame doesn't have its own
2640 minibuffer window.
2642 A frame's focus redirection can be changed by `select-frame'. If frame
2643 FOO is selected, and then a different frame BAR is selected, any
2644 frames redirecting their focus to FOO are shifted to redirect their
2645 focus to BAR. This allows focus redirection to work properly when the
2646 user switches from one frame to another using `select-window'.
2648 This means that a frame whose focus is redirected to itself is treated
2649 differently from a frame whose focus is redirected to nil; the former
2650 is affected by `select-frame', while the latter is not.
2652 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2653 (Lisp_Object frame, Lisp_Object focus_frame)
2655 /* Note that we don't check for a live frame here. It's reasonable
2656 to redirect the focus of a frame you're about to delete, if you
2657 know what other frame should receive those keystrokes. */
2658 struct frame *f = decode_any_frame (frame);
2660 if (! NILP (focus_frame))
2661 CHECK_LIVE_FRAME (focus_frame);
2663 fset_focus_frame (f, focus_frame);
2665 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2666 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2668 return Qnil;
2672 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2673 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2674 If FRAME is omitted or nil, the selected frame is used.
2675 Return nil if FRAME's focus is not redirected.
2676 See `redirect-frame-focus'. */)
2677 (Lisp_Object frame)
2679 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2682 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 2, 0,
2683 doc: /* Set the input focus to FRAME.
2684 FRAME nil means use the selected frame. Optional argument NOACTIVATE
2685 means do not activate FRAME.
2687 If there is no window system support, this function does nothing. */)
2688 (Lisp_Object frame, Lisp_Object noactivate)
2690 #ifdef HAVE_WINDOW_SYSTEM
2691 x_focus_frame (decode_window_system_frame (frame), !NILP (noactivate));
2692 #endif
2693 return Qnil;
2696 DEFUN ("frame-after-make-frame",
2697 Fframe_after_make_frame,
2698 Sframe_after_make_frame, 2, 2, 0,
2699 doc: /* Mark FRAME as made.
2700 FRAME nil means use the selected frame. Second argument MADE non-nil
2701 means functions on `window-configuration-change-hook' are called
2702 whenever the window configuration of FRAME changes. MADE nil means
2703 these functions are not called.
2705 This function is currently called by `make-frame' only and should be
2706 otherwise used with utter care to avoid that running functions on
2707 `window-configuration-change-hook' is impeded forever. */)
2708 (Lisp_Object frame, Lisp_Object made)
2710 struct frame *f = decode_live_frame (frame);
2711 f->after_make_frame = !NILP (made);
2712 f->inhibit_horizontal_resize = false;
2713 f->inhibit_vertical_resize = false;
2714 return made;
2718 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2720 void
2721 frames_discard_buffer (Lisp_Object buffer)
2723 Lisp_Object frame, tail;
2725 FOR_EACH_FRAME (tail, frame)
2727 fset_buffer_list
2728 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2729 fset_buried_buffer_list
2730 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2734 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2735 If the alist already has an element for PROP, we change it. */
2737 void
2738 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2740 register Lisp_Object tem;
2742 tem = Fassq (prop, *alistptr);
2743 if (EQ (tem, Qnil))
2744 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2745 else
2746 Fsetcdr (tem, val);
2749 static int
2750 frame_name_fnn_p (char *str, ptrdiff_t len)
2752 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2754 char *p = str + 2;
2755 while ('0' <= *p && *p <= '9')
2756 p++;
2757 if (p == str + len)
2758 return 1;
2760 return 0;
2763 /* Set the name of the terminal frame. Also used by MSDOS frames.
2764 Modeled after x_set_name which is used for WINDOW frames. */
2766 static void
2767 set_term_frame_name (struct frame *f, Lisp_Object name)
2769 f->explicit_name = ! NILP (name);
2771 /* If NAME is nil, set the name to F<num>. */
2772 if (NILP (name))
2774 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2776 /* Check for no change needed in this very common case
2777 before we do any consing. */
2778 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2779 return;
2781 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2783 else
2785 CHECK_STRING (name);
2787 /* Don't change the name if it's already NAME. */
2788 if (! NILP (Fstring_equal (name, f->name)))
2789 return;
2791 /* Don't allow the user to set the frame name to F<num>, so it
2792 doesn't clash with the names we generate for terminal frames. */
2793 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2794 error ("Frame names of the form F<num> are usurped by Emacs");
2797 fset_name (f, name);
2798 update_mode_lines = 16;
2801 void
2802 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2804 register Lisp_Object old_alist_elt;
2806 if (EQ (prop, Qminibuffer))
2808 if (WINDOWP (val))
2810 if (!MINI_WINDOW_P (XWINDOW (val)))
2811 error ("The `minibuffer' parameter does not specify a valid minibuffer window");
2812 else if (FRAME_MINIBUF_ONLY_P (f))
2814 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2815 val = Qonly;
2816 else
2817 error ("Can't change the minibuffer window of a minibuffer-only frame");
2819 else if (FRAME_HAS_MINIBUF_P (f))
2821 if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
2822 val = Qt;
2823 else
2824 error ("Can't change the minibuffer window of a frame with its own minibuffer");
2826 else
2827 /* Store the chosen minibuffer window. */
2828 fset_minibuffer_window (f, val);
2830 else
2832 Lisp_Object old_val = Fcdr (Fassq (Qminibuffer, f->param_alist));
2834 if (!NILP (old_val))
2836 if (WINDOWP (old_val) && NILP (val))
2837 /* Don't change the value for a minibuffer-less frame if
2838 only nil was specified as new value. */
2839 val = old_val;
2840 else if (!EQ (old_val, val))
2841 error ("Can't change the `minibuffer' parameter of this frame");
2846 /* Check each parent-frame and delete-before parameter for a
2847 circular dependency. Do not check between parameters, so you can
2848 still create circular dependencies with different properties, for
2849 example a chain of frames F1->F2->...Fn such that F1 is an ancestor
2850 frame of Fn and thus cannot be deleted before Fn and a second chain
2851 Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
2852 else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
2854 Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
2856 if (!EQ (oldval, val) && !NILP (val))
2858 Lisp_Object frame;
2859 Lisp_Object frame1 = val;
2861 if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
2862 error ("Invalid `%s' frame parameter",
2863 SSDATA (SYMBOL_NAME (prop)));
2865 XSETFRAME (frame, f);
2867 while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
2868 if (EQ (frame1, frame))
2869 error ("Circular specification of `%s' frame parameter",
2870 SSDATA (SYMBOL_NAME (prop)));
2871 else
2872 frame1 = get_frame_param (XFRAME (frame1), prop);
2876 /* The buffer-list parameters are stored in a special place and not
2877 in the alist. All buffers must be live. */
2878 else if (EQ (prop, Qbuffer_list))
2880 Lisp_Object list = Qnil;
2881 for (; CONSP (val); val = XCDR (val))
2882 if (!NILP (Fbuffer_live_p (XCAR (val))))
2883 list = Fcons (XCAR (val), list);
2884 fset_buffer_list (f, Fnreverse (list));
2885 return;
2887 else if (EQ (prop, Qburied_buffer_list))
2889 Lisp_Object list = Qnil;
2890 for (; CONSP (val); val = XCDR (val))
2891 if (!NILP (Fbuffer_live_p (XCAR (val))))
2892 list = Fcons (XCAR (val), list);
2893 fset_buried_buffer_list (f, Fnreverse (list));
2894 return;
2897 /* The tty color needed to be set before the frame's parameter
2898 alist was updated with the new value. This is not true any more,
2899 but we still do this test early on. */
2900 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2901 && f == FRAME_TTY (f)->previous_frame)
2902 /* Force redisplay of this tty. */
2903 FRAME_TTY (f)->previous_frame = NULL;
2905 /* Update the frame parameter alist. */
2906 old_alist_elt = Fassq (prop, f->param_alist);
2907 if (EQ (old_alist_elt, Qnil))
2908 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2909 else
2910 Fsetcdr (old_alist_elt, val);
2912 /* Update some other special parameters in their special places
2913 in addition to the alist. */
2915 if (EQ (prop, Qbuffer_predicate))
2916 fset_buffer_predicate (f, val);
2918 if (! FRAME_WINDOW_P (f))
2920 if (EQ (prop, Qmenu_bar_lines))
2921 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2922 else if (EQ (prop, Qname))
2923 set_term_frame_name (f, val);
2927 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2928 is not an unspecified foreground or background color. */
2930 static Lisp_Object
2931 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
2933 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
2934 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
2935 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
2936 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
2939 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
2940 doc: /* Return the parameters-alist of frame FRAME.
2941 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2942 The meaningful PARMs depend on the kind of frame.
2943 If FRAME is omitted or nil, return information on the currently selected frame. */)
2944 (Lisp_Object frame)
2946 Lisp_Object alist;
2947 struct frame *f = decode_any_frame (frame);
2948 int height, width;
2950 if (!FRAME_LIVE_P (f))
2951 return Qnil;
2953 alist = Fcopy_alist (f->param_alist);
2955 if (!FRAME_WINDOW_P (f))
2957 Lisp_Object elt;
2959 /* If the frame's parameter alist says the colors are
2960 unspecified and reversed, take the frame's background pixel
2961 for foreground and vice versa. */
2962 elt = Fassq (Qforeground_color, alist);
2963 if (CONSP (elt) && STRINGP (XCDR (elt)))
2965 elt = frame_unspecified_color (f, XCDR (elt));
2966 if (!NILP (elt))
2967 store_in_alist (&alist, Qforeground_color, elt);
2969 else
2970 store_in_alist (&alist, Qforeground_color,
2971 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
2972 elt = Fassq (Qbackground_color, alist);
2973 if (CONSP (elt) && STRINGP (XCDR (elt)))
2975 elt = frame_unspecified_color (f, XCDR (elt));
2976 if (!NILP (elt))
2977 store_in_alist (&alist, Qbackground_color, elt);
2979 else
2980 store_in_alist (&alist, Qbackground_color,
2981 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
2982 store_in_alist (&alist, Qfont,
2983 build_string (FRAME_MSDOS_P (f)
2984 ? "ms-dos"
2985 : FRAME_W32_P (f) ? "w32term"
2986 :"tty"));
2988 store_in_alist (&alist, Qname, f->name);
2989 height = (f->new_height
2990 ? (f->new_pixelwise
2991 ? (f->new_height / FRAME_LINE_HEIGHT (f))
2992 : f->new_height)
2993 : FRAME_LINES (f));
2994 store_in_alist (&alist, Qheight, make_number (height));
2995 width = (f->new_width
2996 ? (f->new_pixelwise
2997 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
2998 : f->new_width)
2999 : FRAME_COLS (f));
3000 store_in_alist (&alist, Qwidth, make_number (width));
3001 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
3002 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
3003 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
3004 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
3006 /* I think this should be done with a hook. */
3007 #ifdef HAVE_WINDOW_SYSTEM
3008 if (FRAME_WINDOW_P (f))
3009 x_report_frame_params (f, &alist);
3010 else
3011 #endif
3013 /* This ought to be correct in f->param_alist for an X frame. */
3014 Lisp_Object lines;
3015 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
3016 store_in_alist (&alist, Qmenu_bar_lines, lines);
3019 return alist;
3023 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
3024 doc: /* Return FRAME's value for parameter PARAMETER.
3025 If FRAME is nil, describe the currently selected frame. */)
3026 (Lisp_Object frame, Lisp_Object parameter)
3028 struct frame *f = decode_any_frame (frame);
3029 Lisp_Object value = Qnil;
3031 CHECK_SYMBOL (parameter);
3033 XSETFRAME (frame, f);
3035 if (FRAME_LIVE_P (f))
3037 /* Avoid consing in frequent cases. */
3038 if (EQ (parameter, Qname))
3039 value = f->name;
3040 #ifdef HAVE_WINDOW_SYSTEM
3041 /* These are used by vertical motion commands. */
3042 else if (EQ (parameter, Qvertical_scroll_bars))
3043 value = (f->vertical_scroll_bar_type == vertical_scroll_bar_none
3044 ? Qnil
3045 : (f->vertical_scroll_bar_type == vertical_scroll_bar_left
3046 ? Qleft : Qright));
3047 else if (EQ (parameter, Qhorizontal_scroll_bars))
3048 value = f->horizontal_scroll_bars ? Qt : Qnil;
3049 else if (EQ (parameter, Qline_spacing) && f->extra_line_spacing == 0)
3050 /* If this is non-zero, we can't determine whether the user specified
3051 an integer or float value without looking through 'param_alist'. */
3052 value = make_number (0);
3053 else if (EQ (parameter, Qfont) && FRAME_X_P (f))
3054 value = FRAME_FONT (f)->props[FONT_NAME_INDEX];
3055 #endif /* HAVE_WINDOW_SYSTEM */
3056 #ifdef HAVE_X_WINDOWS
3057 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
3058 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
3059 #endif /* HAVE_X_WINDOWS */
3060 else if (EQ (parameter, Qbackground_color)
3061 || EQ (parameter, Qforeground_color))
3063 value = Fassq (parameter, f->param_alist);
3064 if (CONSP (value))
3066 value = XCDR (value);
3067 /* Fframe_parameters puts the actual fg/bg color names,
3068 even if f->param_alist says otherwise. This is
3069 important when param_alist's notion of colors is
3070 "unspecified". We need to do the same here. */
3071 if (STRINGP (value) && !FRAME_WINDOW_P (f))
3073 Lisp_Object tem = frame_unspecified_color (f, value);
3075 if (!NILP (tem))
3076 value = tem;
3079 else
3080 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3082 else if (EQ (parameter, Qdisplay_type)
3083 || EQ (parameter, Qbackground_mode))
3084 value = Fcdr (Fassq (parameter, f->param_alist));
3085 else
3086 /* FIXME: Avoid this code path at all (as well as code duplication)
3087 by sharing more code with Fframe_parameters. */
3088 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
3091 return value;
3095 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
3096 Smodify_frame_parameters, 2, 2, 0,
3097 doc: /* Modify FRAME according to new values of its parameters in ALIST.
3098 If FRAME is nil, it defaults to the selected frame.
3099 ALIST is an alist of parameters to change and their new values.
3100 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
3101 Which PARMs are meaningful depends on the kind of frame.
3102 The meaningful parameters are acted upon, i.e. the frame is changed
3103 according to their new values, and are also stored in the frame's
3104 parameter list so that `frame-parameters' will return them.
3105 PARMs that are not meaningful are still stored in the frame's parameter
3106 list, but are otherwise ignored. */)
3107 (Lisp_Object frame, Lisp_Object alist)
3109 struct frame *f = decode_live_frame (frame);
3110 Lisp_Object prop, val;
3112 /* I think this should be done with a hook. */
3113 #ifdef HAVE_WINDOW_SYSTEM
3114 if (FRAME_WINDOW_P (f))
3115 x_set_frame_parameters (f, alist);
3116 else
3117 #endif
3118 #ifdef MSDOS
3119 if (FRAME_MSDOS_P (f))
3120 IT_set_frame_parameters (f, alist);
3121 else
3122 #endif
3125 EMACS_INT length = XFASTINT (Flength (alist));
3126 ptrdiff_t i;
3127 Lisp_Object *parms;
3128 Lisp_Object *values;
3129 USE_SAFE_ALLOCA;
3130 SAFE_ALLOCA_LISP (parms, 2 * length);
3131 values = parms + length;
3133 /* Extract parm names and values into those vectors. */
3135 for (i = 0; CONSP (alist); alist = XCDR (alist))
3137 Lisp_Object elt;
3139 elt = XCAR (alist);
3140 parms[i] = Fcar (elt);
3141 values[i] = Fcdr (elt);
3142 i++;
3145 /* Now process them in reverse of specified order. */
3146 while (--i >= 0)
3148 prop = parms[i];
3149 val = values[i];
3150 store_frame_param (f, prop, val);
3152 if (EQ (prop, Qforeground_color)
3153 || EQ (prop, Qbackground_color))
3154 update_face_from_frame_parameter (f, prop, val);
3157 SAFE_FREE ();
3159 return Qnil;
3162 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
3163 0, 1, 0,
3164 doc: /* Height in pixels of a line in the font in frame FRAME.
3165 If FRAME is omitted or nil, the selected frame is used.
3166 For a terminal frame, the value is always 1. */)
3167 (Lisp_Object frame)
3169 #ifdef HAVE_WINDOW_SYSTEM
3170 struct frame *f = decode_any_frame (frame);
3172 if (FRAME_WINDOW_P (f))
3173 return make_number (FRAME_LINE_HEIGHT (f));
3174 else
3175 #endif
3176 return make_number (1);
3180 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
3181 0, 1, 0,
3182 doc: /* Width in pixels of characters in the font in frame FRAME.
3183 If FRAME is omitted or nil, the selected frame is used.
3184 On a graphical screen, the width is the standard width of the default font.
3185 For a terminal screen, the value is always 1. */)
3186 (Lisp_Object frame)
3188 #ifdef HAVE_WINDOW_SYSTEM
3189 struct frame *f = decode_any_frame (frame);
3191 if (FRAME_WINDOW_P (f))
3192 return make_number (FRAME_COLUMN_WIDTH (f));
3193 else
3194 #endif
3195 return make_number (1);
3198 DEFUN ("frame-native-width", Fframe_native_width,
3199 Sframe_native_width, 0, 1, 0,
3200 doc: /* Return FRAME's native width in pixels.
3201 For a terminal frame, the result really gives the width in characters.
3202 If FRAME is omitted or nil, the selected frame is used. */)
3203 (Lisp_Object frame)
3205 struct frame *f = decode_any_frame (frame);
3207 #ifdef HAVE_WINDOW_SYSTEM
3208 if (FRAME_WINDOW_P (f))
3209 return make_number (FRAME_PIXEL_WIDTH (f));
3210 else
3211 #endif
3212 return make_number (FRAME_TOTAL_COLS (f));
3215 DEFUN ("frame-native-height", Fframe_native_height,
3216 Sframe_native_height, 0, 1, 0,
3217 doc: /* Return FRAME's native height in pixels.
3218 If FRAME is omitted or nil, the selected frame is used. The exact value
3219 of the result depends on the window-system and toolkit in use:
3221 In the Gtk+ and NS versions, it includes only any window (including the
3222 minibuffer or echo area), mode line, and header line. It does not
3223 include the tool bar or menu bar. With other graphical versions, it may
3224 also include the tool bar and the menu bar.
3226 For a text terminal, it includes the menu bar. In this case, the
3227 result is really in characters rather than pixels (i.e., is identical
3228 to `frame-height'). */)
3229 (Lisp_Object frame)
3231 struct frame *f = decode_any_frame (frame);
3233 #ifdef HAVE_WINDOW_SYSTEM
3234 if (FRAME_WINDOW_P (f))
3235 return make_number (FRAME_PIXEL_HEIGHT (f));
3236 else
3237 #endif
3238 return make_number (FRAME_TOTAL_LINES (f));
3241 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
3242 Stool_bar_pixel_width, 0, 1, 0,
3243 doc: /* Return width in pixels of FRAME's tool bar.
3244 The result is greater than zero only when the tool bar is on the left
3245 or right side of FRAME. If FRAME is omitted or nil, the selected frame
3246 is used. */)
3247 (Lisp_Object frame)
3249 #ifdef FRAME_TOOLBAR_WIDTH
3250 struct frame *f = decode_any_frame (frame);
3252 if (FRAME_WINDOW_P (f))
3253 return make_number (FRAME_TOOLBAR_WIDTH (f));
3254 #endif
3255 return make_number (0);
3258 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
3259 doc: /* Return width in columns of FRAME's text area. */)
3260 (Lisp_Object frame)
3262 return make_number (FRAME_COLS (decode_any_frame (frame)));
3265 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
3266 doc: /* Return height in lines of FRAME's text area. */)
3267 (Lisp_Object frame)
3269 return make_number (FRAME_LINES (decode_any_frame (frame)));
3272 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
3273 doc: /* Return number of total columns of FRAME. */)
3274 (Lisp_Object frame)
3276 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
3279 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
3280 doc: /* Return number of total lines of FRAME. */)
3281 (Lisp_Object frame)
3283 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
3286 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
3287 doc: /* Return text area width of FRAME in pixels. */)
3288 (Lisp_Object frame)
3290 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
3293 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
3294 doc: /* Return text area height of FRAME in pixels. */)
3295 (Lisp_Object frame)
3297 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
3300 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
3301 doc: /* Return scroll bar width of FRAME in pixels. */)
3302 (Lisp_Object frame)
3304 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
3307 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
3308 doc: /* Return scroll bar height of FRAME in pixels. */)
3309 (Lisp_Object frame)
3311 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
3314 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
3315 doc: /* Return fringe width of FRAME in pixels. */)
3316 (Lisp_Object frame)
3318 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
3321 DEFUN ("frame-internal-border-width", Fframe_internal_border_width, Sframe_internal_border_width, 0, 1, 0,
3322 doc: /* Return width of FRAME's internal border in pixels. */)
3323 (Lisp_Object frame)
3325 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
3328 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
3329 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
3330 (Lisp_Object frame)
3332 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
3335 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
3336 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
3337 (Lisp_Object frame)
3339 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
3342 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
3343 doc: /* Set text height of frame FRAME to HEIGHT lines.
3344 Optional third arg PRETEND non-nil means that redisplay should use
3345 HEIGHT lines but that the idea of the actual height of the frame should
3346 not be changed.
3348 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3349 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
3350 window managers may refuse to honor a HEIGHT that is not an integer
3351 multiple of the default frame font height. */)
3352 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
3354 struct frame *f = decode_live_frame (frame);
3355 int pixel_height;
3357 CHECK_TYPE_RANGED_INTEGER (int, height);
3359 pixel_height = (!NILP (pixelwise)
3360 ? XINT (height)
3361 : XINT (height) * FRAME_LINE_HEIGHT (f));
3362 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
3364 return Qnil;
3367 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
3368 doc: /* Set text width of frame FRAME to WIDTH columns.
3369 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
3370 columns but that the idea of the actual width of the frame should not
3371 be changed.
3373 Optional fourth argument PIXELWISE non-nil means that FRAME should be
3374 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
3375 window managers may refuse to honor a WIDTH that is not an integer
3376 multiple of the default frame font width. */)
3377 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
3379 struct frame *f = decode_live_frame (frame);
3380 int pixel_width;
3382 CHECK_TYPE_RANGED_INTEGER (int, width);
3384 pixel_width = (!NILP (pixelwise)
3385 ? XINT (width)
3386 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3387 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
3389 return Qnil;
3392 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
3393 doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
3394 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
3395 When `frame-resize-pixelwise' is nil, some window managers may refuse to
3396 honor a WIDTH that is not an integer multiple of the default frame font
3397 width or a HEIGHT that is not an integer multiple of the default frame
3398 font height. */)
3399 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
3401 struct frame *f = decode_live_frame (frame);
3402 int pixel_width, pixel_height;
3404 CHECK_TYPE_RANGED_INTEGER (int, width);
3405 CHECK_TYPE_RANGED_INTEGER (int, height);
3407 pixel_width = (!NILP (pixelwise)
3408 ? XINT (width)
3409 : XINT (width) * FRAME_COLUMN_WIDTH (f));
3410 pixel_height = (!NILP (pixelwise)
3411 ? XINT (height)
3412 : XINT (height) * FRAME_LINE_HEIGHT (f));
3413 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
3415 return Qnil;
3418 DEFUN ("frame-position", Fframe_position,
3419 Sframe_position, 0, 1, 0,
3420 doc: /* Return top left corner of FRAME in pixels.
3421 FRAME must be a live frame and defaults to the selected one. The return
3422 value is a cons (x, y) of the coordinates of the top left corner of
3423 FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
3424 display. */)
3425 (Lisp_Object frame)
3427 register struct frame *f = decode_live_frame (frame);
3429 return Fcons (make_number (f->left_pos), make_number (f->top_pos));
3432 DEFUN ("set-frame-position", Fset_frame_position,
3433 Sset_frame_position, 3, 3, 0,
3434 doc: /* Set position of FRAME to (X, Y).
3435 FRAME must be a live frame and defaults to the selected one. X and Y,
3436 if positive, specify the coordinate of the left and top edge of FRAME's
3437 outer frame in pixels relative to an origin (0, 0) of FRAME's display.
3438 If any of X or Y is negative, it specifies the coordinates of the right
3439 or bottom edge of the outer frame of FRAME relative to the right or
3440 bottom edge of FRAME's display. */)
3441 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
3443 struct frame *f = decode_live_frame (frame);
3445 CHECK_TYPE_RANGED_INTEGER (int, x);
3446 CHECK_TYPE_RANGED_INTEGER (int, y);
3448 /* I think this should be done with a hook. */
3449 if (FRAME_WINDOW_P (f))
3451 #ifdef HAVE_WINDOW_SYSTEM
3452 x_set_offset (f, XINT (x), XINT (y), 1);
3453 #endif
3456 return Qt;
3459 /***********************************************************************
3460 Frame Parameters
3461 ***********************************************************************/
3463 /* Connect the frame-parameter names for X frames
3464 to the ways of passing the parameter values to the window system.
3466 The name of a parameter, as a Lisp symbol,
3467 has an `x-frame-parameter' property which is an integer in Lisp
3468 that is an index in this table. */
3470 struct frame_parm_table {
3471 const char *name;
3472 int sym;
3475 static const struct frame_parm_table frame_parms[] =
3477 {"auto-raise", SYMBOL_INDEX (Qauto_raise)},
3478 {"auto-lower", SYMBOL_INDEX (Qauto_lower)},
3479 {"background-color", -1},
3480 {"border-color", SYMBOL_INDEX (Qborder_color)},
3481 {"border-width", SYMBOL_INDEX (Qborder_width)},
3482 {"cursor-color", SYMBOL_INDEX (Qcursor_color)},
3483 {"cursor-type", SYMBOL_INDEX (Qcursor_type)},
3484 {"font", -1},
3485 {"foreground-color", -1},
3486 {"icon-name", SYMBOL_INDEX (Qicon_name)},
3487 {"icon-type", SYMBOL_INDEX (Qicon_type)},
3488 {"internal-border-width", SYMBOL_INDEX (Qinternal_border_width)},
3489 {"right-divider-width", SYMBOL_INDEX (Qright_divider_width)},
3490 {"bottom-divider-width", SYMBOL_INDEX (Qbottom_divider_width)},
3491 {"menu-bar-lines", SYMBOL_INDEX (Qmenu_bar_lines)},
3492 {"mouse-color", SYMBOL_INDEX (Qmouse_color)},
3493 {"name", SYMBOL_INDEX (Qname)},
3494 {"scroll-bar-width", SYMBOL_INDEX (Qscroll_bar_width)},
3495 {"scroll-bar-height", SYMBOL_INDEX (Qscroll_bar_height)},
3496 {"title", SYMBOL_INDEX (Qtitle)},
3497 {"unsplittable", SYMBOL_INDEX (Qunsplittable)},
3498 {"vertical-scroll-bars", SYMBOL_INDEX (Qvertical_scroll_bars)},
3499 {"horizontal-scroll-bars", SYMBOL_INDEX (Qhorizontal_scroll_bars)},
3500 {"visibility", SYMBOL_INDEX (Qvisibility)},
3501 {"tool-bar-lines", SYMBOL_INDEX (Qtool_bar_lines)},
3502 {"scroll-bar-foreground", SYMBOL_INDEX (Qscroll_bar_foreground)},
3503 {"scroll-bar-background", SYMBOL_INDEX (Qscroll_bar_background)},
3504 {"screen-gamma", SYMBOL_INDEX (Qscreen_gamma)},
3505 {"line-spacing", SYMBOL_INDEX (Qline_spacing)},
3506 {"left-fringe", SYMBOL_INDEX (Qleft_fringe)},
3507 {"right-fringe", SYMBOL_INDEX (Qright_fringe)},
3508 {"wait-for-wm", SYMBOL_INDEX (Qwait_for_wm)},
3509 {"fullscreen", SYMBOL_INDEX (Qfullscreen)},
3510 {"font-backend", SYMBOL_INDEX (Qfont_backend)},
3511 {"alpha", SYMBOL_INDEX (Qalpha)},
3512 {"sticky", SYMBOL_INDEX (Qsticky)},
3513 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3514 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3515 {"undecorated", SYMBOL_INDEX (Qundecorated)},
3516 {"parent-frame", SYMBOL_INDEX (Qparent_frame)},
3517 {"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
3518 {"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
3519 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3520 {"z-group", SYMBOL_INDEX (Qz_group)},
3521 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3522 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
3525 #ifdef HAVE_WINDOW_SYSTEM
3527 /* Enumeration type for switch in frame_float. */
3528 enum frame_float_type
3530 FRAME_FLOAT_WIDTH,
3531 FRAME_FLOAT_HEIGHT,
3532 FRAME_FLOAT_LEFT,
3533 FRAME_FLOAT_TOP
3537 * frame_float:
3539 * Process the value VAL of the float type frame parameter 'width',
3540 * 'height', 'left', or 'top' specified via a frame_float_type
3541 * enumeration type WHAT for frame F. Such parameters relate the outer
3542 * size or position of F to the size of the F's display or parent frame
3543 * which have to be both available in some way.
3545 * The return value is a size or position value in pixels. VAL must be
3546 * in the range 0.0 to 1.0 where a width/height of 0.0 means to return 0
3547 * and 1.0 means to return the full width/height of the display/parent.
3548 * For positions, 0.0 means position in the left/top corner of the
3549 * display/parent while 1.0 means to position at the right/bottom corner
3550 * of the display/parent frame.
3552 * Set PARENT_DONE and OUTER_DONE to avoid recalculation of the outer
3553 * size or parent or display attributes when more float parameters are
3554 * calculated in a row: -1 means not processed yet, 0 means processing
3555 * failed, 1 means processing succeeded.
3557 * Return DEFAULT_VALUE when processing fails for whatever reason with
3558 * one exception: When calculating F's outer edges fails (probably
3559 * because F has not been created yet) return the difference between F's
3560 * native and text size.
3562 static int
3563 frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
3564 int *parent_done, int *outer_done, int default_value)
3566 double d_val = XFLOAT_DATA (val);
3568 if (d_val < 0.0 || d_val > 1.0)
3569 /* Invalid VAL. */
3570 return default_value;
3571 else
3573 static unsigned parent_width, parent_height;
3574 static int parent_left, parent_top;
3575 static unsigned outer_minus_text_width, outer_minus_text_height;
3576 struct frame *p = FRAME_PARENT_FRAME (f);
3578 if (*parent_done == 1)
3580 else if (p)
3582 parent_width = FRAME_PIXEL_WIDTH (p);
3583 parent_height = FRAME_PIXEL_HEIGHT (p);
3584 *parent_done = 1;
3586 else
3588 if (*parent_done == 0)
3589 /* No workarea available. */
3590 return default_value;
3591 else if (*parent_done == -1)
3593 Lisp_Object monitor_attributes;
3594 Lisp_Object workarea;
3595 Lisp_Object frame;
3597 XSETFRAME (frame, f);
3598 monitor_attributes = Fcar (call1 (Qdisplay_monitor_attributes_list, frame));
3599 if (NILP (monitor_attributes))
3601 /* No monitor attributes available. */
3602 *parent_done = 0;
3604 return default_value;
3607 workarea = Fcdr (Fassq (Qworkarea, monitor_attributes));
3608 if (NILP (workarea))
3610 /* No workarea available. */
3611 *parent_done = 0;
3613 return default_value;
3616 /* Workarea available. */
3617 parent_left = XINT (Fnth (make_number (0), workarea));
3618 parent_top = XINT (Fnth (make_number (1), workarea));
3619 parent_width = XINT (Fnth (make_number (2), workarea));
3620 parent_height = XINT (Fnth (make_number (3), workarea));
3621 *parent_done = 1;
3625 if (*outer_done == 1)
3627 else if (FRAME_UNDECORATED (f))
3629 outer_minus_text_width
3630 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3631 outer_minus_text_height
3632 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3633 *outer_done = 1;
3635 else if (*outer_done == 0)
3636 /* No outer size available. */
3637 return default_value;
3638 else if (*outer_done == -1)
3640 Lisp_Object frame, outer_edges;
3642 XSETFRAME (frame, f);
3643 outer_edges = call2 (Qframe_edges, frame, Qouter_edges);
3645 if (!NILP (outer_edges))
3647 outer_minus_text_width
3648 = (XINT (Fnth (make_number (2), outer_edges))
3649 - XINT (Fnth (make_number (0), outer_edges))
3650 - FRAME_TEXT_WIDTH (f));
3651 outer_minus_text_height
3652 = (XINT (Fnth (make_number (3), outer_edges))
3653 - XINT (Fnth (make_number (1), outer_edges))
3654 - FRAME_TEXT_HEIGHT (f));
3656 else
3658 /* If we can't get any outer edges, proceed as if the frame
3659 were undecorated. */
3660 outer_minus_text_width
3661 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3662 outer_minus_text_height
3663 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3666 *outer_done = 1;
3669 switch (what)
3671 case FRAME_FLOAT_WIDTH:
3672 return parent_width * d_val - outer_minus_text_width;
3674 case FRAME_FLOAT_HEIGHT:
3675 return parent_height * d_val - outer_minus_text_height;
3677 case FRAME_FLOAT_LEFT:
3679 int rest_width = (parent_width
3680 - FRAME_TEXT_WIDTH (f)
3681 - outer_minus_text_width);
3683 if (p)
3684 return (rest_width <= 0 ? 0 : d_val * rest_width);
3685 else
3686 return (rest_width <= 0
3687 ? parent_left
3688 : parent_left + d_val * rest_width);
3690 case FRAME_FLOAT_TOP:
3692 int rest_height = (parent_height
3693 - FRAME_TEXT_HEIGHT (f)
3694 - outer_minus_text_height);
3696 if (p)
3697 return (rest_height <= 0 ? 0 : d_val * rest_height);
3698 else
3699 return (rest_height <= 0
3700 ? parent_top
3701 : parent_top + d_val * rest_height);
3703 default:
3704 emacs_abort ();
3709 /* Change the parameters of frame F as specified by ALIST.
3710 If a parameter is not specially recognized, do nothing special;
3711 otherwise call the `x_set_...' function for that parameter.
3712 Except for certain geometry properties, always call store_frame_param
3713 to store the new value in the parameter alist. */
3715 void
3716 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3718 Lisp_Object tail, frame;
3721 /* If both of these parameters are present, it's more efficient to
3722 set them both at once. So we wait until we've looked at the
3723 entire list before we set them. */
3724 int width = -1, height = -1; /* -1 denotes they were not changed. */
3726 /* Same here. */
3727 Lisp_Object left, top;
3729 /* Same with these. */
3730 Lisp_Object icon_left, icon_top;
3732 /* And with this. */
3733 Lisp_Object fullscreen;
3734 bool fullscreen_change = false;
3736 /* Record in these vectors all the parms specified. */
3737 Lisp_Object *parms;
3738 Lisp_Object *values;
3739 ptrdiff_t i, j, size;
3740 bool left_no_change = 0, top_no_change = 0;
3741 #ifdef HAVE_X_WINDOWS
3742 bool icon_left_no_change = 0, icon_top_no_change = 0;
3743 #endif
3744 int parent_done = -1, outer_done = -1;
3746 XSETFRAME (frame, f);
3747 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
3748 size++;
3749 CHECK_LIST_END (tail, alist);
3751 USE_SAFE_ALLOCA;
3752 SAFE_ALLOCA_LISP (parms, 2 * size);
3753 values = parms + size;
3755 /* Extract parm names and values into those vectors. */
3757 i = 0, j = size - 1;
3758 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3760 Lisp_Object elt = XCAR (tail), prop = Fcar (elt), val = Fcdr (elt);
3762 /* Some properties are independent of other properties, but other
3763 properties are dependent upon them. These special properties
3764 are foreground_color, background_color (affects cursor_color)
3765 and font (affects fringe widths); they're recorded starting
3766 from the end of PARMS and VALUES to process them first by using
3767 reverse iteration. */
3769 if (EQ (prop, Qforeground_color)
3770 || EQ (prop, Qbackground_color)
3771 || EQ (prop, Qfont))
3773 parms[j] = prop;
3774 values[j] = val;
3775 j--;
3777 else
3779 parms[i] = prop;
3780 values[i] = val;
3781 i++;
3785 /* TAIL and ALIST are not used again below here. */
3786 alist = tail = Qnil;
3788 top = left = Qunbound;
3789 icon_left = icon_top = Qunbound;
3791 /* Reverse order is used to make sure that special
3792 properties noticed above are processed first. */
3793 for (i = size - 1; i >= 0; i--)
3795 Lisp_Object prop, val;
3797 prop = parms[i];
3798 val = values[i];
3800 if (EQ (prop, Qwidth))
3802 if (RANGED_INTEGERP (0, val, INT_MAX))
3803 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3804 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3805 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3806 width = XFASTINT (XCDR (val));
3807 else if (FLOATP (val))
3808 width = frame_float (f, val, FRAME_FLOAT_WIDTH, &parent_done,
3809 &outer_done, -1);
3811 else if (EQ (prop, Qheight))
3813 if (RANGED_INTEGERP (0, val, INT_MAX))
3814 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3815 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3816 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3817 height = XFASTINT (XCDR (val));
3818 else if (FLOATP (val))
3819 height = frame_float (f, val, FRAME_FLOAT_HEIGHT, &parent_done,
3820 &outer_done, -1);
3822 else if (EQ (prop, Qtop))
3823 top = val;
3824 else if (EQ (prop, Qleft))
3825 left = val;
3826 else if (EQ (prop, Qicon_top))
3827 icon_top = val;
3828 else if (EQ (prop, Qicon_left))
3829 icon_left = val;
3830 else if (EQ (prop, Qfullscreen))
3832 fullscreen = val;
3833 fullscreen_change = true;
3835 else
3837 register Lisp_Object param_index, old_value;
3839 old_value = get_frame_param (f, prop);
3841 store_frame_param (f, prop, val);
3843 param_index = Fget (prop, Qx_frame_parameter);
3844 if (NATNUMP (param_index)
3845 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3846 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3847 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3851 /* Don't die if just one of these was set. */
3852 if (EQ (left, Qunbound))
3854 left_no_change = 1;
3855 if (f->left_pos < 0)
3856 left = list2 (Qplus, make_number (f->left_pos));
3857 else
3858 XSETINT (left, f->left_pos);
3860 if (EQ (top, Qunbound))
3862 top_no_change = 1;
3863 if (f->top_pos < 0)
3864 top = list2 (Qplus, make_number (f->top_pos));
3865 else
3866 XSETINT (top, f->top_pos);
3869 /* If one of the icon positions was not set, preserve or default it. */
3870 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3872 #ifdef HAVE_X_WINDOWS
3873 icon_left_no_change = 1;
3874 #endif
3875 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3876 if (NILP (icon_left))
3877 XSETINT (icon_left, 0);
3879 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3881 #ifdef HAVE_X_WINDOWS
3882 icon_top_no_change = 1;
3883 #endif
3884 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3885 if (NILP (icon_top))
3886 XSETINT (icon_top, 0);
3889 /* Don't set these parameters unless they've been explicitly
3890 specified. The window might be mapped or resized while we're in
3891 this function, and we don't want to override that unless the lisp
3892 code has asked for it.
3894 Don't set these parameters unless they actually differ from the
3895 window's current parameters; the window may not actually exist
3896 yet. */
3897 if ((width != -1 && width != FRAME_TEXT_WIDTH (f))
3898 || (height != -1 && height != FRAME_TEXT_HEIGHT (f)))
3899 /* We could consider checking f->after_make_frame here, but I
3900 don't have the faintest idea why the following is needed at
3901 all. With the old setting it can get a Heisenbug when
3902 EmacsFrameResize intermittently provokes a delayed
3903 change_frame_size in the middle of adjust_frame_size. */
3904 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
3905 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters);
3907 if ((!NILP (left) || !NILP (top))
3908 && ! (left_no_change && top_no_change)
3909 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3910 && NUMBERP (top) && XINT (top) == f->top_pos))
3912 int leftpos = 0;
3913 int toppos = 0;
3915 /* Record the signs. */
3916 f->size_hint_flags &= ~ (XNegative | YNegative);
3917 if (EQ (left, Qminus))
3918 f->size_hint_flags |= XNegative;
3919 else if (TYPE_RANGED_INTEGERP (int, left))
3921 leftpos = XINT (left);
3922 if (leftpos < 0)
3923 f->size_hint_flags |= XNegative;
3925 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3926 && CONSP (XCDR (left))
3927 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3929 leftpos = - XINT (XCAR (XCDR (left)));
3930 f->size_hint_flags |= XNegative;
3932 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3933 && CONSP (XCDR (left))
3934 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3935 leftpos = XINT (XCAR (XCDR (left)));
3936 else if (FLOATP (left))
3937 leftpos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
3938 &outer_done, 0);
3940 if (EQ (top, Qminus))
3941 f->size_hint_flags |= YNegative;
3942 else if (TYPE_RANGED_INTEGERP (int, top))
3944 toppos = XINT (top);
3945 if (toppos < 0)
3946 f->size_hint_flags |= YNegative;
3948 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3949 && CONSP (XCDR (top))
3950 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3952 toppos = - XINT (XCAR (XCDR (top)));
3953 f->size_hint_flags |= YNegative;
3955 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3956 && CONSP (XCDR (top))
3957 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
3958 toppos = XINT (XCAR (XCDR (top)));
3959 else if (FLOATP (top))
3960 toppos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
3961 &outer_done, 0);
3963 /* Store the numeric value of the position. */
3964 f->top_pos = toppos;
3965 f->left_pos = leftpos;
3967 f->win_gravity = NorthWestGravity;
3969 /* Actually set that position, and convert to absolute. */
3970 x_set_offset (f, leftpos, toppos, -1);
3973 if (fullscreen_change)
3975 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
3977 frame_size_history_add
3978 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
3980 store_frame_param (f, Qfullscreen, fullscreen);
3981 if (!EQ (fullscreen, old_value))
3982 x_set_fullscreen (f, fullscreen, old_value);
3986 #ifdef HAVE_X_WINDOWS
3987 if ((!NILP (icon_left) || !NILP (icon_top))
3988 && ! (icon_left_no_change && icon_top_no_change))
3989 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3990 #endif /* HAVE_X_WINDOWS */
3992 SAFE_FREE ();
3996 /* Insert a description of internally-recorded parameters of frame X
3997 into the parameter alist *ALISTPTR that is to be given to the user.
3998 Only parameters that are specific to the X window system
3999 and whose values are not correctly recorded in the frame's
4000 param_alist need to be considered here. */
4002 void
4003 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
4005 Lisp_Object tem;
4006 uprintmax_t w;
4007 char buf[INT_BUFSIZE_BOUND (w)];
4009 /* Represent negative positions (off the top or left screen edge)
4010 in a way that Fmodify_frame_parameters will understand correctly. */
4011 XSETINT (tem, f->left_pos);
4012 if (f->left_pos >= 0)
4013 store_in_alist (alistptr, Qleft, tem);
4014 else
4015 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
4017 XSETINT (tem, f->top_pos);
4018 if (f->top_pos >= 0)
4019 store_in_alist (alistptr, Qtop, tem);
4020 else
4021 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
4023 store_in_alist (alistptr, Qborder_width,
4024 make_number (f->border_width));
4025 store_in_alist (alistptr, Qinternal_border_width,
4026 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
4027 store_in_alist (alistptr, Qright_divider_width,
4028 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
4029 store_in_alist (alistptr, Qbottom_divider_width,
4030 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
4031 store_in_alist (alistptr, Qleft_fringe,
4032 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
4033 store_in_alist (alistptr, Qright_fringe,
4034 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
4035 store_in_alist (alistptr, Qscroll_bar_width,
4036 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4037 ? make_number (0)
4038 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
4039 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4040 /* nil means "use default width"
4041 for non-toolkit scroll bar.
4042 ruler-mode.el depends on this. */
4043 : Qnil));
4044 store_in_alist (alistptr, Qscroll_bar_height,
4045 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
4046 ? make_number (0)
4047 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
4048 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4049 /* nil means "use default height"
4050 for non-toolkit scroll bar. */
4051 : Qnil));
4052 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
4053 MS-Windows it returns a value whose type is HANDLE, which is
4054 actually a pointer. Explicit casting avoids compiler
4055 warnings. */
4056 w = (uintptr_t) FRAME_X_WINDOW (f);
4057 store_in_alist (alistptr, Qwindow_id,
4058 make_formatted_string (buf, "%"pMu, w));
4059 #ifdef HAVE_X_WINDOWS
4060 #ifdef USE_X_TOOLKIT
4061 /* Tooltip frame may not have this widget. */
4062 if (FRAME_X_OUTPUT (f)->widget)
4063 #endif
4064 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
4065 store_in_alist (alistptr, Qouter_window_id,
4066 make_formatted_string (buf, "%"pMu, w));
4067 #endif
4068 store_in_alist (alistptr, Qicon_name, f->icon_name);
4069 store_in_alist (alistptr, Qvisibility,
4070 (FRAME_VISIBLE_P (f) ? Qt
4071 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
4072 store_in_alist (alistptr, Qdisplay,
4073 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
4075 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
4076 tem = Qnil;
4077 else
4078 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
4079 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
4080 store_in_alist (alistptr, Qparent_id, tem);
4081 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
4085 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
4086 the previous value of that parameter, NEW_VALUE is the new value. */
4088 void
4089 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4091 if (NILP (new_value))
4092 f->want_fullscreen = FULLSCREEN_NONE;
4093 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
4094 f->want_fullscreen = FULLSCREEN_BOTH;
4095 else if (EQ (new_value, Qfullwidth))
4096 f->want_fullscreen = FULLSCREEN_WIDTH;
4097 else if (EQ (new_value, Qfullheight))
4098 f->want_fullscreen = FULLSCREEN_HEIGHT;
4099 else if (EQ (new_value, Qmaximized))
4100 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
4102 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
4103 FRAME_TERMINAL (f)->fullscreen_hook (f);
4107 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
4108 the previous value of that parameter, NEW_VALUE is the new value. */
4110 void
4111 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4113 if (NILP (new_value))
4114 f->extra_line_spacing = 0;
4115 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
4116 f->extra_line_spacing = XFASTINT (new_value);
4117 else if (FLOATP (new_value))
4119 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
4121 if (new_spacing >= 0)
4122 f->extra_line_spacing = new_spacing;
4123 else
4124 signal_error ("Invalid line-spacing", new_value);
4126 else
4127 signal_error ("Invalid line-spacing", new_value);
4128 if (FRAME_VISIBLE_P (f))
4129 redraw_frame (f);
4133 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
4134 the previous value of that parameter, NEW_VALUE is the new value. */
4136 void
4137 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4139 Lisp_Object bgcolor;
4141 if (NILP (new_value))
4142 f->gamma = 0;
4143 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
4144 /* The value 0.4545 is the normal viewing gamma. */
4145 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
4146 else
4147 signal_error ("Invalid screen-gamma", new_value);
4149 /* Apply the new gamma value to the frame background. */
4150 bgcolor = Fassq (Qbackground_color, f->param_alist);
4151 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
4153 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
4154 if (NATNUMP (parm_index)
4155 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
4156 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4157 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
4158 (f, bgcolor, Qnil);
4161 clear_face_cache (true); /* FIXME: Why of all frames? */
4162 fset_redisplay (f);
4166 void
4167 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4169 Lisp_Object font_object;
4170 int fontset = -1;
4171 #ifdef HAVE_X_WINDOWS
4172 Lisp_Object font_param = arg;
4173 #endif
4175 /* Set the frame parameter back to the old value because we may
4176 fail to use ARG as the new parameter value. */
4177 store_frame_param (f, Qfont, oldval);
4179 /* ARG is a fontset name, a font name, a cons of fontset name and a
4180 font object, or a font object. In the last case, this function
4181 never fail. */
4182 if (STRINGP (arg))
4184 fontset = fs_query_fontset (arg, 0);
4185 if (fontset < 0)
4187 font_object = font_open_by_name (f, arg);
4188 if (NILP (font_object))
4189 error ("Font `%s' is not defined", SSDATA (arg));
4190 arg = AREF (font_object, FONT_NAME_INDEX);
4192 else if (fontset > 0)
4194 font_object = font_open_by_name (f, fontset_ascii (fontset));
4195 if (NILP (font_object))
4196 error ("Font `%s' is not defined", SDATA (arg));
4197 arg = AREF (font_object, FONT_NAME_INDEX);
4199 else
4200 error ("The default fontset can't be used for a frame font");
4202 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
4204 /* This is the case that the ASCII font of F's fontset XCAR
4205 (arg) is changed to the font XCDR (arg) by
4206 `set-fontset-font'. */
4207 fontset = fs_query_fontset (XCAR (arg), 0);
4208 if (fontset < 0)
4209 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
4210 font_object = XCDR (arg);
4211 arg = AREF (font_object, FONT_NAME_INDEX);
4212 #ifdef HAVE_X_WINDOWS
4213 font_param = Ffont_get (font_object, QCname);
4214 #endif
4216 else if (FONT_OBJECT_P (arg))
4218 font_object = arg;
4219 #ifdef HAVE_X_WINDOWS
4220 font_param = Ffont_get (font_object, QCname);
4221 #endif
4222 /* This is to store the XLFD font name in the frame parameter for
4223 backward compatibility. We should store the font-object
4224 itself in the future. */
4225 arg = AREF (font_object, FONT_NAME_INDEX);
4226 fontset = FRAME_FONTSET (f);
4227 /* Check if we can use the current fontset. If not, set FONTSET
4228 to -1 to generate a new fontset from FONT-OBJECT. */
4229 if (fontset >= 0)
4231 Lisp_Object ascii_font = fontset_ascii (fontset);
4232 Lisp_Object spec = font_spec_from_name (ascii_font);
4234 /* SPEC might be nil because ASCII_FONT's name doesn't parse
4235 according to stupid XLFD rules, which, for example,
4236 disallow font names that include a dash followed by a
4237 number. So in those cases we simply request x_new_font
4238 below to generate a new fontset. */
4239 if (NILP (spec) || ! font_match_p (spec, font_object))
4240 fontset = -1;
4243 else
4244 signal_error ("Invalid font", arg);
4246 if (! NILP (Fequal (font_object, oldval)))
4247 return;
4249 x_new_font (f, font_object, fontset);
4250 store_frame_param (f, Qfont, arg);
4251 #ifdef HAVE_X_WINDOWS
4252 store_frame_param (f, Qfont_parameter, font_param);
4253 #endif
4254 /* Recalculate toolbar height. */
4255 f->n_tool_bar_rows = 0;
4257 /* Ensure we redraw it. */
4258 clear_current_matrices (f);
4260 /* Attempt to hunt down bug#16028. */
4261 SET_FRAME_GARBAGED (f);
4263 /* This is important if we are called by some Lisp as part of
4264 redisplaying the frame, see redisplay_internal. */
4265 f->fonts_changed = true;
4267 recompute_basic_faces (f);
4269 do_pending_window_change (0);
4271 /* We used to call face-set-after-frame-default here, but it leads to
4272 recursive calls (since that function can set the `default' face's
4273 font which in turns changes the frame's `font' parameter).
4274 Also I don't know what this call is meant to do, but it seems the
4275 wrong way to do it anyway (it does a lot more work than what seems
4276 reasonable in response to a change to `font'). */
4280 void
4281 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4283 if (! NILP (new_value)
4284 && !CONSP (new_value))
4286 char *p0, *p1;
4288 CHECK_STRING (new_value);
4289 p0 = p1 = SSDATA (new_value);
4290 new_value = Qnil;
4291 while (*p0)
4293 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
4294 if (p0 < p1)
4295 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
4296 new_value);
4297 if (*p1)
4299 int c;
4301 while ((c = *++p1) && c_isspace (c));
4303 p0 = p1;
4305 new_value = Fnreverse (new_value);
4308 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
4309 return;
4311 if (FRAME_FONT (f))
4312 free_all_realized_faces (Qnil);
4314 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
4315 if (NILP (new_value))
4317 if (NILP (old_value))
4318 error ("No font backend available");
4319 font_update_drivers (f, old_value);
4320 error ("None of specified font backends are available");
4322 store_frame_param (f, Qfont_backend, new_value);
4324 if (FRAME_FONT (f))
4326 Lisp_Object frame;
4328 XSETFRAME (frame, f);
4329 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
4330 face_change = true;
4331 windows_or_buffers_changed = 18;
4335 void
4336 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4338 int unit = FRAME_COLUMN_WIDTH (f);
4339 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
4340 int new_width;
4342 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4343 ? eabs (XINT (new_value)) : 8);
4345 if (new_width != old_width)
4347 f->left_fringe_width = new_width;
4348 f->fringe_cols /* Round up. */
4349 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
4351 if (FRAME_X_WINDOW (f) != 0)
4352 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
4354 SET_FRAME_GARBAGED (f);
4359 void
4360 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4362 int unit = FRAME_COLUMN_WIDTH (f);
4363 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
4364 int new_width;
4366 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
4367 ? eabs (XINT (new_value)) : 8);
4369 if (new_width != old_width)
4371 f->right_fringe_width = new_width;
4372 f->fringe_cols /* Round up. */
4373 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
4375 if (FRAME_X_WINDOW (f) != 0)
4376 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
4378 SET_FRAME_GARBAGED (f);
4383 void
4384 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4386 CHECK_TYPE_RANGED_INTEGER (int, arg);
4388 if (XINT (arg) == f->border_width)
4389 return;
4391 if (FRAME_X_WINDOW (f) != 0)
4392 error ("Cannot change the border width of a frame");
4394 f->border_width = XINT (arg);
4397 void
4398 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4400 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
4401 CHECK_TYPE_RANGED_INTEGER (int, arg);
4402 int new = max (0, XINT (arg));
4403 if (new != old)
4405 f->right_divider_width = new;
4406 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
4407 adjust_frame_glyphs (f);
4408 SET_FRAME_GARBAGED (f);
4412 void
4413 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4415 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
4416 CHECK_TYPE_RANGED_INTEGER (int, arg);
4417 int new = max (0, XINT (arg));
4418 if (new != old)
4420 f->bottom_divider_width = new;
4421 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
4422 adjust_frame_glyphs (f);
4423 SET_FRAME_GARBAGED (f);
4427 void
4428 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
4430 Lisp_Object frame;
4431 XSETFRAME (frame, f);
4433 if (NILP (value))
4434 Fmake_frame_invisible (frame, Qt);
4435 else if (EQ (value, Qicon))
4436 Ficonify_frame (frame);
4437 else
4438 Fmake_frame_visible (frame);
4441 void
4442 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4444 f->auto_raise = !EQ (Qnil, arg);
4447 void
4448 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4450 f->auto_lower = !EQ (Qnil, arg);
4453 void
4454 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4456 f->no_split = !NILP (arg);
4459 void
4460 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4462 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4463 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
4464 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4465 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
4467 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
4468 = (NILP (arg)
4469 ? vertical_scroll_bar_none
4470 : EQ (Qleft, arg)
4471 ? vertical_scroll_bar_left
4472 : EQ (Qright, arg)
4473 ? vertical_scroll_bar_right
4474 : EQ (Qleft, Vdefault_frame_scroll_bars)
4475 ? vertical_scroll_bar_left
4476 : EQ (Qright, Vdefault_frame_scroll_bars)
4477 ? vertical_scroll_bar_right
4478 : vertical_scroll_bar_none);
4480 /* We set this parameter before creating the X window for the
4481 frame, so we can get the geometry right from the start.
4482 However, if the window hasn't been created yet, we shouldn't
4483 call x_set_window_size. */
4484 if (FRAME_X_WINDOW (f))
4485 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
4487 SET_FRAME_GARBAGED (f);
4491 void
4492 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4494 #if USE_HORIZONTAL_SCROLL_BARS
4495 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
4496 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
4498 f->horizontal_scroll_bars = NILP (arg) ? false : true;
4500 /* We set this parameter before creating the X window for the
4501 frame, so we can get the geometry right from the start.
4502 However, if the window hasn't been created yet, we shouldn't
4503 call x_set_window_size. */
4504 if (FRAME_X_WINDOW (f))
4505 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
4507 SET_FRAME_GARBAGED (f);
4509 #endif
4512 void
4513 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4515 int unit = FRAME_COLUMN_WIDTH (f);
4517 if (NILP (arg))
4519 x_set_scroll_bar_default_width (f);
4521 if (FRAME_X_WINDOW (f))
4522 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4524 SET_FRAME_GARBAGED (f);
4526 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4527 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
4529 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
4530 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
4531 if (FRAME_X_WINDOW (f))
4532 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
4534 SET_FRAME_GARBAGED (f);
4537 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
4538 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
4541 void
4542 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4544 #if USE_HORIZONTAL_SCROLL_BARS
4545 int unit = FRAME_LINE_HEIGHT (f);
4547 if (NILP (arg))
4549 x_set_scroll_bar_default_height (f);
4551 if (FRAME_X_WINDOW (f))
4552 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4554 SET_FRAME_GARBAGED (f);
4556 else if (RANGED_INTEGERP (1, arg, INT_MAX)
4557 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
4559 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
4560 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
4561 if (FRAME_X_WINDOW (f))
4562 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
4564 SET_FRAME_GARBAGED (f);
4567 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
4568 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
4569 #endif
4572 void
4573 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4575 double alpha = 1.0;
4576 double newval[2];
4577 int i;
4578 Lisp_Object item;
4580 for (i = 0; i < 2; i++)
4582 newval[i] = 1.0;
4583 if (CONSP (arg))
4585 item = CAR (arg);
4586 arg = CDR (arg);
4588 else
4589 item = arg;
4591 if (NILP (item))
4592 alpha = - 1.0;
4593 else if (FLOATP (item))
4595 alpha = XFLOAT_DATA (item);
4596 if (! (0 <= alpha && alpha <= 1.0))
4597 args_out_of_range (make_float (0.0), make_float (1.0));
4599 else if (INTEGERP (item))
4601 EMACS_INT ialpha = XINT (item);
4602 if (! (0 <= ialpha && ialpha <= 100))
4603 args_out_of_range (make_number (0), make_number (100));
4604 alpha = ialpha / 100.0;
4606 else
4607 wrong_type_argument (Qnumberp, item);
4608 newval[i] = alpha;
4611 for (i = 0; i < 2; i++)
4612 f->alpha[i] = newval[i];
4614 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
4615 block_input ();
4616 x_set_frame_alpha (f);
4617 unblock_input ();
4618 #endif
4620 return;
4625 * x_set_no_special_glyphs:
4627 * Set frame F's `no-special-glyphs' parameter which, if non-nil,
4628 * suppresses the display of truncation and continuation glyphs
4629 * outside fringes.
4631 void
4632 x_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4634 if (!EQ (new_value, old_value))
4635 FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (new_value);
4639 #ifndef HAVE_NS
4641 /* Non-zero if mouse is grabbed on DPYINFO
4642 and we know the frame where it is. */
4644 bool x_mouse_grabbed (Display_Info *dpyinfo)
4646 return (dpyinfo->grabbed
4647 && dpyinfo->last_mouse_frame
4648 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
4651 /* Re-highlight something with mouse-face properties
4652 on DPYINFO using saved frame and mouse position. */
4654 void
4655 x_redo_mouse_highlight (Display_Info *dpyinfo)
4657 if (dpyinfo->last_mouse_motion_frame
4658 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
4659 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
4660 dpyinfo->last_mouse_motion_x,
4661 dpyinfo->last_mouse_motion_y);
4664 #endif /* HAVE_NS */
4666 /* Subroutines of creating an X frame. */
4668 /* Make sure that Vx_resource_name is set to a reasonable value.
4669 Fix it up, or set it to `emacs' if it is too hopeless. */
4671 void
4672 validate_x_resource_name (void)
4674 ptrdiff_t len = 0;
4675 /* Number of valid characters in the resource name. */
4676 ptrdiff_t good_count = 0;
4677 /* Number of invalid characters in the resource name. */
4678 ptrdiff_t bad_count = 0;
4679 Lisp_Object new;
4680 ptrdiff_t i;
4682 if (!STRINGP (Vx_resource_class))
4683 Vx_resource_class = build_string (EMACS_CLASS);
4685 if (STRINGP (Vx_resource_name))
4687 unsigned char *p = SDATA (Vx_resource_name);
4689 len = SBYTES (Vx_resource_name);
4691 /* Only letters, digits, - and _ are valid in resource names.
4692 Count the valid characters and count the invalid ones. */
4693 for (i = 0; i < len; i++)
4695 int c = p[i];
4696 if (! ((c >= 'a' && c <= 'z')
4697 || (c >= 'A' && c <= 'Z')
4698 || (c >= '0' && c <= '9')
4699 || c == '-' || c == '_'))
4700 bad_count++;
4701 else
4702 good_count++;
4705 else
4706 /* Not a string => completely invalid. */
4707 bad_count = 5, good_count = 0;
4709 /* If name is valid already, return. */
4710 if (bad_count == 0)
4711 return;
4713 /* If name is entirely invalid, or nearly so, or is so implausibly
4714 large that alloca might not work, use `emacs'. */
4715 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
4717 Vx_resource_name = build_string ("emacs");
4718 return;
4721 /* Name is partly valid. Copy it and replace the invalid characters
4722 with underscores. */
4724 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
4726 for (i = 0; i < len; i++)
4728 int c = SREF (new, i);
4729 if (! ((c >= 'a' && c <= 'z')
4730 || (c >= 'A' && c <= 'Z')
4731 || (c >= '0' && c <= '9')
4732 || c == '-' || c == '_'))
4733 SSET (new, i, '_');
4737 /* Get specified attribute from resource database RDB.
4738 See Fx_get_resource below for other parameters. */
4740 static Lisp_Object
4741 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
4743 CHECK_STRING (attribute);
4744 CHECK_STRING (class);
4746 if (!NILP (component))
4747 CHECK_STRING (component);
4748 if (!NILP (subclass))
4749 CHECK_STRING (subclass);
4750 if (NILP (component) != NILP (subclass))
4751 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
4753 validate_x_resource_name ();
4755 /* Allocate space for the components, the dots which separate them,
4756 and the final '\0'. Make them big enough for the worst case. */
4757 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4758 + (STRINGP (component)
4759 ? SBYTES (component) : 0)
4760 + SBYTES (attribute)
4761 + 3);
4763 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4764 + SBYTES (class)
4765 + (STRINGP (subclass)
4766 ? SBYTES (subclass) : 0)
4767 + 3);
4768 USE_SAFE_ALLOCA;
4769 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4770 char *class_key = name_key + name_keysize;
4772 /* Start with emacs.FRAMENAME for the name (the specific one)
4773 and with `Emacs' for the class key (the general one). */
4774 char *nz = lispstpcpy (name_key, Vx_resource_name);
4775 char *cz = lispstpcpy (class_key, Vx_resource_class);
4777 *cz++ = '.';
4778 cz = lispstpcpy (cz, class);
4780 if (!NILP (component))
4782 *cz++ = '.';
4783 lispstpcpy (cz, subclass);
4785 *nz++ = '.';
4786 nz = lispstpcpy (nz, component);
4789 *nz++ = '.';
4790 lispstpcpy (nz, attribute);
4792 char *value = x_get_string_resource (rdb, name_key, class_key);
4793 SAFE_FREE();
4795 if (value && *value)
4796 return build_string (value);
4797 else
4798 return Qnil;
4802 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4803 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4804 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4805 class, where INSTANCE is the name under which Emacs was invoked, or
4806 the name specified by the `-name' or `-rn' command-line arguments.
4808 The optional arguments COMPONENT and SUBCLASS add to the key and the
4809 class, respectively. You must specify both of them or neither.
4810 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4811 and the class is `Emacs.CLASS.SUBCLASS'. */)
4812 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4813 Lisp_Object subclass)
4815 check_window_system (NULL);
4817 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4818 attribute, class, component, subclass);
4821 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4823 Lisp_Object
4824 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4825 Lisp_Object class, Lisp_Object component,
4826 Lisp_Object subclass)
4828 return xrdb_get_resource (dpyinfo->xrdb,
4829 attribute, class, component, subclass);
4832 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
4833 /* Used when C code wants a resource value. */
4834 /* Called from oldXMenu/Create.c. */
4835 char *
4836 x_get_resource_string (const char *attribute, const char *class)
4838 char *result;
4839 struct frame *sf = SELECTED_FRAME ();
4840 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4841 USE_SAFE_ALLOCA;
4843 /* Allocate space for the components, the dots which separate them,
4844 and the final '\0'. */
4845 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4846 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4847 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4848 char *class_key = name_key + name_keysize;
4850 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4851 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4853 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4854 name_key, class_key);
4855 SAFE_FREE ();
4856 return result;
4858 #endif
4860 /* Return the value of parameter PARAM.
4862 First search ALIST, then Vdefault_frame_alist, then the X defaults
4863 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4865 Convert the resource to the type specified by desired_type.
4867 If no default is specified, return Qunbound. If you call
4868 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4869 and don't let it get stored in any Lisp-visible variables! */
4871 Lisp_Object
4872 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4873 const char *attribute, const char *class, enum resource_types type)
4875 Lisp_Object tem;
4877 tem = Fassq (param, alist);
4879 if (!NILP (tem))
4881 /* If we find this parm in ALIST, clear it out
4882 so that it won't be "left over" at the end. */
4883 Lisp_Object tail;
4884 XSETCAR (tem, Qnil);
4885 /* In case the parameter appears more than once in the alist,
4886 clear it out. */
4887 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4888 if (CONSP (XCAR (tail))
4889 && EQ (XCAR (XCAR (tail)), param))
4890 XSETCAR (XCAR (tail), Qnil);
4892 else
4893 tem = Fassq (param, Vdefault_frame_alist);
4895 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4896 look in the X resources. */
4897 if (EQ (tem, Qnil))
4899 if (attribute && dpyinfo)
4901 AUTO_STRING (at, attribute);
4902 AUTO_STRING (cl, class);
4903 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4905 if (NILP (tem))
4906 return Qunbound;
4908 switch (type)
4910 case RES_TYPE_NUMBER:
4911 return make_number (atoi (SSDATA (tem)));
4913 case RES_TYPE_BOOLEAN_NUMBER:
4914 if (!strcmp (SSDATA (tem), "on")
4915 || !strcmp (SSDATA (tem), "true"))
4916 return make_number (1);
4917 return make_number (atoi (SSDATA (tem)));
4918 break;
4920 case RES_TYPE_FLOAT:
4921 return make_float (atof (SSDATA (tem)));
4923 case RES_TYPE_BOOLEAN:
4924 tem = Fdowncase (tem);
4925 if (!strcmp (SSDATA (tem), "on")
4926 #ifdef HAVE_NS
4927 || !strcmp (SSDATA (tem), "yes")
4928 #endif
4929 || !strcmp (SSDATA (tem), "true"))
4930 return Qt;
4931 else
4932 return Qnil;
4934 case RES_TYPE_STRING:
4935 return tem;
4937 case RES_TYPE_SYMBOL:
4938 /* As a special case, we map the values `true' and `on'
4939 to Qt, and `false' and `off' to Qnil. */
4941 Lisp_Object lower;
4942 lower = Fdowncase (tem);
4943 if (!strcmp (SSDATA (lower), "on")
4944 #ifdef HAVE_NS
4945 || !strcmp (SSDATA (lower), "yes")
4946 #endif
4947 || !strcmp (SSDATA (lower), "true"))
4948 return Qt;
4949 else if (!strcmp (SSDATA (lower), "off")
4950 #ifdef HAVE_NS
4951 || !strcmp (SSDATA (lower), "no")
4952 #endif
4953 || !strcmp (SSDATA (lower), "false"))
4954 return Qnil;
4955 else
4956 return Fintern (tem, Qnil);
4959 default:
4960 emacs_abort ();
4963 else
4964 return Qunbound;
4966 return Fcdr (tem);
4969 static Lisp_Object
4970 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
4971 const char *attribute, const char *class,
4972 enum resource_types type)
4974 return x_get_arg (FRAME_DISPLAY_INFO (f),
4975 alist, param, attribute, class, type);
4978 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
4980 Lisp_Object
4981 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
4982 Lisp_Object param,
4983 const char *attribute, const char *class,
4984 enum resource_types type)
4986 Lisp_Object value;
4988 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
4989 attribute, class, type);
4990 if (! NILP (value) && ! EQ (value, Qunbound))
4991 store_frame_param (f, param, value);
4993 return value;
4997 /* Record in frame F the specified or default value according to ALIST
4998 of the parameter named PROP (a Lisp symbol).
4999 If no value is specified for PROP, look for an X default for XPROP
5000 on the frame named NAME.
5001 If that is not found either, use the value DEFLT. */
5003 Lisp_Object
5004 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
5005 Lisp_Object deflt, const char *xprop, const char *xclass,
5006 enum resource_types type)
5008 Lisp_Object tem;
5010 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
5011 if (EQ (tem, Qunbound))
5012 tem = deflt;
5013 AUTO_FRAME_ARG (arg, prop, tem);
5014 x_set_frame_parameters (f, arg);
5015 return tem;
5019 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
5022 * XParseGeometry parses strings of the form
5023 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5024 * width, height, xoffset, and yoffset are unsigned integers.
5025 * Example: "=80x24+300-49"
5026 * The equal sign is optional.
5027 * It returns a bitmask that indicates which of the four values
5028 * were actually found in the string. For each value found,
5029 * the corresponding argument is updated; for each value
5030 * not found, the corresponding argument is left unchanged.
5033 static int
5034 XParseGeometry (char *string,
5035 int *x, int *y,
5036 unsigned int *width, unsigned int *height)
5038 int mask = NoValue;
5039 char *strind;
5040 unsigned long tempWidth UNINIT, tempHeight UNINIT;
5041 long int tempX UNINIT, tempY UNINIT;
5042 char *nextCharacter;
5044 if (string == NULL || *string == '\0')
5045 return mask;
5046 if (*string == '=')
5047 string++; /* ignore possible '=' at beg of geometry spec */
5049 strind = string;
5050 if (*strind != '+' && *strind != '-' && *strind != 'x')
5052 tempWidth = strtoul (strind, &nextCharacter, 10);
5053 if (strind == nextCharacter)
5054 return 0;
5055 strind = nextCharacter;
5056 mask |= WidthValue;
5059 if (*strind == 'x' || *strind == 'X')
5061 strind++;
5062 tempHeight = strtoul (strind, &nextCharacter, 10);
5063 if (strind == nextCharacter)
5064 return 0;
5065 strind = nextCharacter;
5066 mask |= HeightValue;
5069 if (*strind == '+' || *strind == '-')
5071 if (*strind == '-')
5072 mask |= XNegative;
5073 tempX = strtol (strind, &nextCharacter, 10);
5074 if (strind == nextCharacter)
5075 return 0;
5076 strind = nextCharacter;
5077 mask |= XValue;
5078 if (*strind == '+' || *strind == '-')
5080 if (*strind == '-')
5081 mask |= YNegative;
5082 tempY = strtol (strind, &nextCharacter, 10);
5083 if (strind == nextCharacter)
5084 return 0;
5085 strind = nextCharacter;
5086 mask |= YValue;
5090 /* If strind isn't at the end of the string then it's an invalid
5091 geometry specification. */
5093 if (*strind != '\0')
5094 return 0;
5096 if (mask & XValue)
5097 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
5098 if (mask & YValue)
5099 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
5100 if (mask & WidthValue)
5101 *width = min (tempWidth, UINT_MAX);
5102 if (mask & HeightValue)
5103 *height = min (tempHeight, UINT_MAX);
5104 return mask;
5107 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
5110 /* NS used to define x-parse-geometry in ns-win.el, but that confused
5111 make-docfile: the documentation string in ns-win.el was used for
5112 x-parse-geometry even in non-NS builds.
5114 With two definitions of x-parse-geometry in this file, various
5115 things still get confused (eg M-x apropos documentation), so that
5116 it is best if the two definitions just share the same doc-string.
5118 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
5119 doc: /* Parse a display geometry string STRING.
5120 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
5121 The properties returned may include `top', `left', `height', and `width'.
5122 For X, the value of `left' or `top' may be an integer,
5123 or a list (+ N) meaning N pixels relative to top/left corner,
5124 or a list (- N) meaning -N pixels relative to bottom/right corner.
5125 On Nextstep, this just calls `ns-parse-geometry'. */)
5126 (Lisp_Object string)
5128 int geometry, x, y;
5129 unsigned int width, height;
5130 Lisp_Object result;
5132 CHECK_STRING (string);
5134 #ifdef HAVE_NS
5135 if (strchr (SSDATA (string), ' ') != NULL)
5136 return call1 (Qns_parse_geometry, string);
5137 #endif
5138 geometry = XParseGeometry (SSDATA (string),
5139 &x, &y, &width, &height);
5140 result = Qnil;
5141 if (geometry & XValue)
5143 Lisp_Object element;
5145 if (x >= 0 && (geometry & XNegative))
5146 element = list3 (Qleft, Qminus, make_number (-x));
5147 else if (x < 0 && ! (geometry & XNegative))
5148 element = list3 (Qleft, Qplus, make_number (x));
5149 else
5150 element = Fcons (Qleft, make_number (x));
5151 result = Fcons (element, result);
5154 if (geometry & YValue)
5156 Lisp_Object element;
5158 if (y >= 0 && (geometry & YNegative))
5159 element = list3 (Qtop, Qminus, make_number (-y));
5160 else if (y < 0 && ! (geometry & YNegative))
5161 element = list3 (Qtop, Qplus, make_number (y));
5162 else
5163 element = Fcons (Qtop, make_number (y));
5164 result = Fcons (element, result);
5167 if (geometry & WidthValue)
5168 result = Fcons (Fcons (Qwidth, make_number (width)), result);
5169 if (geometry & HeightValue)
5170 result = Fcons (Fcons (Qheight, make_number (height)), result);
5172 return result;
5176 /* Calculate the desired size and position of frame F.
5177 Return the flags saying which aspects were specified.
5179 Also set the win_gravity and size_hint_flags of F.
5181 Adjust height for toolbar if TOOLBAR_P is 1.
5183 This function does not make the coordinates positive. */
5185 #define DEFAULT_ROWS 36
5186 #define DEFAULT_COLS 80
5188 long
5189 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x_width, int *x_height)
5191 Lisp_Object height, width, user_size, top, left, user_position;
5192 long window_prompting = 0;
5193 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
5194 int parent_done = -1, outer_done = -1;
5196 /* Default values if we fall through.
5197 Actually, if that happens we should get
5198 window manager prompting. */
5199 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
5200 SET_FRAME_COLS (f, DEFAULT_COLS);
5201 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
5202 SET_FRAME_LINES (f, DEFAULT_ROWS);
5204 /* Window managers expect that if program-specified
5205 positions are not (0,0), they're intentional, not defaults. */
5206 f->top_pos = 0;
5207 f->left_pos = 0;
5209 /* Calculate a tool bar height so that the user gets a text display
5210 area of the size he specified with -g or via .Xdefaults. Later
5211 changes of the tool bar height don't change the frame size. This
5212 is done so that users can create tall Emacs frames without having
5213 to guess how tall the tool bar will get. */
5214 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
5216 if (frame_default_tool_bar_height)
5217 FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
5218 else
5220 int margin, relief;
5222 relief = (tool_bar_button_relief >= 0
5223 ? tool_bar_button_relief
5224 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
5226 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
5227 margin = XFASTINT (Vtool_bar_button_margin);
5228 else if (CONSP (Vtool_bar_button_margin)
5229 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
5230 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
5231 else
5232 margin = 0;
5234 FRAME_TOOL_BAR_HEIGHT (f)
5235 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
5239 /* Ensure that earlier new_width and new_height settings won't
5240 override what we specify below. */
5241 f->new_width = f->new_height = 0;
5243 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
5244 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
5245 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
5247 if (!EQ (width, Qunbound))
5249 if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
5251 CHECK_NUMBER (XCDR (width));
5252 if ((XINT (XCDR (width)) < 0 || XINT (XCDR (width)) > INT_MAX))
5253 xsignal1 (Qargs_out_of_range, XCDR (width));
5255 SET_FRAME_WIDTH (f, XINT (XCDR (width)));
5256 f->inhibit_horizontal_resize = true;
5257 *x_width = XINT (XCDR (width));
5259 else if (FLOATP (width))
5261 double d_width = XFLOAT_DATA (width);
5263 if (d_width < 0.0 || d_width > 1.0)
5264 xsignal1 (Qargs_out_of_range, width);
5265 else
5267 int new_width = frame_float (f, width, FRAME_FLOAT_WIDTH,
5268 &parent_done, &outer_done, -1);
5270 if (new_width > -1)
5271 SET_FRAME_WIDTH (f, new_width);
5274 else
5276 CHECK_NUMBER (width);
5277 if ((XINT (width) < 0 || XINT (width) > INT_MAX))
5278 xsignal1 (Qargs_out_of_range, width);
5280 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
5284 if (!EQ (height, Qunbound))
5286 if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
5288 CHECK_NUMBER (XCDR (height));
5289 if ((XINT (XCDR (height)) < 0 || XINT (XCDR (height)) > INT_MAX))
5290 xsignal1 (Qargs_out_of_range, XCDR (height));
5292 SET_FRAME_HEIGHT (f, XINT (XCDR (height)));
5293 f->inhibit_vertical_resize = true;
5294 *x_height = XINT (XCDR (height));
5296 else if (FLOATP (height))
5298 double d_height = XFLOAT_DATA (height);
5300 if (d_height < 0.0 || d_height > 1.0)
5301 xsignal1 (Qargs_out_of_range, height);
5302 else
5304 int new_height = frame_float (f, height, FRAME_FLOAT_HEIGHT,
5305 &parent_done, &outer_done, -1);
5307 if (new_height > -1)
5308 SET_FRAME_HEIGHT (f, new_height);
5311 else
5313 CHECK_NUMBER (height);
5314 if ((XINT (height) < 0) || (XINT (height) > INT_MAX))
5315 xsignal1 (Qargs_out_of_range, height);
5317 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
5321 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
5322 if (!NILP (user_size) && !EQ (user_size, Qunbound))
5323 window_prompting |= USSize;
5324 else
5325 window_prompting |= PSize;
5328 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
5329 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
5330 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
5331 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
5333 if (EQ (top, Qminus))
5335 f->top_pos = 0;
5336 window_prompting |= YNegative;
5338 else if (CONSP (top) && EQ (XCAR (top), Qminus)
5339 && CONSP (XCDR (top))
5340 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
5342 f->top_pos = - XINT (XCAR (XCDR (top)));
5343 window_prompting |= YNegative;
5345 else if (CONSP (top) && EQ (XCAR (top), Qplus)
5346 && CONSP (XCDR (top))
5347 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
5349 f->top_pos = XINT (XCAR (XCDR (top)));
5351 else if (FLOATP (top))
5352 f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
5353 &outer_done, 0);
5354 else if (EQ (top, Qunbound))
5355 f->top_pos = 0;
5356 else
5358 CHECK_TYPE_RANGED_INTEGER (int, top);
5359 f->top_pos = XINT (top);
5360 if (f->top_pos < 0)
5361 window_prompting |= YNegative;
5364 if (EQ (left, Qminus))
5366 f->left_pos = 0;
5367 window_prompting |= XNegative;
5369 else if (CONSP (left) && EQ (XCAR (left), Qminus)
5370 && CONSP (XCDR (left))
5371 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
5373 f->left_pos = - XINT (XCAR (XCDR (left)));
5374 window_prompting |= XNegative;
5376 else if (CONSP (left) && EQ (XCAR (left), Qplus)
5377 && CONSP (XCDR (left))
5378 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
5380 f->left_pos = XINT (XCAR (XCDR (left)));
5382 else if (FLOATP (left))
5383 f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
5384 &outer_done, 0);
5385 else if (EQ (left, Qunbound))
5386 f->left_pos = 0;
5387 else
5389 CHECK_TYPE_RANGED_INTEGER (int, left);
5390 f->left_pos = XINT (left);
5391 if (f->left_pos < 0)
5392 window_prompting |= XNegative;
5395 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
5396 window_prompting |= USPosition;
5397 else
5398 window_prompting |= PPosition;
5401 if (window_prompting & XNegative)
5403 if (window_prompting & YNegative)
5404 f->win_gravity = SouthEastGravity;
5405 else
5406 f->win_gravity = NorthEastGravity;
5408 else
5410 if (window_prompting & YNegative)
5411 f->win_gravity = SouthWestGravity;
5412 else
5413 f->win_gravity = NorthWestGravity;
5416 f->size_hint_flags = window_prompting;
5418 return window_prompting;
5423 #endif /* HAVE_WINDOW_SYSTEM */
5425 void
5426 frame_make_pointer_invisible (struct frame *f)
5428 if (! NILP (Vmake_pointer_invisible))
5430 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
5431 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5433 f->mouse_moved = 0;
5434 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
5435 f->pointer_invisible = 1;
5440 void
5441 frame_make_pointer_visible (struct frame *f)
5443 /* We don't check Vmake_pointer_invisible here in case the
5444 pointer was invisible when Vmake_pointer_invisible was set to nil. */
5445 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
5446 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
5448 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
5449 f->pointer_invisible = 0;
5453 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
5454 Sframe_pointer_visible_p, 0, 1, 0,
5455 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
5456 Otherwise it returns nil. FRAME omitted or nil means the
5457 selected frame. This is useful when `make-pointer-invisible' is set. */)
5458 (Lisp_Object frame)
5460 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
5465 /***********************************************************************
5466 Multimonitor data
5467 ***********************************************************************/
5469 #ifdef HAVE_WINDOW_SYSTEM
5471 # if (defined HAVE_NS \
5472 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
5473 void
5474 free_monitors (struct MonitorInfo *monitors, int n_monitors)
5476 int i;
5477 for (i = 0; i < n_monitors; ++i)
5478 xfree (monitors[i].name);
5479 xfree (monitors);
5481 # endif
5483 Lisp_Object
5484 make_monitor_attribute_list (struct MonitorInfo *monitors,
5485 int n_monitors,
5486 int primary_monitor,
5487 Lisp_Object monitor_frames,
5488 const char *source)
5490 Lisp_Object attributes_list = Qnil;
5491 Lisp_Object primary_monitor_attributes = Qnil;
5492 int i;
5494 for (i = 0; i < n_monitors; ++i)
5496 Lisp_Object geometry, workarea, attributes = Qnil;
5497 struct MonitorInfo *mi = &monitors[i];
5499 if (mi->geom.width == 0) continue;
5501 workarea = list4i (mi->work.x, mi->work.y,
5502 mi->work.width, mi->work.height);
5503 geometry = list4i (mi->geom.x, mi->geom.y,
5504 mi->geom.width, mi->geom.height);
5505 attributes = Fcons (Fcons (Qsource, build_string (source)),
5506 attributes);
5507 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
5508 attributes);
5509 attributes = Fcons (Fcons (Qmm_size,
5510 list2i (mi->mm_width, mi->mm_height)),
5511 attributes);
5512 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5513 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5514 if (mi->name)
5515 attributes = Fcons (Fcons (Qname, make_string (mi->name,
5516 strlen (mi->name))),
5517 attributes);
5519 if (i == primary_monitor)
5520 primary_monitor_attributes = attributes;
5521 else
5522 attributes_list = Fcons (attributes, attributes_list);
5525 if (!NILP (primary_monitor_attributes))
5526 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
5527 return attributes_list;
5530 #endif /* HAVE_WINDOW_SYSTEM */
5533 /***********************************************************************
5534 Initialization
5535 ***********************************************************************/
5537 void
5538 syms_of_frame (void)
5540 DEFSYM (Qframep, "framep");
5541 DEFSYM (Qframe_live_p, "frame-live-p");
5542 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
5543 DEFSYM (Qdisplay_monitor_attributes_list, "display-monitor-attributes-list");
5544 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
5545 DEFSYM (Qexplicit_name, "explicit-name");
5546 DEFSYM (Qheight, "height");
5547 DEFSYM (Qicon, "icon");
5548 DEFSYM (Qminibuffer, "minibuffer");
5549 DEFSYM (Qundecorated, "undecorated");
5550 DEFSYM (Qno_special_glyphs, "no-special-glyphs");
5551 DEFSYM (Qparent_frame, "parent-frame");
5552 DEFSYM (Qskip_taskbar, "skip-taskbar");
5553 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
5554 DEFSYM (Qno_accept_focus, "no-accept-focus");
5555 DEFSYM (Qz_group, "z-group");
5556 DEFSYM (Qoverride_redirect, "override-redirect");
5557 DEFSYM (Qdelete_before, "delete-before");
5558 DEFSYM (Qmodeline, "modeline");
5559 DEFSYM (Qonly, "only");
5560 DEFSYM (Qnone, "none");
5561 DEFSYM (Qwidth, "width");
5562 DEFSYM (Qtext_pixels, "text-pixels");
5563 DEFSYM (Qgeometry, "geometry");
5564 DEFSYM (Qicon_left, "icon-left");
5565 DEFSYM (Qicon_top, "icon-top");
5566 DEFSYM (Qtooltip, "tooltip");
5567 DEFSYM (Quser_position, "user-position");
5568 DEFSYM (Quser_size, "user-size");
5569 DEFSYM (Qwindow_id, "window-id");
5570 #ifdef HAVE_X_WINDOWS
5571 DEFSYM (Qouter_window_id, "outer-window-id");
5572 #endif
5573 DEFSYM (Qparent_id, "parent-id");
5574 DEFSYM (Qx, "x");
5575 DEFSYM (Qw32, "w32");
5576 DEFSYM (Qpc, "pc");
5577 DEFSYM (Qns, "ns");
5578 DEFSYM (Qvisible, "visible");
5579 DEFSYM (Qbuffer_predicate, "buffer-predicate");
5580 DEFSYM (Qbuffer_list, "buffer-list");
5581 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
5582 DEFSYM (Qdisplay_type, "display-type");
5583 DEFSYM (Qbackground_mode, "background-mode");
5584 DEFSYM (Qnoelisp, "noelisp");
5585 DEFSYM (Qtty_color_mode, "tty-color-mode");
5586 DEFSYM (Qtty, "tty");
5587 DEFSYM (Qtty_type, "tty-type");
5589 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
5591 DEFSYM (Qfullwidth, "fullwidth");
5592 DEFSYM (Qfullheight, "fullheight");
5593 DEFSYM (Qfullboth, "fullboth");
5594 DEFSYM (Qmaximized, "maximized");
5595 DEFSYM (Qx_resource_name, "x-resource-name");
5596 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
5598 DEFSYM (Qworkarea, "workarea");
5599 DEFSYM (Qmm_size, "mm-size");
5600 DEFSYM (Qframes, "frames");
5601 DEFSYM (Qsource, "source");
5603 DEFSYM (Qframe_edges, "frame-edges");
5604 DEFSYM (Qouter_edges, "outer-edges");
5605 DEFSYM (Qouter_position, "outer-position");
5606 DEFSYM (Qouter_size, "outer-size");
5607 DEFSYM (Qnative_edges, "native-edges");
5608 DEFSYM (Qinner_edges, "inner-edges");
5609 DEFSYM (Qexternal_border_size, "external-border-size");
5610 DEFSYM (Qtitle_bar_size, "title-bar-size");
5611 DEFSYM (Qmenu_bar_external, "menu-bar-external");
5612 DEFSYM (Qmenu_bar_size, "menu-bar-size");
5613 DEFSYM (Qtool_bar_external, "tool-bar-external");
5614 DEFSYM (Qtool_bar_size, "tool-bar-size");
5615 /* The following are used for frame_size_history. */
5616 DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
5617 DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
5618 DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
5619 DEFSYM (Qx_set_frame_parameters, "x-set-frame-parameters");
5620 DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
5621 DEFSYM (Qset_frame_size, "set-frame-size");
5622 DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
5623 DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
5624 DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
5625 DEFSYM (Qxg_frame_resized, "xg-frame-resized");
5626 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
5627 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
5628 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
5629 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
5630 DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
5631 DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
5632 DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
5633 DEFSYM (Qx_net_wm_state, "x-net-wm-state");
5634 DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
5635 DEFSYM (Qtb_size_cb, "tb-size-cb");
5636 DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
5637 DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
5638 DEFSYM (Qx_set_menu_bar_lines, "x-set-menu-bar-lines");
5639 DEFSYM (Qchange_frame_size, "change-frame-size");
5640 DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
5641 DEFSYM (Qset_window_configuration, "set-window-configuration");
5642 DEFSYM (Qx_create_frame_1, "x-create-frame-1");
5643 DEFSYM (Qx_create_frame_2, "x-create-frame-2");
5644 DEFSYM (Qterminal_frame, "terminal-frame");
5646 #ifdef HAVE_NS
5647 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
5648 #endif
5650 DEFSYM (Qalpha, "alpha");
5651 DEFSYM (Qauto_lower, "auto-lower");
5652 DEFSYM (Qauto_raise, "auto-raise");
5653 DEFSYM (Qborder_color, "border-color");
5654 DEFSYM (Qborder_width, "border-width");
5655 DEFSYM (Qouter_border_width, "outer-border-width");
5656 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
5657 DEFSYM (Qcursor_color, "cursor-color");
5658 DEFSYM (Qcursor_type, "cursor-type");
5659 DEFSYM (Qfont_backend, "font-backend");
5660 DEFSYM (Qfullscreen, "fullscreen");
5661 DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
5662 DEFSYM (Qicon_name, "icon-name");
5663 DEFSYM (Qicon_type, "icon-type");
5664 DEFSYM (Qinternal_border_width, "internal-border-width");
5665 DEFSYM (Qleft_fringe, "left-fringe");
5666 DEFSYM (Qline_spacing, "line-spacing");
5667 DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
5668 DEFSYM (Qupdate_frame_menubar, "update-frame-menubar");
5669 DEFSYM (Qfree_frame_menubar_1, "free-frame-menubar-1");
5670 DEFSYM (Qfree_frame_menubar_2, "free-frame-menubar-2");
5671 DEFSYM (Qmouse_color, "mouse-color");
5672 DEFSYM (Qname, "name");
5673 DEFSYM (Qright_divider_width, "right-divider-width");
5674 DEFSYM (Qright_fringe, "right-fringe");
5675 DEFSYM (Qscreen_gamma, "screen-gamma");
5676 DEFSYM (Qscroll_bar_background, "scroll-bar-background");
5677 DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
5678 DEFSYM (Qscroll_bar_height, "scroll-bar-height");
5679 DEFSYM (Qscroll_bar_width, "scroll-bar-width");
5680 DEFSYM (Qsticky, "sticky");
5681 DEFSYM (Qtitle, "title");
5682 DEFSYM (Qtool_bar_lines, "tool-bar-lines");
5683 DEFSYM (Qtool_bar_position, "tool-bar-position");
5684 DEFSYM (Qunsplittable, "unsplittable");
5685 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
5686 DEFSYM (Qvisibility, "visibility");
5687 DEFSYM (Qwait_for_wm, "wait-for-wm");
5688 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5689 DEFSYM (Qno_other_frame, "no-other-frame");
5690 DEFSYM (Qbelow, "below");
5691 DEFSYM (Qabove_suspended, "above-suspended");
5692 DEFSYM (Qmin_width, "min-width");
5693 DEFSYM (Qmin_height, "min-height");
5694 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
5695 DEFSYM (Qkeep_ratio, "keep-ratio");
5696 DEFSYM (Qwidth_only, "width-only");
5697 DEFSYM (Qheight_only, "height-only");
5698 DEFSYM (Qleft_only, "left-only");
5699 DEFSYM (Qtop_only, "top-only");
5702 int i;
5704 for (i = 0; i < ARRAYELTS (frame_parms); i++)
5706 Lisp_Object v = (frame_parms[i].sym < 0
5707 ? intern_c_string (frame_parms[i].name)
5708 : builtin_lisp_symbol (frame_parms[i].sym));
5709 Fput (v, Qx_frame_parameter, make_number (i));
5713 #ifdef HAVE_WINDOW_SYSTEM
5714 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
5715 doc: /* The name Emacs uses to look up X resources.
5716 `x-get-resource' uses this as the first component of the instance name
5717 when requesting resource values.
5718 Emacs initially sets `x-resource-name' to the name under which Emacs
5719 was invoked, or to the value specified with the `-name' or `-rn'
5720 switches, if present.
5722 It may be useful to bind this variable locally around a call
5723 to `x-get-resource'. See also the variable `x-resource-class'. */);
5724 Vx_resource_name = Qnil;
5726 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
5727 doc: /* The class Emacs uses to look up X resources.
5728 `x-get-resource' uses this as the first component of the instance class
5729 when requesting resource values.
5731 Emacs initially sets `x-resource-class' to "Emacs".
5733 Setting this variable permanently is not a reasonable thing to do,
5734 but binding this variable locally around a call to `x-get-resource'
5735 is a reasonable practice. See also the variable `x-resource-name'. */);
5736 Vx_resource_class = build_string (EMACS_CLASS);
5738 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
5739 doc: /* The lower limit of the frame opacity (alpha transparency).
5740 The value should range from 0 (invisible) to 100 (completely opaque).
5741 You can also use a floating number between 0.0 and 1.0. */);
5742 Vframe_alpha_lower_limit = make_number (20);
5743 #endif
5745 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
5746 doc: /* Alist of default values for frame creation.
5747 These may be set in your init file, like this:
5748 (setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
5749 These override values given in window system configuration data,
5750 including X Windows' defaults database.
5751 For values specific to the first Emacs frame, see `initial-frame-alist'.
5752 For window-system specific values, see `window-system-default-frame-alist'.
5753 For values specific to the separate minibuffer frame, see
5754 `minibuffer-frame-alist'.
5755 The `menu-bar-lines' element of the list controls whether new frames
5756 have menu bars; `menu-bar-mode' works by altering this element.
5757 Setting this variable does not affect existing frames, only new ones. */);
5758 Vdefault_frame_alist = Qnil;
5760 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
5761 doc: /* Default position of vertical scroll bars on this window-system. */);
5762 #ifdef HAVE_WINDOW_SYSTEM
5763 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
5764 /* MS-Windows, macOS, and GTK have scroll bars on the right by
5765 default. */
5766 Vdefault_frame_scroll_bars = Qright;
5767 #else
5768 Vdefault_frame_scroll_bars = Qleft;
5769 #endif
5770 #else
5771 Vdefault_frame_scroll_bars = Qnil;
5772 #endif
5774 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
5775 scroll_bar_adjust_thumb_portion_p,
5776 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
5777 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
5778 even if the end of the buffer is shown (i.e. overscrolling).
5779 Set to nil if you want the thumb to be at the bottom when the end of the buffer
5780 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
5781 is visible. In this case you can not overscroll. */);
5782 scroll_bar_adjust_thumb_portion_p = 1;
5784 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
5785 doc: /* The initial frame-object, which represents Emacs's stdout. */);
5787 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
5788 doc: /* If non-nil, function to transform normal value of `mouse-position'.
5789 `mouse-position' and `mouse-pixel-position' call this function, passing their
5790 usual return value as argument, and return whatever this function returns.
5791 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
5792 which need to do mouse handling at the Lisp level. */);
5793 Vmouse_position_function = Qnil;
5795 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
5796 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
5797 If the value is an integer, highlighting is only shown after moving the
5798 mouse, while keyboard input turns off the highlight even when the mouse
5799 is over the clickable text. However, the mouse shape still indicates
5800 when the mouse is over clickable text. */);
5801 Vmouse_highlight = Qt;
5803 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
5804 doc: /* If non-nil, make pointer invisible while typing.
5805 The pointer becomes visible again when the mouse is moved. */);
5806 Vmake_pointer_invisible = Qt;
5808 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
5809 doc: /* Normal hook run when a frame gains input focus.
5810 The frame gaining focus is selected at the time this hook is run. */);
5811 Vfocus_in_hook = Qnil;
5813 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
5814 doc: /* Normal hook run when all frames lost input focus. */);
5815 Vfocus_out_hook = Qnil;
5817 DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
5818 doc: /* Functions run after a frame was moved.
5819 The functions are run with one arg, the frame that moved. */);
5820 Vmove_frame_functions = Qnil;
5822 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
5823 doc: /* Functions run before deleting a frame.
5824 The functions are run with one arg, the frame to be deleted.
5825 See `delete-frame'.
5827 Note that functions in this list may be called just before the frame is
5828 actually deleted, or some time later (or even both when an earlier function
5829 in `delete-frame-functions' (indirectly) calls `delete-frame'
5830 recursively). */);
5831 Vdelete_frame_functions = Qnil;
5832 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
5834 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
5835 doc: /* Non-nil if Menu-Bar mode is enabled.
5836 See the command `menu-bar-mode' for a description of this minor mode.
5837 Setting this variable directly does not take effect;
5838 either customize it (see the info node `Easy Customization')
5839 or call the function `menu-bar-mode'. */);
5840 Vmenu_bar_mode = Qt;
5842 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
5843 doc: /* Non-nil if Tool-Bar mode is enabled.
5844 See the command `tool-bar-mode' for a description of this minor mode.
5845 Setting this variable directly does not take effect;
5846 either customize it (see the info node `Easy Customization')
5847 or call the function `tool-bar-mode'. */);
5848 #ifdef HAVE_WINDOW_SYSTEM
5849 Vtool_bar_mode = Qt;
5850 #else
5851 Vtool_bar_mode = Qnil;
5852 #endif
5854 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
5855 doc: /* Minibufferless frames use this frame's minibuffer.
5856 Emacs cannot create minibufferless frames unless this is set to an
5857 appropriate surrogate.
5859 Emacs consults this variable only when creating minibufferless
5860 frames; once the frame is created, it sticks with its assigned
5861 minibuffer, no matter what this variable is set to. This means that
5862 this variable doesn't necessarily say anything meaningful about the
5863 current set of frames, or where the minibuffer is currently being
5864 displayed.
5866 This variable is local to the current terminal and cannot be buffer-local. */);
5868 DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
5869 doc: /* Non-nil if window system changes focus when you move the mouse.
5870 You should set this variable to tell Emacs how your window manager
5871 handles focus, since there is no way in general for Emacs to find out
5872 automatically.
5874 There are three meaningful values:
5876 - The default nil should be used when your window manager follows a
5877 "click-to-focus" policy where you have to click the mouse inside of a
5878 frame in order for that frame to get focus.
5880 - The value t should be used when your window manager has the focus
5881 automatically follow the position of the mouse pointer but a window
5882 that gains focus is not raised automatically.
5884 - The value `auto-raise' should be used when your window manager has the
5885 focus automatically follow the position of the mouse pointer and a
5886 window that gains focus is raised automatically.
5888 If this option is non-nil, Emacs moves the mouse pointer to the frame
5889 selected by `select-frame-set-input-focus'. This function is used by a
5890 number of commands like, for example, `other-frame' and `pop-to-buffer'.
5891 If this option is nil and your focus follows mouse window manager does
5892 not autonomously move the mouse pointer to the newly selected frame, the
5893 previously selected window manager window might get reselected instead
5894 immediately.
5896 The distinction between the values t and `auto-raise' is not needed for
5897 "normal" frames because the window manager takes care of raising them.
5898 Setting this to `auto-raise' will, however, override the standard
5899 behavior of a window manager that does not automatically raise the frame
5900 that gets focus. Setting this to `auto-raise' is also necessary to
5901 automatically raise child frames which are usually left alone by the
5902 window manager.
5904 Note that this option does not distinguish "sloppy" focus (where the
5905 frame that previously had focus retains focus as long as the mouse
5906 pointer does not move into another window manager window) from "strict"
5907 focus (where a frame immediately loses focus when it's left by the mouse
5908 pointer).
5910 In order to extend a "focus follows mouse" policy to individual Emacs
5911 windows, customize the variable `mouse-autoselect-window'. */);
5912 focus_follows_mouse = Qnil;
5914 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5915 doc: /* Non-nil means resize frames pixelwise.
5916 If this option is nil, resizing a frame rounds its sizes to the frame's
5917 current values of `frame-char-height' and `frame-char-width'. If this
5918 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5919 by one pixel.
5921 With some window managers you may have to set this to non-nil in order
5922 to set the size of a frame in pixels, to maximize frames or to make them
5923 fullscreen. To resize your initial frame pixelwise, set this option to
5924 a non-nil value in your init file. */);
5925 frame_resize_pixelwise = 0;
5927 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
5928 doc: /* Whether frames should be resized implicitly.
5929 If this option is nil, setting font, menu bar, tool bar, internal
5930 borders, fringes or scroll bars of a specific frame may resize the frame
5931 in order to preserve the number of columns or lines it displays. If
5932 this option is t, no such resizing is done. Note that the size of
5933 fullscreen and maximized frames, the height of fullheight frames and the
5934 width of fullwidth frames never change implicitly.
5936 The value of this option can be also be a list of frame parameters. In
5937 this case, resizing is inhibited when changing a parameter that appears
5938 in that list. The parameters currently handled by this option include
5939 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
5940 `tool-bar-lines'.
5942 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
5943 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
5944 `right-fringe' is handled as if the frame contained just one live
5945 window. This means, for example, that removing vertical scroll bars on
5946 a frame containing several side by side windows will shrink the frame
5947 width by the width of one scroll bar provided this option is nil and
5948 keep it unchanged if this option is either t or a list containing
5949 `vertical-scroll-bars'.
5951 The default value is \\='(tool-bar-lines) on Lucid, Motif and Windows
5952 \(which means that adding/removing a tool bar does not change the frame
5953 height), nil on all other window systems including GTK+ (which means
5954 that changing any of the parameters listed above may change the size of
5955 the frame), and t otherwise (which means the frame size never changes
5956 implicitly when there's no window system support).
5958 Note that when a frame is not large enough to accommodate a change of
5959 any of the parameters listed above, Emacs may try to enlarge the frame
5960 even if this option is non-nil. */);
5961 #if defined (HAVE_WINDOW_SYSTEM)
5962 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
5963 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
5964 #else
5965 frame_inhibit_implied_resize = Qnil;
5966 #endif
5967 #else
5968 frame_inhibit_implied_resize = Qt;
5969 #endif
5971 DEFVAR_LISP ("frame-size-history", frame_size_history,
5972 doc: /* History of frame size adjustments.
5973 If non-nil, list recording frame size adjustment. Adjustments are
5974 recorded only if the first element of this list is a positive number.
5975 Adding an adjustment decrements that number by one.
5977 The remaining elements are the adjustments. Each adjustment is a list
5978 of four elements `frame', `function', `sizes' and `more'. `frame' is
5979 the affected frame and `function' the invoking function. `sizes' is
5980 usually a list of four elements `old-width', `old-height', `new-width'
5981 and `new-height' representing the old and new sizes recorded/requested
5982 by `function'. `more' is a list with additional information.
5984 The function `frame--size-history' displays the value of this variable
5985 in a more readable form. */);
5986 frame_size_history = Qnil;
5988 DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame,
5989 doc: /* Non-nil means reuse hidden tooltip frames.
5990 When this is nil, delete a tooltip frame when hiding the associated
5991 tooltip. When this is non-nil, make the tooltip frame invisible only,
5992 so it can be reused when the next tooltip is shown.
5994 Setting this to non-nil may drastically reduce the consing overhead
5995 incurred by creating new tooltip frames. However, a value of non-nil
5996 means also that intermittent changes of faces or `default-frame-alist'
5997 are not applied when showing a tooltip in a reused frame.
5999 This variable is effective only with the X toolkit (and there only when
6000 Gtk+ tooltips are not used) and on Windows. */);
6001 tooltip_reuse_hidden_frame = false;
6003 staticpro (&Vframe_list);
6005 defsubr (&Sframep);
6006 defsubr (&Sframe_live_p);
6007 defsubr (&Swindow_system);
6008 defsubr (&Sframe_windows_min_size);
6009 defsubr (&Smake_terminal_frame);
6010 defsubr (&Shandle_switch_frame);
6011 defsubr (&Sselect_frame);
6012 defsubr (&Sselected_frame);
6013 defsubr (&Sframe_list);
6014 defsubr (&Sframe_parent);
6015 defsubr (&Sframe_ancestor_p);
6016 defsubr (&Snext_frame);
6017 defsubr (&Sprevious_frame);
6018 defsubr (&Slast_nonminibuf_frame);
6019 defsubr (&Sdelete_frame);
6020 defsubr (&Smouse_position);
6021 defsubr (&Smouse_pixel_position);
6022 defsubr (&Sset_mouse_position);
6023 defsubr (&Sset_mouse_pixel_position);
6024 #if 0
6025 defsubr (&Sframe_configuration);
6026 defsubr (&Srestore_frame_configuration);
6027 #endif
6028 defsubr (&Smake_frame_visible);
6029 defsubr (&Smake_frame_invisible);
6030 defsubr (&Siconify_frame);
6031 defsubr (&Sframe_visible_p);
6032 defsubr (&Svisible_frame_list);
6033 defsubr (&Sraise_frame);
6034 defsubr (&Slower_frame);
6035 defsubr (&Sx_focus_frame);
6036 defsubr (&Sframe_after_make_frame);
6037 defsubr (&Sredirect_frame_focus);
6038 defsubr (&Sframe_focus);
6039 defsubr (&Sframe_parameters);
6040 defsubr (&Sframe_parameter);
6041 defsubr (&Smodify_frame_parameters);
6042 defsubr (&Sframe_char_height);
6043 defsubr (&Sframe_char_width);
6044 defsubr (&Sframe_native_height);
6045 defsubr (&Sframe_native_width);
6046 defsubr (&Sframe_text_cols);
6047 defsubr (&Sframe_text_lines);
6048 defsubr (&Sframe_total_cols);
6049 defsubr (&Sframe_total_lines);
6050 defsubr (&Sframe_text_width);
6051 defsubr (&Sframe_text_height);
6052 defsubr (&Sscroll_bar_width);
6053 defsubr (&Sscroll_bar_height);
6054 defsubr (&Sfringe_width);
6055 defsubr (&Sframe_internal_border_width);
6056 defsubr (&Sright_divider_width);
6057 defsubr (&Sbottom_divider_width);
6058 defsubr (&Stool_bar_pixel_width);
6059 defsubr (&Sset_frame_height);
6060 defsubr (&Sset_frame_width);
6061 defsubr (&Sset_frame_size);
6062 defsubr (&Sframe_position);
6063 defsubr (&Sset_frame_position);
6064 defsubr (&Sframe_pointer_visible_p);
6066 #ifdef HAVE_WINDOW_SYSTEM
6067 defsubr (&Sx_get_resource);
6068 defsubr (&Sx_parse_geometry);
6069 #endif