Merge branch 'emacs-24'
[emacs.git] / src / frame.c
blobeaab63a0ea41d4a9391f92d806c7defcc0d22340
1 /* Generic frame functions.
3 Copyright (C) 1993-1995, 1997, 1999-2014 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
10 (at 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 <errno.h>
24 #include <limits.h>
26 #include <c-ctype.h>
28 #include "lisp.h"
29 #include "character.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 "commands.h"
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "blockinput.h"
41 #include "termchar.h"
42 #include "termhooks.h"
43 #include "dispextern.h"
44 #include "window.h"
45 #include "font.h"
46 #ifdef HAVE_WINDOW_SYSTEM
47 #include "fontset.h"
48 #endif
49 #include "cm.h"
50 #ifdef MSDOS
51 #include "msdos.h"
52 #include "dosfns.h"
53 #endif
54 #ifdef USE_X_TOOLKIT
55 #include "widget.h"
56 #endif
58 #ifdef HAVE_NS
59 Lisp_Object Qns_parse_geometry;
60 #endif
62 Lisp_Object Qframep, Qframe_live_p;
63 Lisp_Object Qicon, Qmodeline;
64 Lisp_Object Qonly, Qnone;
65 Lisp_Object Qx, Qw32, Qpc, Qns;
66 Lisp_Object Qvisible;
67 Lisp_Object Qdisplay_type;
68 static Lisp_Object Qbackground_mode;
69 Lisp_Object Qnoelisp;
71 static Lisp_Object Qx_frame_parameter;
72 Lisp_Object Qx_resource_name;
73 Lisp_Object Qterminal;
75 /* Frame parameters (set or reported). */
77 Lisp_Object Qauto_raise, Qauto_lower;
78 Lisp_Object Qborder_color, Qborder_width;
79 Lisp_Object Qcursor_color, Qcursor_type;
80 Lisp_Object Qheight, Qwidth;
81 Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
82 Lisp_Object Qtooltip;
83 Lisp_Object Qinternal_border_width;
84 Lisp_Object Qright_divider_width, Qbottom_divider_width;
85 Lisp_Object Qmouse_color;
86 Lisp_Object Qminibuffer;
87 Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
88 Lisp_Object Qscroll_bar_height, Qhorizontal_scroll_bars;
89 Lisp_Object Qvisibility;
90 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
91 Lisp_Object Qscreen_gamma;
92 Lisp_Object Qline_spacing;
93 static Lisp_Object Quser_position, Quser_size;
94 Lisp_Object Qwait_for_wm;
95 static Lisp_Object Qwindow_id;
96 #ifdef HAVE_X_WINDOWS
97 static Lisp_Object Qouter_window_id;
98 #endif
99 Lisp_Object Qparent_id;
100 Lisp_Object Qtitle, Qname;
101 static Lisp_Object Qexplicit_name;
102 Lisp_Object Qunsplittable;
103 Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position;
104 Lisp_Object Qleft_fringe, Qright_fringe;
105 Lisp_Object Qbuffer_predicate;
106 static Lisp_Object Qbuffer_list, Qburied_buffer_list;
107 Lisp_Object Qtty_color_mode;
108 Lisp_Object Qtty, Qtty_type;
110 Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth, Qmaximized;
111 Lisp_Object Qsticky;
112 Lisp_Object Qfont_backend;
113 Lisp_Object Qalpha;
115 Lisp_Object Qface_set_after_frame_default;
117 static Lisp_Object Qfocus_in_hook;
118 static Lisp_Object Qfocus_out_hook;
119 static Lisp_Object Qdelete_frame_functions;
120 static Lisp_Object Qframe_windows_min_size;
121 static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
123 Lisp_Object Qframe_position, Qframe_outer_size, Qframe_inner_size;
124 Lisp_Object Qexternal_border_size, Qtitle_height;
125 Lisp_Object Qmenu_bar_external, Qmenu_bar_size;
126 Lisp_Object Qtool_bar_external, Qtool_bar_size;
128 /* The currently selected frame. */
130 Lisp_Object selected_frame;
132 /* A frame which is not just a mini-buffer, or NULL if there are no such
133 frames. This is usually the most recent such frame that was selected. */
135 static struct frame *last_nonminibuf_frame;
137 /* False means there are no visible garbaged frames. */
138 bool frame_garbaged;
140 #ifdef HAVE_WINDOW_SYSTEM
141 static void x_report_frame_params (struct frame *, Lisp_Object *);
142 #endif
144 /* These setters are used only in this file, so they can be private. */
145 static void
146 fset_buffer_predicate (struct frame *f, Lisp_Object val)
148 f->buffer_predicate = val;
150 static void
151 fset_minibuffer_window (struct frame *f, Lisp_Object val)
153 f->minibuffer_window = val;
156 struct frame *
157 decode_live_frame (register Lisp_Object frame)
159 if (NILP (frame))
160 frame = selected_frame;
161 CHECK_LIVE_FRAME (frame);
162 return XFRAME (frame);
165 struct frame *
166 decode_any_frame (register Lisp_Object frame)
168 if (NILP (frame))
169 frame = selected_frame;
170 CHECK_FRAME (frame);
171 return XFRAME (frame);
174 #ifdef HAVE_WINDOW_SYSTEM
176 bool
177 window_system_available (struct frame *f)
179 return f ? FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f) : x_display_list != NULL;
182 #endif /* HAVE_WINDOW_SYSTEM */
184 struct frame *
185 decode_window_system_frame (Lisp_Object frame)
187 struct frame *f = decode_live_frame (frame);
189 if (!window_system_available (f))
190 error ("Window system frame should be used");
191 return f;
194 void
195 check_window_system (struct frame *f)
197 if (!window_system_available (f))
198 error (f ? "Window system frame should be used"
199 : "Window system is not in use or not initialized");
202 /* Return the value of frame parameter PROP in frame FRAME. */
204 Lisp_Object
205 get_frame_param (register struct frame *frame, Lisp_Object prop)
207 register Lisp_Object tem;
209 tem = Fassq (prop, frame->param_alist);
210 if (EQ (tem, Qnil))
211 return tem;
212 return Fcdr (tem);
215 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
216 state of frame F would be affected by a vertical (horizontal if
217 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
218 parameter that is changed. */
219 bool
220 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
222 return (EQ (frame_inhibit_implied_resize, Qt)
223 || (CONSP (frame_inhibit_implied_resize)
224 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
225 || !NILP (get_frame_param (f, Qfullscreen))
226 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
229 static void
230 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
232 int nlines;
233 int olines = FRAME_MENU_BAR_LINES (f);
235 /* Right now, menu bars don't work properly in minibuf-only frames;
236 most of the commands try to apply themselves to the minibuffer
237 frame itself, and get an error because you can't switch buffers
238 in or split the minibuffer window. */
239 if (FRAME_MINIBUF_ONLY_P (f))
240 return;
242 if (TYPE_RANGED_INTEGERP (int, value))
243 nlines = XINT (value);
244 else
245 nlines = 0;
247 if (nlines != olines)
249 windows_or_buffers_changed = 14;
250 FRAME_MENU_BAR_LINES (f) = nlines;
251 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
252 change_frame_size (f, FRAME_COLS (f),
253 FRAME_LINES (f) + olines - nlines,
254 0, 1, 0, 0);
258 Lisp_Object Vframe_list;
261 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
262 doc: /* Return non-nil if OBJECT is a frame.
263 Value is:
264 t for a termcap frame (a character-only terminal),
265 'x' for an Emacs frame that is really an X window,
266 'w32' for an Emacs frame that is a window on MS-Windows display,
267 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
268 'pc' for a direct-write MS-DOS frame.
269 See also `frame-live-p'. */)
270 (Lisp_Object object)
272 if (!FRAMEP (object))
273 return Qnil;
274 switch (XFRAME (object)->output_method)
276 case output_initial: /* The initial frame is like a termcap frame. */
277 case output_termcap:
278 return Qt;
279 case output_x_window:
280 return Qx;
281 case output_w32:
282 return Qw32;
283 case output_msdos_raw:
284 return Qpc;
285 case output_ns:
286 return Qns;
287 default:
288 emacs_abort ();
292 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
293 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
294 Value is nil if OBJECT is not a live frame. If object is a live
295 frame, the return value indicates what sort of terminal device it is
296 displayed on. See the documentation of `framep' for possible
297 return values. */)
298 (Lisp_Object object)
300 return ((FRAMEP (object)
301 && FRAME_LIVE_P (XFRAME (object)))
302 ? Fframep (object)
303 : Qnil);
306 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
307 doc: /* The name of the window system that FRAME is displaying through.
308 The value is a symbol:
309 nil for a termcap frame (a character-only terminal),
310 'x' for an Emacs frame that is really an X window,
311 'w32' for an Emacs frame that is a window on MS-Windows display,
312 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
313 'pc' for a direct-write MS-DOS frame.
315 FRAME defaults to the currently selected frame.
317 Use of this function as a predicate is deprecated. Instead,
318 use `display-graphic-p' or any of the other `display-*-p'
319 predicates which report frame's specific UI-related capabilities. */)
320 (Lisp_Object frame)
322 Lisp_Object type;
323 if (NILP (frame))
324 frame = selected_frame;
326 type = Fframep (frame);
328 if (NILP (type))
329 wrong_type_argument (Qframep, frame);
331 if (EQ (type, Qt))
332 return Qnil;
333 else
334 return type;
337 static int
338 frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, Lisp_Object pixelwise)
340 return XINT (call3 (Qframe_windows_min_size, frame, horizontal, pixelwise));
344 /* Make sure windows sizes of frame F are OK. new_width and new_height
345 are in pixels. A value of -1 means no change is requested for that
346 size (but the frame may still have to be resized to accommodate
347 windows with their minimum sizes). This can either issue a request
348 to resize the frame externally (via x_set_window_size), to resize the
349 frame internally (via resize_frame_windows) or do nothing at all.
351 The argument INHIBIT can assume the following values:
353 0 means to unconditionally call x_set_window_size even if sizes
354 apparently do not change. Fx_create_frame uses this to pass the
355 initial size to the window manager.
357 1 means to call x_set_window_size if the outer frame size really
358 changes. Fset_frame_size, Fset_frame_height, ... use this.
360 2 means to call x_set_window_size provided frame_inhibit_resize
361 allows it. The menu and tool bar code use this ("3" won't work
362 here in general because menu and tool bar are often not counted in
363 the frame's text height).
365 3 means call x_set_window_size if window minimum sizes must be
366 preserved or frame_inhibit_resize allows it. x_set_left_fringe,
367 x_set_scroll_bar_width, x_new_font ... use (or should use) this.
369 4 means call x_set_window_size only if window minimum sizes must be
370 preserved. x_set_right_divider_width, x_set_border_width and the
371 code responsible for wrapping the tool bar use this.
373 5 means to never call x_set_window_size. change_frame_size uses
374 this.
376 Note that even when x_set_window_size is not called, individual
377 windows may have to be resized (via `window--sanitize-window-sizes')
378 in order to support minimum size constraints.
380 PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
381 symbol of the parameter changed (like `menu-bar-lines', `font', ...).
382 This is passed on to frame_inhibit_resize to let the latter decide on
383 a case-by-case basis whether the frame may be resized externally. */
384 void
385 adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
386 bool pretend, Lisp_Object parameter)
388 int unit_width = FRAME_COLUMN_WIDTH (f);
389 int unit_height = FRAME_LINE_HEIGHT (f);
390 int old_pixel_width = FRAME_PIXEL_WIDTH (f);
391 int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
392 int new_pixel_width, new_pixel_height;
393 /* The following two values are calculated from the old frame pixel
394 sizes and any "new" settings for tool bar, menu bar and internal
395 borders. We do it this way to detect whether we have to call
396 x_set_window_size as consequence of the new settings. */
397 int windows_width = FRAME_WINDOWS_WIDTH (f);
398 int windows_height = FRAME_WINDOWS_HEIGHT (f);
399 int min_windows_width, min_windows_height;
400 /* These are a bit tedious, maybe we should use a macro. */
401 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
402 int old_windows_width = WINDOW_PIXEL_WIDTH (r);
403 int old_windows_height
404 = (WINDOW_PIXEL_HEIGHT (r)
405 + (FRAME_HAS_MINIBUF_P (f)
406 ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
407 : 0));
408 int new_windows_width, new_windows_height;
409 int old_text_width = FRAME_TEXT_WIDTH (f);
410 int old_text_height = FRAME_TEXT_HEIGHT (f);
411 /* If a size is < 0 use the old value. */
412 int new_text_width = (new_width >= 0) ? new_width : old_text_width;
413 int new_text_height = (new_height >= 0) ? new_height : old_text_height;
414 int new_cols, new_lines;
415 bool inhibit_horizontal, inhibit_vertical;
416 Lisp_Object frame;
418 XSETFRAME (frame, f);
419 /* The following two values are calculated from the old window body
420 sizes and any "new" settings for scroll bars, dividers, fringes and
421 margins (though the latter should have been processed already). */
422 min_windows_width = frame_windows_min_size (frame, Qt, Qt);
423 min_windows_height = frame_windows_min_size (frame, Qnil, Qt);
425 if (inhibit >= 2 && inhibit <= 4)
426 /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay
427 within the limits and either frame_inhibit_resize tells us to do
428 so or INHIBIT equals 4. */
430 inhibit_horizontal = ((windows_width >= min_windows_width
431 && (inhibit == 4
432 || frame_inhibit_resize (f, true, parameter)))
433 ? true : false);
434 inhibit_vertical = ((windows_height >= min_windows_height
435 && (inhibit == 4
436 || frame_inhibit_resize (f, false, parameter)))
437 ? true : false);
439 else
440 /* Otherwise inhibit if INHIBIT equals 5. */
441 inhibit_horizontal = inhibit_vertical = inhibit == 5;
443 new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
444 ? old_pixel_width
445 : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
446 min_windows_width
447 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
448 new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
449 new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
450 new_cols = new_text_width / unit_width;
452 new_pixel_height = ((inhibit_vertical && (inhibit < 5))
453 ? old_pixel_height
454 : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
455 min_windows_height
456 + FRAME_TOP_MARGIN_HEIGHT (f)
457 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
458 new_windows_height = (new_pixel_height
459 - FRAME_TOP_MARGIN_HEIGHT (f)
460 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
461 new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
462 new_lines = new_text_height / unit_height;
464 #ifdef HAVE_WINDOW_SYSTEM
465 if (FRAME_WINDOW_P (f)
466 && f->can_x_set_window_size
467 && ((!inhibit_horizontal
468 && (new_pixel_width != old_pixel_width
469 || inhibit == 0 || inhibit == 2))
470 || (!inhibit_vertical
471 && (new_pixel_height != old_pixel_height
472 || inhibit == 0 || inhibit == 2))))
473 /* We are either allowed to change the frame size or the minimum
474 sizes request such a change. Do not care for fixing minimum
475 sizes here, we do that eventually when we're called from
476 change_frame_size. */
478 /* Make sure we respect fullheight and fullwidth. */
479 if (inhibit_horizontal)
480 new_text_width = old_text_width;
481 else if (inhibit_vertical)
482 new_text_height = old_text_height;
484 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
485 f->resized_p = true;
487 return;
489 #endif
491 if (new_text_width == old_text_width
492 && new_text_height == old_text_height
493 && new_windows_width == old_windows_width
494 && new_windows_height == old_windows_height
495 && new_pixel_width == old_pixel_width
496 && new_pixel_height == old_pixel_height)
497 /* No change. Sanitize window sizes and return. */
499 sanitize_window_sizes (frame, Qt);
500 sanitize_window_sizes (frame, Qnil);
502 return;
505 block_input ();
507 #ifdef MSDOS
508 /* We only can set screen dimensions to certain values supported
509 by our video hardware. Try to find the smallest size greater
510 or equal to the requested dimensions. */
511 dos_set_window_size (&new_lines, &new_cols);
512 #endif
514 if (new_windows_width != old_windows_width)
516 resize_frame_windows (f, new_windows_width, 1, 1);
518 /* MSDOS frames cannot PRETEND, as they change frame size by
519 manipulating video hardware. */
520 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
521 FrameCols (FRAME_TTY (f)) = new_cols;
523 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
524 if (WINDOWP (f->tool_bar_window))
526 XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
527 XWINDOW (f->tool_bar_window)->total_cols
528 = new_windows_width / unit_width;
530 #endif
533 if (new_windows_height != old_windows_height
534 /* When the top margin has changed we have to recalculate the top
535 edges of all windows. No such calculation is necessary for the
536 left edges. */
537 || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
539 resize_frame_windows (f, new_windows_height, 0, 1);
541 /* MSDOS frames cannot PRETEND, as they change frame size by
542 manipulating video hardware. */
543 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
544 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
547 /* Assign new sizes. */
548 FRAME_TEXT_WIDTH (f) = new_text_width;
549 FRAME_TEXT_HEIGHT (f) = new_text_height;
550 FRAME_PIXEL_WIDTH (f) = new_pixel_width;
551 FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
552 SET_FRAME_COLS (f, new_cols);
553 SET_FRAME_LINES (f, new_lines);
556 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
557 int text_area_x, text_area_y, text_area_width, text_area_height;
559 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
560 &text_area_height);
561 if (w->cursor.x >= text_area_x + text_area_width)
562 w->cursor.hpos = w->cursor.x = 0;
563 if (w->cursor.y >= text_area_y + text_area_height)
564 w->cursor.vpos = w->cursor.y = 0;
567 /* Sanitize window sizes. */
568 sanitize_window_sizes (frame, Qt);
569 sanitize_window_sizes (frame, Qnil);
571 adjust_frame_glyphs (f);
572 calculate_costs (f);
573 SET_FRAME_GARBAGED (f);
575 /* A frame was "resized" if one of its pixelsizes changed, even if its
576 X window wasn't resized at all. */
577 f->resized_p = (new_pixel_width != old_pixel_width
578 || new_pixel_height != old_pixel_height);
580 unblock_input ();
582 run_window_configuration_change_hook (f);
586 struct frame *
587 make_frame (bool mini_p)
589 Lisp_Object frame;
590 register struct frame *f;
591 register struct window *rw, *mw;
592 register Lisp_Object root_window;
593 register Lisp_Object mini_window;
595 f = allocate_frame ();
596 XSETFRAME (frame, f);
598 #ifdef USE_GTK
599 /* Initialize Lisp data. Note that allocate_frame initializes all
600 Lisp data to nil, so do it only for slots which should not be nil. */
601 fset_tool_bar_position (f, Qtop);
602 #endif
604 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
605 non-Lisp data, so do it only for slots which should not be zero.
606 To avoid subtle bugs and for the sake of readability, it's better to
607 initialize enum members explicitly even if their values are zero. */
608 f->wants_modeline = true;
609 f->redisplay = true;
610 f->garbaged = true;
611 f->can_x_set_window_size = false;
612 f->can_run_window_configuration_change_hook = false;
613 f->column_width = 1; /* !FRAME_WINDOW_P value. */
614 f->line_height = 1; /* !FRAME_WINDOW_P value. */
615 #ifdef HAVE_WINDOW_SYSTEM
616 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
617 f->horizontal_scroll_bars = false;
618 f->want_fullscreen = FULLSCREEN_NONE;
619 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
620 f->last_tool_bar_item = -1;
621 #endif
622 #endif
624 root_window = make_window ();
625 rw = XWINDOW (root_window);
626 if (mini_p)
628 mini_window = make_window ();
629 mw = XWINDOW (mini_window);
630 wset_next (rw, mini_window);
631 wset_prev (mw, root_window);
632 mw->mini = 1;
633 wset_frame (mw, frame);
634 fset_minibuffer_window (f, mini_window);
636 else
638 mini_window = Qnil;
639 wset_next (rw, Qnil);
640 fset_minibuffer_window (f, Qnil);
643 wset_frame (rw, frame);
645 /* 10 is arbitrary,
646 just so that there is "something there."
647 Correct size will be set up later with adjust_frame_size. */
649 SET_FRAME_COLS (f, 10);
650 SET_FRAME_LINES (f, 10);
651 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
652 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
654 rw->total_cols = 10;
655 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
656 rw->total_lines = mini_p ? 9 : 10;
657 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
659 if (mini_p)
661 mw->top_line = rw->total_lines;
662 mw->pixel_top = rw->pixel_height;
663 mw->total_cols = rw->total_cols;
664 mw->pixel_width = rw->pixel_width;
665 mw->total_lines = 1;
666 mw->pixel_height = FRAME_LINE_HEIGHT (f);
669 /* Choose a buffer for the frame's root window. */
671 Lisp_Object buf = Fcurrent_buffer ();
673 /* If current buffer is hidden, try to find another one. */
674 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
675 buf = other_buffer_safely (buf);
677 /* Use set_window_buffer, not Fset_window_buffer, and don't let
678 hooks be run by it. The reason is that the whole frame/window
679 arrangement is not yet fully initialized at this point. Windows
680 don't have the right size, glyph matrices aren't initialized
681 etc. Running Lisp functions at this point surely ends in a
682 SEGV. */
683 set_window_buffer (root_window, buf, 0, 0);
684 fset_buffer_list (f, list1 (buf));
687 if (mini_p)
689 set_window_buffer (mini_window,
690 (NILP (Vminibuffer_list)
691 ? get_minibuffer (0)
692 : Fcar (Vminibuffer_list)),
693 0, 0);
694 /* No horizontal scroll bars in minibuffers. */
695 wset_horizontal_scroll_bar (mw, Qnil);
698 fset_root_window (f, root_window);
699 fset_selected_window (f, root_window);
700 /* Make sure this window seems more recently used than
701 a newly-created, never-selected window. */
702 XWINDOW (f->selected_window)->use_time = ++window_select_count;
704 return f;
707 #ifdef HAVE_WINDOW_SYSTEM
708 /* Make a frame using a separate minibuffer window on another frame.
709 MINI_WINDOW is the minibuffer window to use. nil means use the
710 default (the global minibuffer). */
712 struct frame *
713 make_frame_without_minibuffer (register Lisp_Object mini_window, KBOARD *kb, Lisp_Object display)
715 register struct frame *f;
716 struct gcpro gcpro1;
718 if (!NILP (mini_window))
719 CHECK_LIVE_WINDOW (mini_window);
721 if (!NILP (mini_window)
722 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
723 error ("Frame and minibuffer must be on the same terminal");
725 /* Make a frame containing just a root window. */
726 f = make_frame (0);
728 if (NILP (mini_window))
730 /* Use default-minibuffer-frame if possible. */
731 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
732 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
734 Lisp_Object frame_dummy;
736 XSETFRAME (frame_dummy, f);
737 GCPRO1 (frame_dummy);
738 /* If there's no minibuffer frame to use, create one. */
739 kset_default_minibuffer_frame
740 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
741 UNGCPRO;
744 mini_window
745 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
748 fset_minibuffer_window (f, mini_window);
750 /* Make the chosen minibuffer window display the proper minibuffer,
751 unless it is already showing a minibuffer. */
752 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
753 /* Use set_window_buffer instead of Fset_window_buffer (see
754 discussion of bug#11984, bug#12025, bug#12026). */
755 set_window_buffer (mini_window,
756 (NILP (Vminibuffer_list)
757 ? get_minibuffer (0)
758 : Fcar (Vminibuffer_list)), 0, 0);
759 return f;
762 /* Make a frame containing only a minibuffer window. */
764 struct frame *
765 make_minibuffer_frame (void)
767 /* First make a frame containing just a root window, no minibuffer. */
769 register struct frame *f = make_frame (0);
770 register Lisp_Object mini_window;
771 register Lisp_Object frame;
773 XSETFRAME (frame, f);
775 f->auto_raise = 0;
776 f->auto_lower = 0;
777 f->no_split = 1;
778 f->wants_modeline = 0;
780 /* Now label the root window as also being the minibuffer.
781 Avoid infinite looping on the window chain by marking next pointer
782 as nil. */
784 mini_window = f->root_window;
785 fset_minibuffer_window (f, mini_window);
786 XWINDOW (mini_window)->mini = 1;
787 wset_next (XWINDOW (mini_window), Qnil);
788 wset_prev (XWINDOW (mini_window), Qnil);
789 wset_frame (XWINDOW (mini_window), frame);
791 /* Put the proper buffer in that window. */
793 /* Use set_window_buffer instead of Fset_window_buffer (see
794 discussion of bug#11984, bug#12025, bug#12026). */
795 set_window_buffer (mini_window,
796 (NILP (Vminibuffer_list)
797 ? get_minibuffer (0)
798 : Fcar (Vminibuffer_list)), 0, 0);
799 return f;
801 #endif /* HAVE_WINDOW_SYSTEM */
803 /* Construct a frame that refers to a terminal. */
805 static printmax_t tty_frame_count;
807 struct frame *
808 make_initial_frame (void)
810 struct frame *f;
811 struct terminal *terminal;
812 Lisp_Object frame;
814 eassert (initial_kboard);
816 /* The first call must initialize Vframe_list. */
817 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
818 Vframe_list = Qnil;
820 terminal = init_initial_terminal ();
822 f = make_frame (1);
823 XSETFRAME (frame, f);
825 Vframe_list = Fcons (frame, Vframe_list);
827 tty_frame_count = 1;
828 fset_name (f, build_pure_c_string ("F1"));
830 SET_FRAME_VISIBLE (f, 1);
832 f->output_method = terminal->type;
833 f->terminal = terminal;
834 f->terminal->reference_count++;
835 f->output_data.nothing = 0;
837 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
838 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
840 #ifdef HAVE_WINDOW_SYSTEM
841 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
842 f->horizontal_scroll_bars = false;
843 #endif
845 /* The default value of menu-bar-mode is t. */
846 set_menu_bar_lines (f, make_number (1), Qnil);
848 if (!noninteractive)
849 init_frame_faces (f);
851 last_nonminibuf_frame = f;
853 return f;
857 static struct frame *
858 make_terminal_frame (struct terminal *terminal)
860 register struct frame *f;
861 Lisp_Object frame;
862 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
864 if (!terminal->name)
865 error ("Terminal is not live, can't create new frames on it");
867 f = make_frame (1);
869 XSETFRAME (frame, f);
870 Vframe_list = Fcons (frame, Vframe_list);
872 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
874 SET_FRAME_VISIBLE (f, 1);
876 f->terminal = terminal;
877 f->terminal->reference_count++;
878 #ifdef MSDOS
879 f->output_data.tty->display_info = &the_only_display_info;
880 if (!inhibit_window_system
881 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
882 || XFRAME (selected_frame)->output_method == output_msdos_raw))
883 f->output_method = output_msdos_raw;
884 else
885 f->output_method = output_termcap;
886 #else /* not MSDOS */
887 f->output_method = output_termcap;
888 create_tty_output (f);
889 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
890 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
891 #endif /* not MSDOS */
893 #ifdef HAVE_WINDOW_SYSTEM
894 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
895 f->horizontal_scroll_bars = false;
896 #endif
898 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
899 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
900 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
901 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
903 /* Set the top frame to the newly created frame. */
904 if (FRAMEP (FRAME_TTY (f)->top_frame)
905 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
906 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
908 FRAME_TTY (f)->top_frame = frame;
910 if (!noninteractive)
911 init_frame_faces (f);
913 return f;
916 /* Get a suitable value for frame parameter PARAMETER for a newly
917 created frame, based on (1) the user-supplied frame parameter
918 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
920 static Lisp_Object
921 get_future_frame_param (Lisp_Object parameter,
922 Lisp_Object supplied_parms,
923 char *current_value)
925 Lisp_Object result;
927 result = Fassq (parameter, supplied_parms);
928 if (NILP (result))
929 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
930 if (NILP (result) && current_value != NULL)
931 result = build_string (current_value);
932 if (!NILP (result) && !STRINGP (result))
933 result = XCDR (result);
934 if (NILP (result) || !STRINGP (result))
935 result = Qnil;
937 return result;
940 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
941 1, 1, 0,
942 doc: /* Create an additional terminal frame, possibly on another terminal.
943 This function takes one argument, an alist specifying frame parameters.
945 You can create multiple frames on a single text terminal, but only one
946 of them (the selected terminal frame) is actually displayed.
948 In practice, generally you don't need to specify any parameters,
949 except when you want to create a new frame on another terminal.
950 In that case, the `tty' parameter specifies the device file to open,
951 and the `tty-type' parameter specifies the terminal type. Example:
953 (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
955 Note that changing the size of one terminal frame automatically
956 affects all frames on the same terminal device. */)
957 (Lisp_Object parms)
959 struct frame *f;
960 struct terminal *t = NULL;
961 Lisp_Object frame, tem;
962 struct frame *sf = SELECTED_FRAME ();
964 #ifdef MSDOS
965 if (sf->output_method != output_msdos_raw
966 && sf->output_method != output_termcap)
967 emacs_abort ();
968 #else /* not MSDOS */
970 #ifdef WINDOWSNT /* This should work now! */
971 if (sf->output_method != output_termcap)
972 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
973 #endif
974 #endif /* not MSDOS */
977 Lisp_Object terminal;
979 terminal = Fassq (Qterminal, parms);
980 if (CONSP (terminal))
982 terminal = XCDR (terminal);
983 t = decode_live_terminal (terminal);
985 #ifdef MSDOS
986 if (t && t != the_only_display_info.terminal)
987 /* msdos.c assumes a single tty_display_info object. */
988 error ("Multiple terminals are not supported on this platform");
989 if (!t)
990 t = the_only_display_info.terminal;
991 #endif
994 if (!t)
996 char *name = 0, *type = 0;
997 Lisp_Object tty, tty_type;
998 USE_SAFE_ALLOCA;
1000 tty = get_future_frame_param
1001 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1002 ? FRAME_TTY (XFRAME (selected_frame))->name
1003 : NULL));
1004 if (!NILP (tty))
1005 SAFE_ALLOCA_STRING (name, tty);
1007 tty_type = get_future_frame_param
1008 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1009 ? FRAME_TTY (XFRAME (selected_frame))->type
1010 : NULL));
1011 if (!NILP (tty_type))
1012 SAFE_ALLOCA_STRING (type, tty_type);
1014 t = init_tty (name, type, 0); /* Errors are not fatal. */
1015 SAFE_FREE ();
1018 f = make_terminal_frame (t);
1021 int width, height;
1022 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1023 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil);
1026 adjust_frame_glyphs (f);
1027 calculate_costs (f);
1028 XSETFRAME (frame, f);
1030 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
1031 store_in_alist (&parms, Qtty,
1032 (t->display_info.tty->name
1033 ? build_string (t->display_info.tty->name)
1034 : Qnil));
1035 Fmodify_frame_parameters (frame, parms);
1037 /* Make the frame face alist be frame-specific, so that each
1038 frame could change its face definitions independently. */
1039 fset_face_alist (f, Fcopy_alist (sf->face_alist));
1040 /* Simple Fcopy_alist isn't enough, because we need the contents of
1041 the vectors which are the CDRs of associations in face_alist to
1042 be copied as well. */
1043 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
1044 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
1045 return frame;
1049 /* Perform the switch to frame FRAME.
1051 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
1052 FRAME1 as frame.
1054 If TRACK is non-zero and the frame that currently has the focus
1055 redirects its focus to the selected frame, redirect that focused
1056 frame's focus to FRAME instead.
1058 FOR_DELETION non-zero means that the selected frame is being
1059 deleted, which includes the possibility that the frame's terminal
1060 is dead.
1062 The value of NORECORD is passed as argument to Fselect_window. */
1064 Lisp_Object
1065 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1067 struct frame *sf = SELECTED_FRAME ();
1069 /* If FRAME is a switch-frame event, extract the frame we should
1070 switch to. */
1071 if (CONSP (frame)
1072 && EQ (XCAR (frame), Qswitch_frame)
1073 && CONSP (XCDR (frame)))
1074 frame = XCAR (XCDR (frame));
1076 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1077 a switch-frame event to arrive after a frame is no longer live,
1078 especially when deleting the initial frame during startup. */
1079 CHECK_FRAME (frame);
1080 if (! FRAME_LIVE_P (XFRAME (frame)))
1081 return Qnil;
1083 if (sf == XFRAME (frame))
1084 return frame;
1086 /* If a frame's focus has been redirected toward the currently
1087 selected frame, we should change the redirection to point to the
1088 newly selected frame. This means that if the focus is redirected
1089 from a minibufferless frame to a surrogate minibuffer frame, we
1090 can use `other-window' to switch between all the frames using
1091 that minibuffer frame, and the focus redirection will follow us
1092 around. */
1093 #if 0
1094 /* This is too greedy; it causes inappropriate focus redirection
1095 that's hard to get rid of. */
1096 if (track)
1098 Lisp_Object tail;
1100 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1102 Lisp_Object focus;
1104 if (!FRAMEP (XCAR (tail)))
1105 emacs_abort ();
1107 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1109 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1110 Fredirect_frame_focus (XCAR (tail), frame);
1113 #else /* ! 0 */
1114 /* Instead, apply it only to the frame we're pointing to. */
1115 #ifdef HAVE_WINDOW_SYSTEM
1116 if (track && FRAME_WINDOW_P (XFRAME (frame)))
1118 Lisp_Object focus, xfocus;
1120 xfocus = x_get_focus_frame (XFRAME (frame));
1121 if (FRAMEP (xfocus))
1123 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1124 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1125 Fredirect_frame_focus (xfocus, frame);
1128 #endif /* HAVE_X_WINDOWS */
1129 #endif /* ! 0 */
1131 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1132 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1134 if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame)))
1136 struct frame *f = XFRAME (frame);
1137 struct tty_display_info *tty = FRAME_TTY (f);
1138 Lisp_Object top_frame = tty->top_frame;
1140 /* Don't mark the frame garbaged and/or obscured if we are
1141 switching to the frame that is already the top frame of that
1142 TTY. */
1143 if (!EQ (frame, top_frame))
1145 if (FRAMEP (top_frame))
1146 /* Mark previously displayed frame as now obscured. */
1147 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1148 SET_FRAME_VISIBLE (f, 1);
1149 /* If the new TTY frame changed dimensions, we need to
1150 resync term.c's idea of the frame size with the new
1151 frame's data. */
1152 if (FRAME_COLS (f) != FrameCols (tty))
1153 FrameCols (tty) = FRAME_COLS (f);
1154 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1155 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1157 tty->top_frame = frame;
1160 selected_frame = frame;
1161 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1162 last_nonminibuf_frame = XFRAME (selected_frame);
1164 Fselect_window (XFRAME (frame)->selected_window, norecord);
1166 /* We want to make sure that the next event generates a frame-switch
1167 event to the appropriate frame. This seems kludgy to me, but
1168 before you take it out, make sure that evaluating something like
1169 (select-window (frame-root-window (new-frame))) doesn't end up
1170 with your typing being interpreted in the new frame instead of
1171 the one you're actually typing in. */
1172 internal_last_event_frame = Qnil;
1174 return frame;
1177 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1178 doc: /* Select FRAME.
1179 Subsequent editing commands apply to its selected window.
1180 Optional argument NORECORD means to neither change the order of
1181 recently selected windows nor the buffer list.
1183 The selection of FRAME lasts until the next time the user does
1184 something to select a different frame, or until the next time
1185 this function is called. If you are using a window system, the
1186 previously selected frame may be restored as the selected frame
1187 when returning to the command loop, because it still may have
1188 the window system's input focus. On a text terminal, the next
1189 redisplay will display FRAME.
1191 This function returns FRAME, or nil if FRAME has been deleted. */)
1192 (Lisp_Object frame, Lisp_Object norecord)
1194 return do_switch_frame (frame, 1, 0, norecord);
1197 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1198 doc: /* Handle a switch-frame event EVENT.
1199 Switch-frame events are usually bound to this function.
1200 A switch-frame event tells Emacs that the window manager has requested
1201 that the user's events be directed to the frame mentioned in the event.
1202 This function selects the selected window of the frame of EVENT.
1204 If EVENT is frame object, handle it as if it were a switch-frame event
1205 to that frame. */)
1206 (Lisp_Object event)
1208 /* Preserve prefix arg that the command loop just cleared. */
1209 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1210 Frun_hooks (1, &Qmouse_leave_buffer_hook);
1211 /* `switch-frame' implies a focus in. */
1212 call1 (intern ("handle-focus-in"), event);
1213 return do_switch_frame (event, 0, 0, Qnil);
1216 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1217 doc: /* Return the frame that is now selected. */)
1218 (void)
1220 return selected_frame;
1223 DEFUN ("frame-list", Fframe_list, Sframe_list,
1224 0, 0, 0,
1225 doc: /* Return a list of all live frames. */)
1226 (void)
1228 Lisp_Object frames;
1229 frames = Fcopy_sequence (Vframe_list);
1230 #ifdef HAVE_WINDOW_SYSTEM
1231 if (FRAMEP (tip_frame))
1232 frames = Fdelq (tip_frame, frames);
1233 #endif
1234 return frames;
1237 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1238 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1239 If MINIBUF is nil, do not consider minibuffer-only candidate.
1240 If MINIBUF is `visible', do not consider an invisible candidate.
1241 If MINIBUF is a window, consider only its own frame and candidate now
1242 using that window as the minibuffer.
1243 If MINIBUF is 0, consider candidate if it is visible or iconified.
1244 Otherwise consider any candidate and return nil if CANDIDATE is not
1245 acceptable. */
1247 static Lisp_Object
1248 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1250 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1252 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1253 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1254 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1255 && FRAME_TTY (c) == FRAME_TTY (f)))
1257 if (NILP (minibuf))
1259 if (!FRAME_MINIBUF_ONLY_P (c))
1260 return candidate;
1262 else if (EQ (minibuf, Qvisible))
1264 if (FRAME_VISIBLE_P (c))
1265 return candidate;
1267 else if (WINDOWP (minibuf))
1269 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1270 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1271 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1272 FRAME_FOCUS_FRAME (c)))
1273 return candidate;
1275 else if (XFASTINT (minibuf) == 0)
1277 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1278 return candidate;
1280 else
1281 return candidate;
1283 return Qnil;
1286 /* Return the next frame in the frame list after FRAME. */
1288 static Lisp_Object
1289 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1291 Lisp_Object f, tail;
1292 int passed = 0;
1294 /* There must always be at least one frame in Vframe_list. */
1295 eassert (CONSP (Vframe_list));
1297 while (passed < 2)
1298 FOR_EACH_FRAME (tail, f)
1300 if (passed)
1302 f = candidate_frame (f, frame, minibuf);
1303 if (!NILP (f))
1304 return f;
1306 if (EQ (frame, f))
1307 passed++;
1309 return frame;
1312 /* Return the previous frame in the frame list before FRAME. */
1314 static Lisp_Object
1315 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1317 Lisp_Object f, tail, prev = Qnil;
1319 /* There must always be at least one frame in Vframe_list. */
1320 eassert (CONSP (Vframe_list));
1322 FOR_EACH_FRAME (tail, f)
1324 if (EQ (frame, f) && !NILP (prev))
1325 return prev;
1326 f = candidate_frame (f, frame, minibuf);
1327 if (!NILP (f))
1328 prev = f;
1331 /* We've scanned the entire list. */
1332 if (NILP (prev))
1333 /* We went through the whole frame list without finding a single
1334 acceptable frame. Return the original frame. */
1335 return frame;
1336 else
1337 /* There were no acceptable frames in the list before FRAME; otherwise,
1338 we would have returned directly from the loop. Since PREV is the last
1339 acceptable frame in the list, return it. */
1340 return prev;
1344 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1345 doc: /* Return the next frame in the frame list after FRAME.
1346 It considers only frames on the same terminal as FRAME.
1347 By default, skip minibuffer-only frames.
1348 If omitted, FRAME defaults to the selected frame.
1349 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1350 If MINIFRAME is a window, include only its own frame
1351 and any frame now using that window as the minibuffer.
1352 If MINIFRAME is `visible', include all visible frames.
1353 If MINIFRAME is 0, include all visible and iconified frames.
1354 Otherwise, include all frames. */)
1355 (Lisp_Object frame, Lisp_Object miniframe)
1357 if (NILP (frame))
1358 frame = selected_frame;
1359 CHECK_LIVE_FRAME (frame);
1360 return next_frame (frame, miniframe);
1363 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1364 doc: /* Return the previous frame in the frame list before FRAME.
1365 It considers only frames on the same terminal as FRAME.
1366 By default, skip minibuffer-only frames.
1367 If omitted, FRAME defaults to the selected frame.
1368 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1369 If MINIFRAME is a window, include only its own frame
1370 and any frame now using that window as the minibuffer.
1371 If MINIFRAME is `visible', include all visible frames.
1372 If MINIFRAME is 0, include all visible and iconified frames.
1373 Otherwise, include all frames. */)
1374 (Lisp_Object frame, Lisp_Object miniframe)
1376 if (NILP (frame))
1377 frame = selected_frame;
1378 CHECK_LIVE_FRAME (frame);
1379 return prev_frame (frame, miniframe);
1382 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1383 Slast_nonminibuf_frame, 0, 0, 0,
1384 doc: /* Return last non-minibuffer frame selected. */)
1385 (void)
1387 Lisp_Object frame = Qnil;
1389 if (last_nonminibuf_frame)
1390 XSETFRAME (frame, last_nonminibuf_frame);
1392 return frame;
1395 /* Return 1 if it is ok to delete frame F;
1396 0 if all frames aside from F are invisible.
1397 (Exception: if F is the terminal frame, and we are using X, return 1.) */
1399 static int
1400 other_visible_frames (struct frame *f)
1402 Lisp_Object frames, this;
1404 FOR_EACH_FRAME (frames, this)
1406 if (f == XFRAME (this))
1407 continue;
1409 /* Verify that we can still talk to the frame's X window,
1410 and note any recent change in visibility. */
1411 #ifdef HAVE_X_WINDOWS
1412 if (FRAME_WINDOW_P (XFRAME (this)))
1413 x_sync (XFRAME (this));
1414 #endif
1416 if (FRAME_VISIBLE_P (XFRAME (this))
1417 || FRAME_ICONIFIED_P (XFRAME (this))
1418 /* Allow deleting the terminal frame when at least one X
1419 frame exists. */
1420 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
1421 return 1;
1423 return 0;
1426 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1427 window. Preferably use the selected frame's minibuffer window
1428 instead. If the selected frame doesn't have one, get some other
1429 frame's minibuffer window. SELECT non-zero means select the new
1430 minibuffer window. */
1431 static void
1432 check_minibuf_window (Lisp_Object frame, int select)
1434 struct frame *f = decode_live_frame (frame);
1436 XSETFRAME (frame, f);
1438 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1440 Lisp_Object frames, this, window = make_number (0);
1442 if (!EQ (frame, selected_frame)
1443 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1444 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1445 else
1446 FOR_EACH_FRAME (frames, this)
1448 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1450 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1451 break;
1455 /* Don't abort if no window was found (Bug#15247). */
1456 if (WINDOWP (window))
1458 /* Use set_window_buffer instead of Fset_window_buffer (see
1459 discussion of bug#11984, bug#12025, bug#12026). */
1460 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1461 minibuf_window = window;
1463 /* SELECT non-zero usually means that FRAME's minibuffer
1464 window was selected; select the new one. */
1465 if (select)
1466 Fselect_window (minibuf_window, Qnil);
1472 /* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1473 unconditionally. x_connection_closed and delete_terminal use
1474 this. Any other value of FORCE implements the semantics
1475 described for Fdelete_frame. */
1476 Lisp_Object
1477 delete_frame (Lisp_Object frame, Lisp_Object force)
1479 struct frame *f = decode_any_frame (frame);
1480 struct frame *sf;
1481 struct kboard *kb;
1483 int minibuffer_selected, is_tooltip_frame;
1485 if (! FRAME_LIVE_P (f))
1486 return Qnil;
1488 if (NILP (force) && !other_visible_frames (f))
1489 error ("Attempt to delete the sole visible or iconified frame");
1491 /* x_connection_closed must have set FORCE to `noelisp' in order
1492 to delete the last frame, if it is gone. */
1493 if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp))
1494 error ("Attempt to delete the only frame");
1496 XSETFRAME (frame, f);
1498 /* Does this frame have a minibuffer, and is it the surrogate
1499 minibuffer for any other frame? */
1500 if (FRAME_HAS_MINIBUF_P (f))
1502 Lisp_Object frames, this;
1504 FOR_EACH_FRAME (frames, this)
1506 Lisp_Object fminiw;
1508 if (EQ (this, frame))
1509 continue;
1511 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (this));
1513 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1515 /* If we MUST delete this frame, delete the other first.
1516 But do this only if FORCE equals `noelisp'. */
1517 if (EQ (force, Qnoelisp))
1518 delete_frame (this, Qnoelisp);
1519 else
1520 error ("Attempt to delete a surrogate minibuffer frame");
1525 is_tooltip_frame = !NILP (Fframe_parameter (frame, intern ("tooltip")));
1527 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1528 frame is a tooltip. FORCE is set to `noelisp' when handling
1529 a disconnect from the terminal, so we don't dare call Lisp
1530 code. */
1531 if (NILP (Vrun_hooks) || is_tooltip_frame)
1533 else if (EQ (force, Qnoelisp))
1534 pending_funcalls
1535 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1536 pending_funcalls);
1537 else
1539 #ifdef HAVE_X_WINDOWS
1540 /* Also, save clipboard to the clipboard manager. */
1541 x_clipboard_manager_save_frame (frame);
1542 #endif
1544 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1547 /* The hook may sometimes (indirectly) cause the frame to be deleted. */
1548 if (! FRAME_LIVE_P (f))
1549 return Qnil;
1551 /* At this point, we are committed to deleting the frame.
1552 There is no more chance for errors to prevent it. */
1554 minibuffer_selected = EQ (minibuf_window, selected_window);
1555 sf = SELECTED_FRAME ();
1556 /* Don't let the frame remain selected. */
1557 if (f == sf)
1559 Lisp_Object tail;
1560 Lisp_Object frame1 = Qnil;
1562 /* Look for another visible frame on the same terminal.
1563 Do not call next_frame here because it may loop forever.
1564 See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1565 FOR_EACH_FRAME (tail, frame1)
1566 if (!EQ (frame, frame1)
1567 && (FRAME_TERMINAL (XFRAME (frame))
1568 == FRAME_TERMINAL (XFRAME (frame1)))
1569 && FRAME_VISIBLE_P (XFRAME (frame1)))
1570 break;
1572 /* If there is none, find *some* other frame. */
1573 if (NILP (frame1) || EQ (frame1, frame))
1575 FOR_EACH_FRAME (tail, frame1)
1577 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
1579 /* Do not change a text terminal's top-frame. */
1580 struct frame *f1 = XFRAME (frame1);
1581 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1583 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1584 if (!EQ (top_frame, frame))
1585 frame1 = top_frame;
1587 break;
1591 #ifdef NS_IMPL_COCOA
1592 else
1593 /* Under NS, there is no system mechanism for choosing a new
1594 window to get focus -- it is left to application code.
1595 So the portion of THIS application interfacing with NS
1596 needs to know about it. We call Fraise_frame, but the
1597 purpose is really to transfer focus. */
1598 Fraise_frame (frame1);
1599 #endif
1601 do_switch_frame (frame1, 0, 1, Qnil);
1602 sf = SELECTED_FRAME ();
1605 /* Don't allow minibuf_window to remain on a deleted frame. */
1606 check_minibuf_window (frame, minibuffer_selected);
1608 /* Don't let echo_area_window to remain on a deleted frame. */
1609 if (EQ (f->minibuffer_window, echo_area_window))
1610 echo_area_window = sf->minibuffer_window;
1612 /* Clear any X selections for this frame. */
1613 #ifdef HAVE_X_WINDOWS
1614 if (FRAME_X_P (f))
1615 x_clear_frame_selections (f);
1616 #endif
1618 /* Free glyphs.
1619 This function must be called before the window tree of the
1620 frame is deleted because windows contain dynamically allocated
1621 memory. */
1622 free_glyphs (f);
1624 #ifdef HAVE_WINDOW_SYSTEM
1625 /* Give chance to each font driver to free a frame specific data. */
1626 font_update_drivers (f, Qnil);
1627 #endif
1629 /* Mark all the windows that used to be on FRAME as deleted, and then
1630 remove the reference to them. */
1631 delete_all_child_windows (f->root_window);
1632 fset_root_window (f, Qnil);
1634 Vframe_list = Fdelq (frame, Vframe_list);
1635 SET_FRAME_VISIBLE (f, 0);
1637 /* Allow the vector of menu bar contents to be freed in the next
1638 garbage collection. The frame object itself may not be garbage
1639 collected until much later, because recent_keys and other data
1640 structures can still refer to it. */
1641 fset_menu_bar_vector (f, Qnil);
1643 /* If FRAME's buffer lists contains killed
1644 buffers, this helps GC to reclaim them. */
1645 fset_buffer_list (f, Qnil);
1646 fset_buried_buffer_list (f, Qnil);
1648 free_font_driver_list (f);
1649 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1650 xfree (f->namebuf);
1651 #endif
1652 xfree (f->decode_mode_spec_buffer);
1653 xfree (FRAME_INSERT_COST (f));
1654 xfree (FRAME_DELETEN_COST (f));
1655 xfree (FRAME_INSERTN_COST (f));
1656 xfree (FRAME_DELETE_COST (f));
1658 /* Since some events are handled at the interrupt level, we may get
1659 an event for f at any time; if we zero out the frame's terminal
1660 now, then we may trip up the event-handling code. Instead, we'll
1661 promise that the terminal of the frame must be valid until we
1662 have called the window-system-dependent frame destruction
1663 routine. */
1667 struct terminal *terminal;
1668 block_input ();
1669 if (FRAME_TERMINAL (f)->delete_frame_hook)
1670 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
1671 terminal = FRAME_TERMINAL (f);
1672 f->output_data.nothing = 0;
1673 f->terminal = 0; /* Now the frame is dead. */
1674 unblock_input ();
1676 /* If needed, delete the terminal that this frame was on.
1677 (This must be done after the frame is killed.) */
1678 terminal->reference_count--;
1679 #ifdef USE_GTK
1680 /* FIXME: Deleting the terminal crashes emacs because of a GTK
1681 bug.
1682 http://lists.gnu.org/archive/html/emacs-devel/2011-10/msg00363.html */
1683 if (terminal->reference_count == 0 && terminal->type == output_x_window)
1684 terminal->reference_count = 1;
1685 #endif /* USE_GTK */
1686 if (terminal->reference_count == 0)
1688 Lisp_Object tmp;
1689 XSETTERMINAL (tmp, terminal);
1691 kb = NULL;
1692 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
1694 else
1695 kb = terminal->kboard;
1698 /* If we've deleted the last_nonminibuf_frame, then try to find
1699 another one. */
1700 if (f == last_nonminibuf_frame)
1702 Lisp_Object frames, this;
1704 last_nonminibuf_frame = 0;
1706 FOR_EACH_FRAME (frames, this)
1708 f = XFRAME (this);
1709 if (!FRAME_MINIBUF_ONLY_P (f))
1711 last_nonminibuf_frame = f;
1712 break;
1717 /* If there's no other frame on the same kboard, get out of
1718 single-kboard state if we're in it for this kboard. */
1719 if (kb != NULL)
1721 Lisp_Object frames, this;
1722 /* Some frame we found on the same kboard, or nil if there are none. */
1723 Lisp_Object frame_on_same_kboard = Qnil;
1725 FOR_EACH_FRAME (frames, this)
1726 if (kb == FRAME_KBOARD (XFRAME (this)))
1727 frame_on_same_kboard = this;
1729 if (NILP (frame_on_same_kboard))
1730 not_single_kboard_state (kb);
1734 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1735 find another one. Prefer minibuffer-only frames, but also notice
1736 frames with other windows. */
1737 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
1739 Lisp_Object frames, this;
1741 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
1742 Lisp_Object frame_with_minibuf = Qnil;
1743 /* Some frame we found on the same kboard, or nil if there are none. */
1744 Lisp_Object frame_on_same_kboard = Qnil;
1746 FOR_EACH_FRAME (frames, this)
1748 struct frame *f1 = XFRAME (this);
1750 /* Consider only frames on the same kboard
1751 and only those with minibuffers. */
1752 if (kb == FRAME_KBOARD (f1)
1753 && FRAME_HAS_MINIBUF_P (f1))
1755 frame_with_minibuf = this;
1756 if (FRAME_MINIBUF_ONLY_P (f1))
1757 break;
1760 if (kb == FRAME_KBOARD (f1))
1761 frame_on_same_kboard = this;
1764 if (!NILP (frame_on_same_kboard))
1766 /* We know that there must be some frame with a minibuffer out
1767 there. If this were not true, all of the frames present
1768 would have to be minibufferless, which implies that at some
1769 point their minibuffer frames must have been deleted, but
1770 that is prohibited at the top; you can't delete surrogate
1771 minibuffer frames. */
1772 if (NILP (frame_with_minibuf))
1773 emacs_abort ();
1775 kset_default_minibuffer_frame (kb, frame_with_minibuf);
1777 else
1778 /* No frames left on this kboard--say no minibuffer either. */
1779 kset_default_minibuffer_frame (kb, Qnil);
1782 /* Cause frame titles to update--necessary if we now have just one frame. */
1783 if (!is_tooltip_frame)
1784 update_mode_lines = 15;
1786 return Qnil;
1789 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
1790 doc: /* Delete FRAME, permanently eliminating it from use.
1791 FRAME defaults to the selected frame.
1793 A frame may not be deleted if its minibuffer is used by other frames.
1794 Normally, you may not delete a frame if all other frames are invisible,
1795 but if the second optional argument FORCE is non-nil, you may do so.
1797 This function runs `delete-frame-functions' before actually
1798 deleting the frame, unless the frame is a tooltip.
1799 The functions are run with one argument, the frame to be deleted. */)
1800 (Lisp_Object frame, Lisp_Object force)
1802 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
1806 /* Return mouse position in character cell units. */
1808 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
1809 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1810 The position is given in canonical character cells, where (0, 0) is the
1811 upper-left corner of the frame, X is the horizontal offset, and Y is the
1812 vertical offset, measured in units of the frame's default character size.
1813 If Emacs is running on a mouseless terminal or hasn't been programmed
1814 to read the mouse position, it returns the selected frame for FRAME
1815 and nil for X and Y.
1816 If `mouse-position-function' is non-nil, `mouse-position' calls it,
1817 passing the normal return value to that function as an argument,
1818 and returns whatever that function returns. */)
1819 (void)
1821 struct frame *f;
1822 Lisp_Object lispy_dummy;
1823 Lisp_Object x, y, retval;
1824 struct gcpro gcpro1;
1826 f = SELECTED_FRAME ();
1827 x = y = Qnil;
1829 /* It's okay for the hook to refrain from storing anything. */
1830 if (FRAME_TERMINAL (f)->mouse_position_hook)
1832 enum scroll_bar_part party_dummy;
1833 Time time_dummy;
1834 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1835 &lispy_dummy, &party_dummy,
1836 &x, &y,
1837 &time_dummy);
1840 if (! NILP (x))
1842 int col = XINT (x);
1843 int row = XINT (y);
1844 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
1845 XSETINT (x, col);
1846 XSETINT (y, row);
1848 XSETFRAME (lispy_dummy, f);
1849 retval = Fcons (lispy_dummy, Fcons (x, y));
1850 GCPRO1 (retval);
1851 if (!NILP (Vmouse_position_function))
1852 retval = call1 (Vmouse_position_function, retval);
1853 RETURN_UNGCPRO (retval);
1856 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
1857 Smouse_pixel_position, 0, 0, 0,
1858 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1859 The position is given in pixel units, where (0, 0) is the
1860 upper-left corner of the frame, X is the horizontal offset, and Y is
1861 the vertical offset.
1862 If Emacs is running on a mouseless terminal or hasn't been programmed
1863 to read the mouse position, it returns the selected frame for FRAME
1864 and nil for X and Y. */)
1865 (void)
1867 struct frame *f;
1868 Lisp_Object lispy_dummy;
1869 Lisp_Object x, y, retval;
1870 struct gcpro gcpro1;
1872 f = SELECTED_FRAME ();
1873 x = y = Qnil;
1875 /* It's okay for the hook to refrain from storing anything. */
1876 if (FRAME_TERMINAL (f)->mouse_position_hook)
1878 enum scroll_bar_part party_dummy;
1879 Time time_dummy;
1880 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1881 &lispy_dummy, &party_dummy,
1882 &x, &y,
1883 &time_dummy);
1886 XSETFRAME (lispy_dummy, f);
1887 retval = Fcons (lispy_dummy, Fcons (x, y));
1888 GCPRO1 (retval);
1889 if (!NILP (Vmouse_position_function))
1890 retval = call1 (Vmouse_position_function, retval);
1891 RETURN_UNGCPRO (retval);
1894 #ifdef HAVE_WINDOW_SYSTEM
1896 /* On frame F, convert character coordinates X and Y to pixel
1897 coordinates *PIX_X and *PIX_Y. */
1899 static void
1900 frame_char_to_pixel_position (struct frame *f, int x, int y,
1901 int *pix_x, int *pix_y)
1903 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
1904 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
1906 if (*pix_x < 0)
1907 *pix_x = 0;
1908 if (*pix_x > FRAME_PIXEL_WIDTH (f))
1909 *pix_x = FRAME_PIXEL_WIDTH (f);
1911 if (*pix_y < 0)
1912 *pix_y = 0;
1913 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
1914 *pix_y = FRAME_PIXEL_HEIGHT (f);
1917 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
1919 static void
1920 frame_set_mouse_position (struct frame *f, int x, int y)
1922 int pix_x, pix_y;
1924 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
1925 frame_set_mouse_pixel_position (f, pix_x, pix_y);
1928 #endif /* HAVE_WINDOW_SYSTEM */
1930 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
1931 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
1932 Coordinates are relative to the frame, not a window,
1933 so the coordinates of the top left character in the frame
1934 may be nonzero due to left-hand scroll bars or the menu bar.
1936 The position is given in canonical character cells, where (0, 0) is
1937 the upper-left corner of the frame, X is the horizontal offset, and
1938 Y is the vertical offset, measured in units of the frame's default
1939 character size.
1941 This function is a no-op for an X frame that is not visible.
1942 If you have just created a frame, you must wait for it to become visible
1943 before calling this function on it, like this.
1944 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
1945 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
1947 CHECK_LIVE_FRAME (frame);
1948 CHECK_TYPE_RANGED_INTEGER (int, x);
1949 CHECK_TYPE_RANGED_INTEGER (int, y);
1951 /* I think this should be done with a hook. */
1952 #ifdef HAVE_WINDOW_SYSTEM
1953 if (FRAME_WINDOW_P (XFRAME (frame)))
1954 /* Warping the mouse will cause enternotify and focus events. */
1955 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
1956 #else
1957 #if defined (MSDOS)
1958 if (FRAME_MSDOS_P (XFRAME (frame)))
1960 Fselect_frame (frame, Qnil);
1961 mouse_moveto (XINT (x), XINT (y));
1963 #else
1964 #ifdef HAVE_GPM
1966 Fselect_frame (frame, Qnil);
1967 term_mouse_moveto (XINT (x), XINT (y));
1969 #endif
1970 #endif
1971 #endif
1973 return Qnil;
1976 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
1977 Sset_mouse_pixel_position, 3, 3, 0,
1978 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
1979 The position is given in pixels, where (0, 0) is the upper-left corner
1980 of the frame, X is the horizontal offset, and Y is the vertical offset.
1982 Note, this is a no-op for an X frame that is not visible.
1983 If you have just created a frame, you must wait for it to become visible
1984 before calling this function on it, like this.
1985 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
1986 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
1988 CHECK_LIVE_FRAME (frame);
1989 CHECK_TYPE_RANGED_INTEGER (int, x);
1990 CHECK_TYPE_RANGED_INTEGER (int, y);
1992 /* I think this should be done with a hook. */
1993 #ifdef HAVE_WINDOW_SYSTEM
1994 if (FRAME_WINDOW_P (XFRAME (frame)))
1995 /* Warping the mouse will cause enternotify and focus events. */
1996 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
1997 #else
1998 #if defined (MSDOS)
1999 if (FRAME_MSDOS_P (XFRAME (frame)))
2001 Fselect_frame (frame, Qnil);
2002 mouse_moveto (XINT (x), XINT (y));
2004 #else
2005 #ifdef HAVE_GPM
2007 Fselect_frame (frame, Qnil);
2008 term_mouse_moveto (XINT (x), XINT (y));
2010 #endif
2011 #endif
2012 #endif
2014 return Qnil;
2017 static void make_frame_visible_1 (Lisp_Object);
2019 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
2020 0, 1, "",
2021 doc: /* Make the frame FRAME visible (assuming it is an X window).
2022 If omitted, FRAME defaults to the currently selected frame. */)
2023 (Lisp_Object frame)
2025 struct frame *f = decode_live_frame (frame);
2027 /* I think this should be done with a hook. */
2028 #ifdef HAVE_WINDOW_SYSTEM
2029 if (FRAME_WINDOW_P (f))
2030 x_make_frame_visible (f);
2031 #endif
2033 make_frame_visible_1 (f->root_window);
2035 /* Make menu bar update for the Buffers and Frames menus. */
2036 /* windows_or_buffers_changed = 15; FIXME: Why? */
2038 XSETFRAME (frame, f);
2039 return frame;
2042 /* Update the display_time slot of the buffers shown in WINDOW
2043 and all its descendants. */
2045 static void
2046 make_frame_visible_1 (Lisp_Object window)
2048 struct window *w;
2050 for (; !NILP (window); window = w->next)
2052 w = XWINDOW (window);
2053 if (WINDOWP (w->contents))
2054 make_frame_visible_1 (w->contents);
2055 else
2056 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2060 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2061 0, 2, "",
2062 doc: /* Make the frame FRAME invisible.
2063 If omitted, FRAME defaults to the currently selected frame.
2064 On graphical displays, invisible frames are not updated and are
2065 usually not displayed at all, even in a window system's \"taskbar\".
2067 Normally you may not make FRAME invisible if all other frames are invisible,
2068 but if the second optional argument FORCE is non-nil, you may do so.
2070 This function has no effect on text terminal frames. Such frames are
2071 always considered visible, whether or not they are currently being
2072 displayed in the terminal. */)
2073 (Lisp_Object frame, Lisp_Object force)
2075 struct frame *f = decode_live_frame (frame);
2077 if (NILP (force) && !other_visible_frames (f))
2078 error ("Attempt to make invisible the sole visible or iconified frame");
2080 /* Don't allow minibuf_window to remain on an invisible frame. */
2081 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2083 /* I think this should be done with a hook. */
2084 #ifdef HAVE_WINDOW_SYSTEM
2085 if (FRAME_WINDOW_P (f))
2086 x_make_frame_invisible (f);
2087 #endif
2089 /* Make menu bar update for the Buffers and Frames menus. */
2090 windows_or_buffers_changed = 16;
2092 return Qnil;
2095 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2096 0, 1, "",
2097 doc: /* Make the frame FRAME into an icon.
2098 If omitted, FRAME defaults to the currently selected frame. */)
2099 (Lisp_Object frame)
2101 struct frame *f = decode_live_frame (frame);
2103 /* Don't allow minibuf_window to remain on an iconified frame. */
2104 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2106 /* I think this should be done with a hook. */
2107 #ifdef HAVE_WINDOW_SYSTEM
2108 if (FRAME_WINDOW_P (f))
2109 x_iconify_frame (f);
2110 #endif
2112 /* Make menu bar update for the Buffers and Frames menus. */
2113 windows_or_buffers_changed = 17;
2115 return Qnil;
2118 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2119 1, 1, 0,
2120 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2121 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2122 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2123 On graphical displays, invisible frames are not updated and are
2124 usually not displayed at all, even in a window system's \"taskbar\".
2126 If FRAME is a text terminal frame, this always returns t.
2127 Such frames are always considered visible, whether or not they are
2128 currently being displayed on the terminal. */)
2129 (Lisp_Object frame)
2131 CHECK_LIVE_FRAME (frame);
2133 if (FRAME_VISIBLE_P (XFRAME (frame)))
2134 return Qt;
2135 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2136 return Qicon;
2137 return Qnil;
2140 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2141 0, 0, 0,
2142 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2143 (void)
2145 Lisp_Object tail, frame, value = Qnil;
2147 FOR_EACH_FRAME (tail, frame)
2148 if (FRAME_VISIBLE_P (XFRAME (frame)))
2149 value = Fcons (frame, value);
2151 return value;
2155 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2156 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2157 If FRAME is invisible or iconified, make it visible.
2158 If you don't specify a frame, the selected frame is used.
2159 If Emacs is displaying on an ordinary terminal or some other device which
2160 doesn't support multiple overlapping frames, this function selects FRAME. */)
2161 (Lisp_Object frame)
2163 struct frame *f = decode_live_frame (frame);
2165 XSETFRAME (frame, f);
2167 if (FRAME_TERMCAP_P (f))
2168 /* On a text terminal select FRAME. */
2169 Fselect_frame (frame, Qnil);
2170 else
2171 /* Do like the documentation says. */
2172 Fmake_frame_visible (frame);
2174 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2175 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2177 return Qnil;
2180 /* Should we have a corresponding function called Flower_Power? */
2181 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2182 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2183 If you don't specify a frame, the selected frame is used.
2184 If Emacs is displaying on an ordinary terminal or some other device which
2185 doesn't support multiple overlapping frames, this function does nothing. */)
2186 (Lisp_Object frame)
2188 struct frame *f = decode_live_frame (frame);
2190 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2191 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2193 return Qnil;
2197 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2198 1, 2, 0,
2199 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2200 In other words, switch-frame events caused by events in FRAME will
2201 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2202 FOCUS-FRAME after reading an event typed at FRAME.
2204 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2205 frame again receives its own keystrokes.
2207 Focus redirection is useful for temporarily redirecting keystrokes to
2208 a surrogate minibuffer frame when a frame doesn't have its own
2209 minibuffer window.
2211 A frame's focus redirection can be changed by `select-frame'. If frame
2212 FOO is selected, and then a different frame BAR is selected, any
2213 frames redirecting their focus to FOO are shifted to redirect their
2214 focus to BAR. This allows focus redirection to work properly when the
2215 user switches from one frame to another using `select-window'.
2217 This means that a frame whose focus is redirected to itself is treated
2218 differently from a frame whose focus is redirected to nil; the former
2219 is affected by `select-frame', while the latter is not.
2221 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2222 (Lisp_Object frame, Lisp_Object focus_frame)
2224 /* Note that we don't check for a live frame here. It's reasonable
2225 to redirect the focus of a frame you're about to delete, if you
2226 know what other frame should receive those keystrokes. */
2227 struct frame *f = decode_any_frame (frame);
2229 if (! NILP (focus_frame))
2230 CHECK_LIVE_FRAME (focus_frame);
2232 fset_focus_frame (f, focus_frame);
2234 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2235 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2237 return Qnil;
2241 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2242 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2243 If FRAME is omitted or nil, the selected frame is used.
2244 Return nil if FRAME's focus is not redirected.
2245 See `redirect-frame-focus'. */)
2246 (Lisp_Object frame)
2248 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2251 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
2252 doc: /* Set the input focus to FRAME.
2253 FRAME nil means use the selected frame.
2254 If there is no window system support, this function does nothing. */)
2255 (Lisp_Object frame)
2257 #ifdef HAVE_WINDOW_SYSTEM
2258 x_focus_frame (decode_window_system_frame (frame));
2259 #endif
2260 return Qnil;
2263 DEFUN ("frame-can-run-window-configuration-change-hook",
2264 Fcan_run_window_configuration_change_hook,
2265 Scan_run_window_configuration_change_hook, 2, 2, 0,
2266 doc: /* Whether `window-configuration-change-hook' is run for frame FRAME.
2267 FRAME nil means use the selected frame. Second argument ALLOW non-nil
2268 means functions on `window-configuration-change-hook' are called
2269 whenever the window configuration of FRAME changes. ALLOW nil means
2270 these functions are not called.
2272 This function is currently called by `face-set-after-frame-default' only
2273 and should be otherwise used with utter care to avoid that running
2274 functions on `window-configuration-change-hook' is impeded forever. */)
2275 (Lisp_Object frame, Lisp_Object allow)
2277 struct frame *f = decode_live_frame (frame);
2279 f->can_run_window_configuration_change_hook = NILP (allow) ? false : true;
2280 return Qnil;
2284 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2286 void
2287 frames_discard_buffer (Lisp_Object buffer)
2289 Lisp_Object frame, tail;
2291 FOR_EACH_FRAME (tail, frame)
2293 fset_buffer_list
2294 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2295 fset_buried_buffer_list
2296 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2300 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2301 If the alist already has an element for PROP, we change it. */
2303 void
2304 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2306 register Lisp_Object tem;
2308 tem = Fassq (prop, *alistptr);
2309 if (EQ (tem, Qnil))
2310 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2311 else
2312 Fsetcdr (tem, val);
2315 static int
2316 frame_name_fnn_p (char *str, ptrdiff_t len)
2318 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2320 char *p = str + 2;
2321 while ('0' <= *p && *p <= '9')
2322 p++;
2323 if (p == str + len)
2324 return 1;
2326 return 0;
2329 /* Set the name of the terminal frame. Also used by MSDOS frames.
2330 Modeled after x_set_name which is used for WINDOW frames. */
2332 static void
2333 set_term_frame_name (struct frame *f, Lisp_Object name)
2335 f->explicit_name = ! NILP (name);
2337 /* If NAME is nil, set the name to F<num>. */
2338 if (NILP (name))
2340 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2342 /* Check for no change needed in this very common case
2343 before we do any consing. */
2344 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2345 return;
2347 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2349 else
2351 CHECK_STRING (name);
2353 /* Don't change the name if it's already NAME. */
2354 if (! NILP (Fstring_equal (name, f->name)))
2355 return;
2357 /* Don't allow the user to set the frame name to F<num>, so it
2358 doesn't clash with the names we generate for terminal frames. */
2359 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2360 error ("Frame names of the form F<num> are usurped by Emacs");
2363 fset_name (f, name);
2364 update_mode_lines = 16;
2367 void
2368 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2370 register Lisp_Object old_alist_elt;
2372 /* The buffer-list parameters are stored in a special place and not
2373 in the alist. All buffers must be live. */
2374 if (EQ (prop, Qbuffer_list))
2376 Lisp_Object list = Qnil;
2377 for (; CONSP (val); val = XCDR (val))
2378 if (!NILP (Fbuffer_live_p (XCAR (val))))
2379 list = Fcons (XCAR (val), list);
2380 fset_buffer_list (f, Fnreverse (list));
2381 return;
2383 if (EQ (prop, Qburied_buffer_list))
2385 Lisp_Object list = Qnil;
2386 for (; CONSP (val); val = XCDR (val))
2387 if (!NILP (Fbuffer_live_p (XCAR (val))))
2388 list = Fcons (XCAR (val), list);
2389 fset_buried_buffer_list (f, Fnreverse (list));
2390 return;
2393 /* If PROP is a symbol which is supposed to have frame-local values,
2394 and it is set up based on this frame, switch to the global
2395 binding. That way, we can create or alter the frame-local binding
2396 without messing up the symbol's status. */
2397 if (SYMBOLP (prop))
2399 struct Lisp_Symbol *sym = XSYMBOL (prop);
2400 start:
2401 switch (sym->redirect)
2403 case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
2404 case SYMBOL_PLAINVAL: case SYMBOL_FORWARDED: break;
2405 case SYMBOL_LOCALIZED:
2406 { struct Lisp_Buffer_Local_Value *blv = sym->val.blv;
2407 if (blv->frame_local && blv_found (blv) && XFRAME (blv->where) == f)
2408 swap_in_global_binding (sym);
2409 break;
2411 default: emacs_abort ();
2415 /* The tty color needed to be set before the frame's parameter
2416 alist was updated with the new value. This is not true any more,
2417 but we still do this test early on. */
2418 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2419 && f == FRAME_TTY (f)->previous_frame)
2420 /* Force redisplay of this tty. */
2421 FRAME_TTY (f)->previous_frame = NULL;
2423 /* Update the frame parameter alist. */
2424 old_alist_elt = Fassq (prop, f->param_alist);
2425 if (EQ (old_alist_elt, Qnil))
2426 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2427 else
2428 Fsetcdr (old_alist_elt, val);
2430 /* Update some other special parameters in their special places
2431 in addition to the alist. */
2433 if (EQ (prop, Qbuffer_predicate))
2434 fset_buffer_predicate (f, val);
2436 if (! FRAME_WINDOW_P (f))
2438 if (EQ (prop, Qmenu_bar_lines))
2439 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2440 else if (EQ (prop, Qname))
2441 set_term_frame_name (f, val);
2444 if (EQ (prop, Qminibuffer) && WINDOWP (val))
2446 if (! MINI_WINDOW_P (XWINDOW (val)))
2447 error ("Surrogate minibuffer windows must be minibuffer windows");
2449 if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
2450 && !EQ (val, f->minibuffer_window))
2451 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
2453 /* Install the chosen minibuffer window, with proper buffer. */
2454 fset_minibuffer_window (f, val);
2458 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2459 is not an unspecified foreground or background color. */
2461 static Lisp_Object
2462 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
2464 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
2465 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
2466 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
2467 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
2470 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
2471 doc: /* Return the parameters-alist of frame FRAME.
2472 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2473 The meaningful PARMs depend on the kind of frame.
2474 If FRAME is omitted or nil, return information on the currently selected frame. */)
2475 (Lisp_Object frame)
2477 Lisp_Object alist;
2478 struct frame *f = decode_any_frame (frame);
2479 int height, width;
2480 struct gcpro gcpro1;
2482 if (!FRAME_LIVE_P (f))
2483 return Qnil;
2485 alist = Fcopy_alist (f->param_alist);
2486 GCPRO1 (alist);
2488 if (!FRAME_WINDOW_P (f))
2490 Lisp_Object elt;
2492 /* If the frame's parameter alist says the colors are
2493 unspecified and reversed, take the frame's background pixel
2494 for foreground and vice versa. */
2495 elt = Fassq (Qforeground_color, alist);
2496 if (CONSP (elt) && STRINGP (XCDR (elt)))
2498 elt = frame_unspecified_color (f, XCDR (elt));
2499 if (!NILP (elt))
2500 store_in_alist (&alist, Qforeground_color, elt);
2502 else
2503 store_in_alist (&alist, Qforeground_color,
2504 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
2505 elt = Fassq (Qbackground_color, alist);
2506 if (CONSP (elt) && STRINGP (XCDR (elt)))
2508 elt = frame_unspecified_color (f, XCDR (elt));
2509 if (!NILP (elt))
2510 store_in_alist (&alist, Qbackground_color, elt);
2512 else
2513 store_in_alist (&alist, Qbackground_color,
2514 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
2515 store_in_alist (&alist, intern ("font"),
2516 build_string (FRAME_MSDOS_P (f)
2517 ? "ms-dos"
2518 : FRAME_W32_P (f) ? "w32term"
2519 :"tty"));
2521 store_in_alist (&alist, Qname, f->name);
2522 height = (f->new_height
2523 ? (f->new_pixelwise
2524 ? (f->new_height / FRAME_LINE_HEIGHT (f))
2525 : f->new_height)
2526 : FRAME_LINES (f));
2527 store_in_alist (&alist, Qheight, make_number (height));
2528 width = (f->new_width
2529 ? (f->new_pixelwise
2530 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
2531 : f->new_width)
2532 : FRAME_COLS (f));
2533 store_in_alist (&alist, Qwidth, make_number (width));
2534 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
2535 store_in_alist (&alist, Qminibuffer,
2536 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
2537 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2538 : FRAME_MINIBUF_WINDOW (f)));
2539 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
2540 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
2541 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
2543 /* I think this should be done with a hook. */
2544 #ifdef HAVE_WINDOW_SYSTEM
2545 if (FRAME_WINDOW_P (f))
2546 x_report_frame_params (f, &alist);
2547 else
2548 #endif
2550 /* This ought to be correct in f->param_alist for an X frame. */
2551 Lisp_Object lines;
2552 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
2553 store_in_alist (&alist, Qmenu_bar_lines, lines);
2556 UNGCPRO;
2557 return alist;
2561 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
2562 doc: /* Return FRAME's value for parameter PARAMETER.
2563 If FRAME is nil, describe the currently selected frame. */)
2564 (Lisp_Object frame, Lisp_Object parameter)
2566 struct frame *f = decode_any_frame (frame);
2567 Lisp_Object value = Qnil;
2569 CHECK_SYMBOL (parameter);
2571 XSETFRAME (frame, f);
2573 if (FRAME_LIVE_P (f))
2575 /* Avoid consing in frequent cases. */
2576 if (EQ (parameter, Qname))
2577 value = f->name;
2578 #ifdef HAVE_X_WINDOWS
2579 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2580 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
2581 #endif /* HAVE_X_WINDOWS */
2582 else if (EQ (parameter, Qbackground_color)
2583 || EQ (parameter, Qforeground_color))
2585 value = Fassq (parameter, f->param_alist);
2586 if (CONSP (value))
2588 value = XCDR (value);
2589 /* Fframe_parameters puts the actual fg/bg color names,
2590 even if f->param_alist says otherwise. This is
2591 important when param_alist's notion of colors is
2592 "unspecified". We need to do the same here. */
2593 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2594 value = frame_unspecified_color (f, value);
2596 else
2597 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2599 else if (EQ (parameter, Qdisplay_type)
2600 || EQ (parameter, Qbackground_mode))
2601 value = Fcdr (Fassq (parameter, f->param_alist));
2602 else
2603 /* FIXME: Avoid this code path at all (as well as code duplication)
2604 by sharing more code with Fframe_parameters. */
2605 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2608 return value;
2612 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
2613 Smodify_frame_parameters, 2, 2, 0,
2614 doc: /* Modify the parameters of frame FRAME according to ALIST.
2615 If FRAME is nil, it defaults to the selected frame.
2616 ALIST is an alist of parameters to change and their new values.
2617 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
2618 The meaningful PARMs depend on the kind of frame.
2619 Undefined PARMs are ignored, but stored in the frame's parameter list
2620 so that `frame-parameters' will return them.
2622 The value of frame parameter FOO can also be accessed
2623 as a frame-local binding for the variable FOO, if you have
2624 enabled such bindings for that variable with `make-variable-frame-local'.
2625 Note that this functionality is obsolete as of Emacs 22.2, and its
2626 use is not recommended. Explicitly check for a frame-parameter instead. */)
2627 (Lisp_Object frame, Lisp_Object alist)
2629 struct frame *f = decode_live_frame (frame);
2630 register Lisp_Object prop, val;
2632 CHECK_LIST (alist);
2634 /* I think this should be done with a hook. */
2635 #ifdef HAVE_WINDOW_SYSTEM
2636 if (FRAME_WINDOW_P (f))
2637 x_set_frame_parameters (f, alist);
2638 else
2639 #endif
2640 #ifdef MSDOS
2641 if (FRAME_MSDOS_P (f))
2642 IT_set_frame_parameters (f, alist);
2643 else
2644 #endif
2647 EMACS_INT length = XFASTINT (Flength (alist));
2648 ptrdiff_t i;
2649 Lisp_Object *parms;
2650 Lisp_Object *values;
2651 USE_SAFE_ALLOCA;
2652 SAFE_ALLOCA_LISP (parms, 2 * length);
2653 values = parms + length;
2655 /* Extract parm names and values into those vectors. */
2657 for (i = 0; CONSP (alist); alist = XCDR (alist))
2659 Lisp_Object elt;
2661 elt = XCAR (alist);
2662 parms[i] = Fcar (elt);
2663 values[i] = Fcdr (elt);
2664 i++;
2667 /* Now process them in reverse of specified order. */
2668 while (--i >= 0)
2670 prop = parms[i];
2671 val = values[i];
2672 store_frame_param (f, prop, val);
2674 if (EQ (prop, Qforeground_color)
2675 || EQ (prop, Qbackground_color))
2676 update_face_from_frame_parameter (f, prop, val);
2679 SAFE_FREE ();
2681 return Qnil;
2684 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
2685 0, 1, 0,
2686 doc: /* Height in pixels of a line in the font in frame FRAME.
2687 If FRAME is omitted or nil, the selected frame is used.
2688 For a terminal frame, the value is always 1. */)
2689 (Lisp_Object frame)
2691 #ifdef HAVE_WINDOW_SYSTEM
2692 struct frame *f = decode_any_frame (frame);
2694 if (FRAME_WINDOW_P (f))
2695 return make_number (FRAME_LINE_HEIGHT (f));
2696 else
2697 #endif
2698 return make_number (1);
2702 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
2703 0, 1, 0,
2704 doc: /* Width in pixels of characters in the font in frame FRAME.
2705 If FRAME is omitted or nil, the selected frame is used.
2706 On a graphical screen, the width is the standard width of the default font.
2707 For a terminal screen, the value is always 1. */)
2708 (Lisp_Object frame)
2710 #ifdef HAVE_WINDOW_SYSTEM
2711 struct frame *f = decode_any_frame (frame);
2713 if (FRAME_WINDOW_P (f))
2714 return make_number (FRAME_COLUMN_WIDTH (f));
2715 else
2716 #endif
2717 return make_number (1);
2720 DEFUN ("frame-pixel-height", Fframe_pixel_height,
2721 Sframe_pixel_height, 0, 1, 0,
2722 doc: /* Return a FRAME's height in pixels.
2723 If FRAME is omitted or nil, the selected frame is used. The exact value
2724 of the result depends on the window-system and toolkit in use:
2726 In the Gtk+ version of Emacs, it includes only any window (including
2727 the minibuffer or echo area), mode line, and header line. It does not
2728 include the tool bar or menu bar.
2730 With other graphical versions, it also includes the tool bar and the
2731 menu bar.
2733 For a text terminal, it includes the menu bar. In this case, the
2734 result is really in characters rather than pixels (i.e., is identical
2735 to `frame-height'). */)
2736 (Lisp_Object frame)
2738 struct frame *f = decode_any_frame (frame);
2740 #ifdef HAVE_WINDOW_SYSTEM
2741 if (FRAME_WINDOW_P (f))
2742 return make_number (FRAME_PIXEL_HEIGHT (f));
2743 else
2744 #endif
2745 return make_number (FRAME_TOTAL_LINES (f));
2748 DEFUN ("frame-pixel-width", Fframe_pixel_width,
2749 Sframe_pixel_width, 0, 1, 0,
2750 doc: /* Return FRAME's width in pixels.
2751 For a terminal frame, the result really gives the width in characters.
2752 If FRAME is omitted or nil, the selected frame is used. */)
2753 (Lisp_Object frame)
2755 struct frame *f = decode_any_frame (frame);
2757 #ifdef HAVE_WINDOW_SYSTEM
2758 if (FRAME_WINDOW_P (f))
2759 return make_number (FRAME_PIXEL_WIDTH (f));
2760 else
2761 #endif
2762 return make_number (FRAME_TOTAL_COLS (f));
2765 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
2766 Stool_bar_pixel_width, 0, 1, 0,
2767 doc: /* Return width in pixels of FRAME's tool bar.
2768 The result is greater than zero only when the tool bar is on the left
2769 or right side of FRAME. If FRAME is omitted or nil, the selected frame
2770 is used. */)
2771 (Lisp_Object frame)
2773 #ifdef FRAME_TOOLBAR_WIDTH
2774 struct frame *f = decode_any_frame (frame);
2776 if (FRAME_WINDOW_P (f))
2777 return make_number (FRAME_TOOLBAR_WIDTH (f));
2778 #endif
2779 return make_number (0);
2782 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
2783 doc: /* Return width in columns of FRAME's text area. */)
2784 (Lisp_Object frame)
2786 return make_number (FRAME_COLS (decode_any_frame (frame)));
2789 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
2790 doc: /* Return height in lines of FRAME's text area. */)
2791 (Lisp_Object frame)
2793 return make_number (FRAME_LINES (decode_any_frame (frame)));
2796 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
2797 doc: /* Return number of total columns of FRAME. */)
2798 (Lisp_Object frame)
2800 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
2803 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
2804 doc: /* Return number of total lines of FRAME. */)
2805 (Lisp_Object frame)
2807 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
2810 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
2811 doc: /* Return text area width of FRAME in pixels. */)
2812 (Lisp_Object frame)
2814 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
2817 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
2818 doc: /* Return text area height of FRAME in pixels. */)
2819 (Lisp_Object frame)
2821 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
2824 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
2825 doc: /* Return scroll bar width of FRAME in pixels. */)
2826 (Lisp_Object frame)
2828 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
2831 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
2832 doc: /* Return scroll bar height of FRAME in pixels. */)
2833 (Lisp_Object frame)
2835 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
2838 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
2839 doc: /* Return fringe width of FRAME in pixels. */)
2840 (Lisp_Object frame)
2842 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
2845 DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0,
2846 doc: /* Return border width of FRAME in pixels. */)
2847 (Lisp_Object frame)
2849 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
2852 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
2853 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
2854 (Lisp_Object frame)
2856 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
2859 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
2860 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
2861 (Lisp_Object frame)
2863 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
2866 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
2867 doc: /* Set height of frame FRAME to HEIGHT lines.
2868 Optional third arg PRETEND non-nil means that redisplay should use
2869 HEIGHT lines but that the idea of the actual height of the frame should
2870 not be changed.
2872 Optional fourth argument PIXELWISE non-nil means that FRAME should be
2873 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
2874 window managers may refuse to honor a HEIGHT that is not an integer
2875 multiple of the default frame font height. */)
2876 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
2878 struct frame *f = decode_live_frame (frame);
2879 int pixel_height;
2881 CHECK_TYPE_RANGED_INTEGER (int, height);
2883 pixel_height = (!NILP (pixelwise)
2884 ? XINT (height)
2885 : XINT (height) * FRAME_LINE_HEIGHT (f));
2886 if (pixel_height != FRAME_TEXT_HEIGHT (f))
2887 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
2889 return Qnil;
2892 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
2893 doc: /* Set width of frame FRAME to WIDTH columns.
2894 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
2895 columns but that the idea of the actual width of the frame should not
2896 be changed.
2898 Optional fourth argument PIXELWISE non-nil means that FRAME should be
2899 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
2900 window managers may refuse to honor a WIDTH that is not an integer
2901 multiple of the default frame font width. */)
2902 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
2904 struct frame *f = decode_live_frame (frame);
2905 int pixel_width;
2907 CHECK_TYPE_RANGED_INTEGER (int, width);
2909 pixel_width = (!NILP (pixelwise)
2910 ? XINT (width)
2911 : XINT (width) * FRAME_COLUMN_WIDTH (f));
2912 if (pixel_width != FRAME_TEXT_WIDTH (f))
2913 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
2915 return Qnil;
2918 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
2919 doc: /* Set size of FRAME to WIDTH by HEIGHT, measured in characters.
2920 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
2921 When `frame-resize-pixelwise' is nil, some window managers may refuse to
2922 honor a WIDTH that is not an integer multiple of the default frame font
2923 width or a HEIGHT that is not an integer multiple of the default frame
2924 font height. */)
2925 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
2927 struct frame *f = decode_live_frame (frame);
2928 int pixel_width, pixel_height;
2930 CHECK_TYPE_RANGED_INTEGER (int, width);
2931 CHECK_TYPE_RANGED_INTEGER (int, height);
2933 pixel_width = (!NILP (pixelwise)
2934 ? XINT (width)
2935 : XINT (width) * FRAME_COLUMN_WIDTH (f));
2936 pixel_height = (!NILP (pixelwise)
2937 ? XINT (height)
2938 : XINT (height) * FRAME_LINE_HEIGHT (f));
2940 if (pixel_width != FRAME_TEXT_WIDTH (f)
2941 || pixel_height != FRAME_TEXT_HEIGHT (f))
2942 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
2944 return Qnil;
2947 DEFUN ("set-frame-position", Fset_frame_position,
2948 Sset_frame_position, 3, 3, 0,
2949 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2950 If FRAME is nil, the selected frame is used. XOFFSET and YOFFSET are
2951 actually the position of the upper left corner of the frame. Negative
2952 values for XOFFSET or YOFFSET are interpreted relative to the rightmost
2953 or bottommost possible position (that stays within the screen). */)
2954 (Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
2956 register struct frame *f = decode_live_frame (frame);
2958 CHECK_TYPE_RANGED_INTEGER (int, xoffset);
2959 CHECK_TYPE_RANGED_INTEGER (int, yoffset);
2961 /* I think this should be done with a hook. */
2962 #ifdef HAVE_WINDOW_SYSTEM
2963 if (FRAME_WINDOW_P (f))
2964 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
2965 #endif
2967 return Qt;
2971 /***********************************************************************
2972 Frame Parameters
2973 ***********************************************************************/
2975 /* Connect the frame-parameter names for X frames
2976 to the ways of passing the parameter values to the window system.
2978 The name of a parameter, as a Lisp symbol,
2979 has an `x-frame-parameter' property which is an integer in Lisp
2980 that is an index in this table. */
2982 struct frame_parm_table {
2983 const char *name;
2984 Lisp_Object *variable;
2987 static const struct frame_parm_table frame_parms[] =
2989 {"auto-raise", &Qauto_raise},
2990 {"auto-lower", &Qauto_lower},
2991 {"background-color", 0},
2992 {"border-color", &Qborder_color},
2993 {"border-width", &Qborder_width},
2994 {"cursor-color", &Qcursor_color},
2995 {"cursor-type", &Qcursor_type},
2996 {"font", 0},
2997 {"foreground-color", 0},
2998 {"icon-name", &Qicon_name},
2999 {"icon-type", &Qicon_type},
3000 {"internal-border-width", &Qinternal_border_width},
3001 {"right-divider-width", &Qright_divider_width},
3002 {"bottom-divider-width", &Qbottom_divider_width},
3003 {"menu-bar-lines", &Qmenu_bar_lines},
3004 {"mouse-color", &Qmouse_color},
3005 {"name", &Qname},
3006 {"scroll-bar-width", &Qscroll_bar_width},
3007 {"scroll-bar-height", &Qscroll_bar_height},
3008 {"title", &Qtitle},
3009 {"unsplittable", &Qunsplittable},
3010 {"vertical-scroll-bars", &Qvertical_scroll_bars},
3011 {"horizontal-scroll-bars", &Qhorizontal_scroll_bars},
3012 {"visibility", &Qvisibility},
3013 {"tool-bar-lines", &Qtool_bar_lines},
3014 {"scroll-bar-foreground", &Qscroll_bar_foreground},
3015 {"scroll-bar-background", &Qscroll_bar_background},
3016 {"screen-gamma", &Qscreen_gamma},
3017 {"line-spacing", &Qline_spacing},
3018 {"left-fringe", &Qleft_fringe},
3019 {"right-fringe", &Qright_fringe},
3020 {"wait-for-wm", &Qwait_for_wm},
3021 {"fullscreen", &Qfullscreen},
3022 {"font-backend", &Qfont_backend},
3023 {"alpha", &Qalpha},
3024 {"sticky", &Qsticky},
3025 {"tool-bar-position", &Qtool_bar_position},
3028 #ifdef HAVE_WINDOW_SYSTEM
3030 /* Change the parameters of frame F as specified by ALIST.
3031 If a parameter is not specially recognized, do nothing special;
3032 otherwise call the `x_set_...' function for that parameter.
3033 Except for certain geometry properties, always call store_frame_param
3034 to store the new value in the parameter alist. */
3036 void
3037 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3039 Lisp_Object tail;
3041 /* If both of these parameters are present, it's more efficient to
3042 set them both at once. So we wait until we've looked at the
3043 entire list before we set them. */
3044 int width IF_LINT (= 0), height IF_LINT (= 0);
3045 bool width_change = 0, height_change = 0;
3047 /* Same here. */
3048 Lisp_Object left, top;
3050 /* Same with these. */
3051 Lisp_Object icon_left, icon_top;
3053 /* Record in these vectors all the parms specified. */
3054 Lisp_Object *parms;
3055 Lisp_Object *values;
3056 ptrdiff_t i, p;
3057 bool left_no_change = 0, top_no_change = 0;
3058 #ifdef HAVE_X_WINDOWS
3059 bool icon_left_no_change = 0, icon_top_no_change = 0;
3060 #endif
3062 i = 0;
3063 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3064 i++;
3066 USE_SAFE_ALLOCA;
3067 SAFE_ALLOCA_LISP (parms, 2 * i);
3068 values = parms + i;
3070 /* Extract parm names and values into those vectors. */
3072 i = 0;
3073 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3075 Lisp_Object elt;
3077 elt = XCAR (tail);
3078 parms[i] = Fcar (elt);
3079 values[i] = Fcdr (elt);
3080 i++;
3082 /* TAIL and ALIST are not used again below here. */
3083 alist = tail = Qnil;
3085 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
3086 because their values appear in VALUES and strings are not valid. */
3087 top = left = Qunbound;
3088 icon_left = icon_top = Qunbound;
3090 /* Process foreground_color and background_color before anything else.
3091 They are independent of other properties, but other properties (e.g.,
3092 cursor_color) are dependent upon them. */
3093 /* Process default font as well, since fringe widths depends on it. */
3094 for (p = 0; p < i; p++)
3096 Lisp_Object prop, val;
3098 prop = parms[p];
3099 val = values[p];
3100 if (EQ (prop, Qforeground_color)
3101 || EQ (prop, Qbackground_color)
3102 || EQ (prop, Qfont))
3104 register Lisp_Object param_index, old_value;
3106 old_value = get_frame_param (f, prop);
3107 if (NILP (Fequal (val, old_value)))
3109 store_frame_param (f, prop, val);
3111 param_index = Fget (prop, Qx_frame_parameter);
3112 if (NATNUMP (param_index)
3113 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3114 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3115 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3120 /* Now process them in reverse of specified order. */
3121 while (i-- != 0)
3123 Lisp_Object prop, val;
3125 prop = parms[i];
3126 val = values[i];
3128 if (EQ (prop, Qwidth) && RANGED_INTEGERP (0, val, INT_MAX))
3130 width_change = 1;
3131 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3133 else if (EQ (prop, Qheight) && RANGED_INTEGERP (0, val, INT_MAX))
3135 height_change = 1;
3136 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3138 else if (EQ (prop, Qtop))
3139 top = val;
3140 else if (EQ (prop, Qleft))
3141 left = val;
3142 else if (EQ (prop, Qicon_top))
3143 icon_top = val;
3144 else if (EQ (prop, Qicon_left))
3145 icon_left = val;
3146 else if (EQ (prop, Qforeground_color)
3147 || EQ (prop, Qbackground_color)
3148 || EQ (prop, Qfont))
3149 /* Processed above. */
3150 continue;
3151 else
3153 register Lisp_Object param_index, old_value;
3155 old_value = get_frame_param (f, prop);
3157 store_frame_param (f, prop, val);
3159 param_index = Fget (prop, Qx_frame_parameter);
3160 if (NATNUMP (param_index)
3161 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3162 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3163 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3167 /* Don't die if just one of these was set. */
3168 if (EQ (left, Qunbound))
3170 left_no_change = 1;
3171 if (f->left_pos < 0)
3172 left = list2 (Qplus, make_number (f->left_pos));
3173 else
3174 XSETINT (left, f->left_pos);
3176 if (EQ (top, Qunbound))
3178 top_no_change = 1;
3179 if (f->top_pos < 0)
3180 top = list2 (Qplus, make_number (f->top_pos));
3181 else
3182 XSETINT (top, f->top_pos);
3185 /* If one of the icon positions was not set, preserve or default it. */
3186 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3188 #ifdef HAVE_X_WINDOWS
3189 icon_left_no_change = 1;
3190 #endif
3191 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3192 if (NILP (icon_left))
3193 XSETINT (icon_left, 0);
3195 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3197 #ifdef HAVE_X_WINDOWS
3198 icon_top_no_change = 1;
3199 #endif
3200 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3201 if (NILP (icon_top))
3202 XSETINT (icon_top, 0);
3205 /* Don't set these parameters unless they've been explicitly
3206 specified. The window might be mapped or resized while we're in
3207 this function, and we don't want to override that unless the lisp
3208 code has asked for it.
3210 Don't set these parameters unless they actually differ from the
3211 window's current parameters; the window may not actually exist
3212 yet. */
3214 Lisp_Object frame;
3216 XSETFRAME (frame, f);
3218 if ((width_change && width != FRAME_TEXT_WIDTH (f))
3219 || (height_change && height != FRAME_TEXT_HEIGHT (f))
3220 || f->new_height || f->new_width)
3222 /* If necessary provide default values for HEIGHT and WIDTH. Do
3223 that here since otherwise a size change implied by an
3224 intermittent font change may get lost as in Bug#17142. */
3225 if (!width_change)
3226 width = (f->new_width
3227 ? (f->new_pixelwise
3228 ? f->new_width
3229 : (f->new_width * FRAME_COLUMN_WIDTH (f)))
3230 : FRAME_TEXT_WIDTH (f));
3232 if (!height_change)
3233 height = (f->new_height
3234 ? (f->new_pixelwise
3235 ? f->new_height
3236 : (f->new_height * FRAME_LINE_HEIGHT (f)))
3237 : FRAME_TEXT_HEIGHT (f));
3239 Fset_frame_size (frame, make_number (width), make_number (height), Qt);
3242 if ((!NILP (left) || !NILP (top))
3243 && ! (left_no_change && top_no_change)
3244 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3245 && NUMBERP (top) && XINT (top) == f->top_pos))
3247 int leftpos = 0;
3248 int toppos = 0;
3250 /* Record the signs. */
3251 f->size_hint_flags &= ~ (XNegative | YNegative);
3252 if (EQ (left, Qminus))
3253 f->size_hint_flags |= XNegative;
3254 else if (TYPE_RANGED_INTEGERP (int, left))
3256 leftpos = XINT (left);
3257 if (leftpos < 0)
3258 f->size_hint_flags |= XNegative;
3260 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3261 && CONSP (XCDR (left))
3262 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3264 leftpos = - XINT (XCAR (XCDR (left)));
3265 f->size_hint_flags |= XNegative;
3267 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3268 && CONSP (XCDR (left))
3269 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3271 leftpos = XINT (XCAR (XCDR (left)));
3274 if (EQ (top, Qminus))
3275 f->size_hint_flags |= YNegative;
3276 else if (TYPE_RANGED_INTEGERP (int, top))
3278 toppos = XINT (top);
3279 if (toppos < 0)
3280 f->size_hint_flags |= YNegative;
3282 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3283 && CONSP (XCDR (top))
3284 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3286 toppos = - XINT (XCAR (XCDR (top)));
3287 f->size_hint_flags |= YNegative;
3289 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3290 && CONSP (XCDR (top))
3291 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
3293 toppos = XINT (XCAR (XCDR (top)));
3297 /* Store the numeric value of the position. */
3298 f->top_pos = toppos;
3299 f->left_pos = leftpos;
3301 f->win_gravity = NorthWestGravity;
3303 /* Actually set that position, and convert to absolute. */
3304 x_set_offset (f, leftpos, toppos, -1);
3306 #ifdef HAVE_X_WINDOWS
3307 if ((!NILP (icon_left) || !NILP (icon_top))
3308 && ! (icon_left_no_change && icon_top_no_change))
3309 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3310 #endif /* HAVE_X_WINDOWS */
3313 SAFE_FREE ();
3317 /* Insert a description of internally-recorded parameters of frame X
3318 into the parameter alist *ALISTPTR that is to be given to the user.
3319 Only parameters that are specific to the X window system
3320 and whose values are not correctly recorded in the frame's
3321 param_alist need to be considered here. */
3323 void
3324 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
3326 Lisp_Object tem;
3327 uprintmax_t w;
3328 char buf[INT_BUFSIZE_BOUND (w)];
3330 /* Represent negative positions (off the top or left screen edge)
3331 in a way that Fmodify_frame_parameters will understand correctly. */
3332 XSETINT (tem, f->left_pos);
3333 if (f->left_pos >= 0)
3334 store_in_alist (alistptr, Qleft, tem);
3335 else
3336 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
3338 XSETINT (tem, f->top_pos);
3339 if (f->top_pos >= 0)
3340 store_in_alist (alistptr, Qtop, tem);
3341 else
3342 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
3344 store_in_alist (alistptr, Qborder_width,
3345 make_number (f->border_width));
3346 store_in_alist (alistptr, Qinternal_border_width,
3347 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
3348 store_in_alist (alistptr, Qright_divider_width,
3349 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
3350 store_in_alist (alistptr, Qbottom_divider_width,
3351 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
3352 store_in_alist (alistptr, Qleft_fringe,
3353 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
3354 store_in_alist (alistptr, Qright_fringe,
3355 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
3356 store_in_alist (alistptr, Qscroll_bar_width,
3357 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3358 ? make_number (0)
3359 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3360 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
3361 /* nil means "use default width"
3362 for non-toolkit scroll bar.
3363 ruler-mode.el depends on this. */
3364 : Qnil));
3365 store_in_alist (alistptr, Qscroll_bar_height,
3366 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
3367 ? make_number (0)
3368 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
3369 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
3370 /* nil means "use default height"
3371 for non-toolkit scroll bar. */
3372 : Qnil));
3373 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
3374 MS-Windows it returns a value whose type is HANDLE, which is
3375 actually a pointer. Explicit casting avoids compiler
3376 warnings. */
3377 w = (uintptr_t) FRAME_X_WINDOW (f);
3378 store_in_alist (alistptr, Qwindow_id,
3379 make_formatted_string (buf, "%"pMu, w));
3380 #ifdef HAVE_X_WINDOWS
3381 #ifdef USE_X_TOOLKIT
3382 /* Tooltip frame may not have this widget. */
3383 if (FRAME_X_OUTPUT (f)->widget)
3384 #endif
3385 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
3386 store_in_alist (alistptr, Qouter_window_id,
3387 make_formatted_string (buf, "%"pMu, w));
3388 #endif
3389 store_in_alist (alistptr, Qicon_name, f->icon_name);
3390 store_in_alist (alistptr, Qvisibility,
3391 (FRAME_VISIBLE_P (f) ? Qt
3392 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3393 store_in_alist (alistptr, Qdisplay,
3394 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
3396 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
3397 tem = Qnil;
3398 else
3399 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
3400 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
3401 store_in_alist (alistptr, Qparent_id, tem);
3402 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
3406 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3407 the previous value of that parameter, NEW_VALUE is the new value. */
3409 void
3410 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3412 if (NILP (new_value))
3413 f->want_fullscreen = FULLSCREEN_NONE;
3414 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
3415 f->want_fullscreen = FULLSCREEN_BOTH;
3416 else if (EQ (new_value, Qfullwidth))
3417 f->want_fullscreen = FULLSCREEN_WIDTH;
3418 else if (EQ (new_value, Qfullheight))
3419 f->want_fullscreen = FULLSCREEN_HEIGHT;
3420 else if (EQ (new_value, Qmaximized))
3421 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
3423 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
3424 FRAME_TERMINAL (f)->fullscreen_hook (f);
3428 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3429 the previous value of that parameter, NEW_VALUE is the new value. */
3431 void
3432 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3434 if (NILP (new_value))
3435 f->extra_line_spacing = 0;
3436 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
3437 f->extra_line_spacing = XFASTINT (new_value);
3438 else if (FLOATP (new_value))
3440 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
3442 if (new_spacing >= 0)
3443 f->extra_line_spacing = new_spacing;
3444 else
3445 signal_error ("Invalid line-spacing", new_value);
3447 else
3448 signal_error ("Invalid line-spacing", new_value);
3449 if (FRAME_VISIBLE_P (f))
3450 redraw_frame (f);
3454 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3455 the previous value of that parameter, NEW_VALUE is the new value. */
3457 void
3458 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3460 Lisp_Object bgcolor;
3462 if (NILP (new_value))
3463 f->gamma = 0;
3464 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
3465 /* The value 0.4545 is the normal viewing gamma. */
3466 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
3467 else
3468 signal_error ("Invalid screen-gamma", new_value);
3470 /* Apply the new gamma value to the frame background. */
3471 bgcolor = Fassq (Qbackground_color, f->param_alist);
3472 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3474 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
3475 if (NATNUMP (parm_index)
3476 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
3477 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3478 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3479 (f, bgcolor, Qnil);
3482 Fclear_face_cache (Qnil);
3486 void
3487 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3489 Lisp_Object font_object;
3490 int fontset = -1;
3491 #ifdef HAVE_X_WINDOWS
3492 Lisp_Object font_param = arg;
3493 #endif
3495 /* Set the frame parameter back to the old value because we may
3496 fail to use ARG as the new parameter value. */
3497 store_frame_param (f, Qfont, oldval);
3499 /* ARG is a fontset name, a font name, a cons of fontset name and a
3500 font object, or a font object. In the last case, this function
3501 never fail. */
3502 if (STRINGP (arg))
3504 fontset = fs_query_fontset (arg, 0);
3505 if (fontset < 0)
3507 font_object = font_open_by_name (f, arg);
3508 if (NILP (font_object))
3509 error ("Font `%s' is not defined", SSDATA (arg));
3510 arg = AREF (font_object, FONT_NAME_INDEX);
3512 else if (fontset > 0)
3514 font_object = font_open_by_name (f, fontset_ascii (fontset));
3515 if (NILP (font_object))
3516 error ("Font `%s' is not defined", SDATA (arg));
3517 arg = AREF (font_object, FONT_NAME_INDEX);
3519 else
3520 error ("The default fontset can't be used for a frame font");
3522 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
3524 /* This is the case that the ASCII font of F's fontset XCAR
3525 (arg) is changed to the font XCDR (arg) by
3526 `set-fontset-font'. */
3527 fontset = fs_query_fontset (XCAR (arg), 0);
3528 if (fontset < 0)
3529 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
3530 font_object = XCDR (arg);
3531 arg = AREF (font_object, FONT_NAME_INDEX);
3532 #ifdef HAVE_X_WINDOWS
3533 font_param = Ffont_get (font_object, QCname);
3534 #endif
3536 else if (FONT_OBJECT_P (arg))
3538 font_object = arg;
3539 #ifdef HAVE_X_WINDOWS
3540 font_param = Ffont_get (font_object, QCname);
3541 #endif
3542 /* This is to store the XLFD font name in the frame parameter for
3543 backward compatibility. We should store the font-object
3544 itself in the future. */
3545 arg = AREF (font_object, FONT_NAME_INDEX);
3546 fontset = FRAME_FONTSET (f);
3547 /* Check if we can use the current fontset. If not, set FONTSET
3548 to -1 to generate a new fontset from FONT-OBJECT. */
3549 if (fontset >= 0)
3551 Lisp_Object ascii_font = fontset_ascii (fontset);
3552 Lisp_Object spec = font_spec_from_name (ascii_font);
3554 if (NILP (spec))
3555 signal_error ("Invalid font name", ascii_font);
3557 if (! font_match_p (spec, font_object))
3558 fontset = -1;
3561 else
3562 signal_error ("Invalid font", arg);
3564 if (! NILP (Fequal (font_object, oldval)))
3565 return;
3567 x_new_font (f, font_object, fontset);
3568 store_frame_param (f, Qfont, arg);
3569 #ifdef HAVE_X_WINDOWS
3570 store_frame_param (f, Qfont_param, font_param);
3571 #endif
3572 /* Recalculate toolbar height. */
3573 f->n_tool_bar_rows = 0;
3575 /* Ensure we redraw it. */
3576 clear_current_matrices (f);
3578 /* Attempt to hunt down bug#16028. */
3579 SET_FRAME_GARBAGED (f);
3581 recompute_basic_faces (f);
3583 do_pending_window_change (0);
3585 /* We used to call face-set-after-frame-default here, but it leads to
3586 recursive calls (since that function can set the `default' face's
3587 font which in turns changes the frame's `font' parameter).
3588 Also I don't know what this call is meant to do, but it seems the
3589 wrong way to do it anyway (it does a lot more work than what seems
3590 reasonable in response to a change to `font'). */
3594 void
3595 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3597 if (! NILP (new_value)
3598 && !CONSP (new_value))
3600 char *p0, *p1;
3602 CHECK_STRING (new_value);
3603 p0 = p1 = SSDATA (new_value);
3604 new_value = Qnil;
3605 while (*p0)
3607 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
3608 if (p0 < p1)
3609 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
3610 new_value);
3611 if (*p1)
3613 int c;
3615 while ((c = *++p1) && c_isspace (c));
3617 p0 = p1;
3619 new_value = Fnreverse (new_value);
3622 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
3623 return;
3625 if (FRAME_FONT (f))
3626 free_all_realized_faces (Qnil);
3628 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
3629 if (NILP (new_value))
3631 if (NILP (old_value))
3632 error ("No font backend available");
3633 font_update_drivers (f, old_value);
3634 error ("None of specified font backends are available");
3636 store_frame_param (f, Qfont_backend, new_value);
3638 if (FRAME_FONT (f))
3640 Lisp_Object frame;
3642 XSETFRAME (frame, f);
3643 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
3644 ++face_change_count;
3645 windows_or_buffers_changed = 18;
3649 void
3650 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3652 int unit = FRAME_COLUMN_WIDTH (f);
3653 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
3654 int new_width;
3656 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3657 ? eabs (XINT (new_value)) : 8);
3659 if (new_width != old_width)
3661 FRAME_LEFT_FRINGE_WIDTH (f) = new_width;
3662 FRAME_FRINGE_COLS (f) /* Round up. */
3663 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
3665 if (FRAME_X_WINDOW (f) != 0)
3666 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
3668 SET_FRAME_GARBAGED (f);
3673 void
3674 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3676 int unit = FRAME_COLUMN_WIDTH (f);
3677 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
3678 int new_width;
3680 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3681 ? eabs (XINT (new_value)) : 8);
3683 if (new_width != old_width)
3685 FRAME_RIGHT_FRINGE_WIDTH (f) = new_width;
3686 FRAME_FRINGE_COLS (f) /* Round up. */
3687 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
3689 if (FRAME_X_WINDOW (f) != 0)
3690 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
3692 SET_FRAME_GARBAGED (f);
3697 void
3698 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3700 CHECK_TYPE_RANGED_INTEGER (int, arg);
3702 if (XINT (arg) == f->border_width)
3703 return;
3705 if (FRAME_X_WINDOW (f) != 0)
3706 error ("Cannot change the border width of a frame");
3708 f->border_width = XINT (arg);
3711 void
3712 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3714 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
3716 CHECK_TYPE_RANGED_INTEGER (int, arg);
3717 FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg);
3718 if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0)
3719 FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
3720 if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old)
3722 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
3723 adjust_frame_glyphs (f);
3724 SET_FRAME_GARBAGED (f);
3729 void
3730 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3732 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
3734 CHECK_TYPE_RANGED_INTEGER (int, arg);
3735 FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg);
3736 if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0)
3737 FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
3738 if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old)
3740 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
3741 adjust_frame_glyphs (f);
3742 SET_FRAME_GARBAGED (f);
3746 void
3747 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
3749 Lisp_Object frame;
3750 XSETFRAME (frame, f);
3752 if (NILP (value))
3753 Fmake_frame_invisible (frame, Qt);
3754 else if (EQ (value, Qicon))
3755 Ficonify_frame (frame);
3756 else
3757 Fmake_frame_visible (frame);
3760 void
3761 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3763 f->auto_raise = !EQ (Qnil, arg);
3766 void
3767 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3769 f->auto_lower = !EQ (Qnil, arg);
3772 void
3773 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3775 f->no_split = !NILP (arg);
3778 void
3779 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3781 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3782 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3783 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3784 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3786 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3787 = (NILP (arg)
3788 ? vertical_scroll_bar_none
3789 : EQ (Qleft, arg)
3790 ? vertical_scroll_bar_left
3791 : EQ (Qright, arg)
3792 ? vertical_scroll_bar_right
3793 : EQ (Qleft, Vdefault_frame_scroll_bars)
3794 ? vertical_scroll_bar_left
3795 : EQ (Qright, Vdefault_frame_scroll_bars)
3796 ? vertical_scroll_bar_right
3797 : vertical_scroll_bar_none);
3799 /* We set this parameter before creating the X window for the
3800 frame, so we can get the geometry right from the start.
3801 However, if the window hasn't been created yet, we shouldn't
3802 call x_set_window_size. */
3803 if (FRAME_X_WINDOW (f))
3804 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
3806 SET_FRAME_GARBAGED (f);
3810 void
3811 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3813 #if USE_HORIZONTAL_SCROLL_BARS
3814 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
3815 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
3817 f->horizontal_scroll_bars = NILP (arg) ? false : true;
3819 /* We set this parameter before creating the X window for the
3820 frame, so we can get the geometry right from the start.
3821 However, if the window hasn't been created yet, we shouldn't
3822 call x_set_window_size. */
3823 if (FRAME_X_WINDOW (f))
3824 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
3826 SET_FRAME_GARBAGED (f);
3828 #endif
3831 void
3832 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3834 int unit = FRAME_COLUMN_WIDTH (f);
3836 if (NILP (arg))
3838 x_set_scroll_bar_default_width (f);
3840 if (FRAME_X_WINDOW (f))
3841 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
3843 SET_FRAME_GARBAGED (f);
3845 else if (RANGED_INTEGERP (1, arg, INT_MAX)
3846 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
3848 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3849 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
3850 if (FRAME_X_WINDOW (f))
3851 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
3853 SET_FRAME_GARBAGED (f);
3856 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3857 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3860 void
3861 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3863 #if USE_HORIZONTAL_SCROLL_BARS
3864 int unit = FRAME_LINE_HEIGHT (f);
3866 if (NILP (arg))
3868 x_set_scroll_bar_default_height (f);
3870 if (FRAME_X_WINDOW (f))
3871 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
3873 SET_FRAME_GARBAGED (f);
3875 else if (RANGED_INTEGERP (1, arg, INT_MAX)
3876 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
3878 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
3879 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
3880 if (FRAME_X_WINDOW (f))
3881 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
3883 SET_FRAME_GARBAGED (f);
3886 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
3887 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
3888 #endif
3891 void
3892 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3894 double alpha = 1.0;
3895 double newval[2];
3896 int i;
3897 Lisp_Object item;
3899 for (i = 0; i < 2; i++)
3901 newval[i] = 1.0;
3902 if (CONSP (arg))
3904 item = CAR (arg);
3905 arg = CDR (arg);
3907 else
3908 item = arg;
3910 if (NILP (item))
3911 alpha = - 1.0;
3912 else if (FLOATP (item))
3914 alpha = XFLOAT_DATA (item);
3915 if (! (0 <= alpha && alpha <= 1.0))
3916 args_out_of_range (make_float (0.0), make_float (1.0));
3918 else if (INTEGERP (item))
3920 EMACS_INT ialpha = XINT (item);
3921 if (! (0 <= ialpha && alpha <= 100))
3922 args_out_of_range (make_number (0), make_number (100));
3923 alpha = ialpha / 100.0;
3925 else
3926 wrong_type_argument (Qnumberp, item);
3927 newval[i] = alpha;
3930 for (i = 0; i < 2; i++)
3931 f->alpha[i] = newval[i];
3933 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
3934 block_input ();
3935 x_set_frame_alpha (f);
3936 unblock_input ();
3937 #endif
3939 return;
3942 #ifndef HAVE_NS
3944 /* Non-zero if mouse is grabbed on DPYINFO
3945 and we know the frame where it is. */
3947 bool x_mouse_grabbed (Display_Info *dpyinfo)
3949 return (dpyinfo->grabbed
3950 && dpyinfo->last_mouse_frame
3951 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
3954 /* Re-highlight something with mouse-face properties
3955 on DPYINFO using saved frame and mouse position. */
3957 void
3958 x_redo_mouse_highlight (Display_Info *dpyinfo)
3960 if (dpyinfo->last_mouse_motion_frame
3961 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
3962 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
3963 dpyinfo->last_mouse_motion_x,
3964 dpyinfo->last_mouse_motion_y);
3967 #endif /* HAVE_NS */
3969 /* Subroutines of creating an X frame. */
3971 /* Make sure that Vx_resource_name is set to a reasonable value.
3972 Fix it up, or set it to `emacs' if it is too hopeless. */
3974 void
3975 validate_x_resource_name (void)
3977 ptrdiff_t len = 0;
3978 /* Number of valid characters in the resource name. */
3979 ptrdiff_t good_count = 0;
3980 /* Number of invalid characters in the resource name. */
3981 ptrdiff_t bad_count = 0;
3982 Lisp_Object new;
3983 ptrdiff_t i;
3985 if (!STRINGP (Vx_resource_class))
3986 Vx_resource_class = build_string (EMACS_CLASS);
3988 if (STRINGP (Vx_resource_name))
3990 unsigned char *p = SDATA (Vx_resource_name);
3992 len = SBYTES (Vx_resource_name);
3994 /* Only letters, digits, - and _ are valid in resource names.
3995 Count the valid characters and count the invalid ones. */
3996 for (i = 0; i < len; i++)
3998 int c = p[i];
3999 if (! ((c >= 'a' && c <= 'z')
4000 || (c >= 'A' && c <= 'Z')
4001 || (c >= '0' && c <= '9')
4002 || c == '-' || c == '_'))
4003 bad_count++;
4004 else
4005 good_count++;
4008 else
4009 /* Not a string => completely invalid. */
4010 bad_count = 5, good_count = 0;
4012 /* If name is valid already, return. */
4013 if (bad_count == 0)
4014 return;
4016 /* If name is entirely invalid, or nearly so, or is so implausibly
4017 large that alloca might not work, use `emacs'. */
4018 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
4020 Vx_resource_name = build_string ("emacs");
4021 return;
4024 /* Name is partly valid. Copy it and replace the invalid characters
4025 with underscores. */
4027 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
4029 for (i = 0; i < len; i++)
4031 int c = SREF (new, i);
4032 if (! ((c >= 'a' && c <= 'z')
4033 || (c >= 'A' && c <= 'Z')
4034 || (c >= '0' && c <= '9')
4035 || c == '-' || c == '_'))
4036 SSET (new, i, '_');
4040 /* Get specified attribute from resource database RDB.
4041 See Fx_get_resource below for other parameters. */
4043 static Lisp_Object
4044 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
4046 CHECK_STRING (attribute);
4047 CHECK_STRING (class);
4049 if (!NILP (component))
4050 CHECK_STRING (component);
4051 if (!NILP (subclass))
4052 CHECK_STRING (subclass);
4053 if (NILP (component) != NILP (subclass))
4054 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
4056 validate_x_resource_name ();
4058 /* Allocate space for the components, the dots which separate them,
4059 and the final '\0'. Make them big enough for the worst case. */
4060 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4061 + (STRINGP (component)
4062 ? SBYTES (component) : 0)
4063 + SBYTES (attribute)
4064 + 3);
4066 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4067 + SBYTES (class)
4068 + (STRINGP (subclass)
4069 ? SBYTES (subclass) : 0)
4070 + 3);
4071 USE_SAFE_ALLOCA;
4072 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4073 char *class_key = name_key + name_keysize;
4075 /* Start with emacs.FRAMENAME for the name (the specific one)
4076 and with `Emacs' for the class key (the general one). */
4077 lispstpcpy (name_key, Vx_resource_name);
4078 lispstpcpy (class_key, Vx_resource_class);
4080 strcat (class_key, ".");
4081 strcat (class_key, SSDATA (class));
4083 if (!NILP (component))
4085 strcat (class_key, ".");
4086 strcat (class_key, SSDATA (subclass));
4088 strcat (name_key, ".");
4089 strcat (name_key, SSDATA (component));
4092 strcat (name_key, ".");
4093 strcat (name_key, SSDATA (attribute));
4095 char *value = x_get_string_resource (rdb, name_key, class_key);
4096 SAFE_FREE();
4098 if (value && *value)
4099 return build_string (value);
4100 else
4101 return Qnil;
4105 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4106 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4107 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4108 class, where INSTANCE is the name under which Emacs was invoked, or
4109 the name specified by the `-name' or `-rn' command-line arguments.
4111 The optional arguments COMPONENT and SUBCLASS add to the key and the
4112 class, respectively. You must specify both of them or neither.
4113 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4114 and the class is `Emacs.CLASS.SUBCLASS'. */)
4115 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4116 Lisp_Object subclass)
4118 check_window_system (NULL);
4120 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4121 attribute, class, component, subclass);
4124 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4126 Lisp_Object
4127 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4128 Lisp_Object class, Lisp_Object component,
4129 Lisp_Object subclass)
4131 return xrdb_get_resource (dpyinfo->xrdb,
4132 attribute, class, component, subclass);
4135 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT
4136 /* Used when C code wants a resource value. */
4137 /* Called from oldXMenu/Create.c. */
4138 char *
4139 x_get_resource_string (const char *attribute, const char *class)
4141 char *result;
4142 struct frame *sf = SELECTED_FRAME ();
4143 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4144 USE_SAFE_ALLOCA;
4146 /* Allocate space for the components, the dots which separate them,
4147 and the final '\0'. */
4148 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4149 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4150 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4151 char *class_key = name_key + name_keysize;
4153 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4154 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4156 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4157 name_key, class_key);
4158 SAFE_FREE ();
4159 return result;
4161 #endif
4163 /* Return the value of parameter PARAM.
4165 First search ALIST, then Vdefault_frame_alist, then the X defaults
4166 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4168 Convert the resource to the type specified by desired_type.
4170 If no default is specified, return Qunbound. If you call
4171 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4172 and don't let it get stored in any Lisp-visible variables! */
4174 Lisp_Object
4175 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4176 const char *attribute, const char *class, enum resource_types type)
4178 Lisp_Object tem;
4180 tem = Fassq (param, alist);
4182 if (!NILP (tem))
4184 /* If we find this parm in ALIST, clear it out
4185 so that it won't be "left over" at the end. */
4186 Lisp_Object tail;
4187 XSETCAR (tem, Qnil);
4188 /* In case the parameter appears more than once in the alist,
4189 clear it out. */
4190 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4191 if (CONSP (XCAR (tail))
4192 && EQ (XCAR (XCAR (tail)), param))
4193 XSETCAR (XCAR (tail), Qnil);
4195 else
4196 tem = Fassq (param, Vdefault_frame_alist);
4198 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4199 look in the X resources. */
4200 if (EQ (tem, Qnil))
4202 if (attribute && dpyinfo)
4204 AUTO_STRING (at, attribute);
4205 AUTO_STRING (cl, class);
4206 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4208 if (NILP (tem))
4209 return Qunbound;
4211 switch (type)
4213 case RES_TYPE_NUMBER:
4214 return make_number (atoi (SSDATA (tem)));
4216 case RES_TYPE_BOOLEAN_NUMBER:
4217 if (!strcmp (SSDATA (tem), "on")
4218 || !strcmp (SSDATA (tem), "true"))
4219 return make_number (1);
4220 return make_number (atoi (SSDATA (tem)));
4221 break;
4223 case RES_TYPE_FLOAT:
4224 return make_float (atof (SSDATA (tem)));
4226 case RES_TYPE_BOOLEAN:
4227 tem = Fdowncase (tem);
4228 if (!strcmp (SSDATA (tem), "on")
4229 #ifdef HAVE_NS
4230 || !strcmp (SSDATA (tem), "yes")
4231 #endif
4232 || !strcmp (SSDATA (tem), "true"))
4233 return Qt;
4234 else
4235 return Qnil;
4237 case RES_TYPE_STRING:
4238 return tem;
4240 case RES_TYPE_SYMBOL:
4241 /* As a special case, we map the values `true' and `on'
4242 to Qt, and `false' and `off' to Qnil. */
4244 Lisp_Object lower;
4245 lower = Fdowncase (tem);
4246 if (!strcmp (SSDATA (lower), "on")
4247 #ifdef HAVE_NS
4248 || !strcmp (SSDATA (lower), "yes")
4249 #endif
4250 || !strcmp (SSDATA (lower), "true"))
4251 return Qt;
4252 else if (!strcmp (SSDATA (lower), "off")
4253 #ifdef HAVE_NS
4254 || !strcmp (SSDATA (lower), "no")
4255 #endif
4256 || !strcmp (SSDATA (lower), "false"))
4257 return Qnil;
4258 else
4259 return Fintern (tem, Qnil);
4262 default:
4263 emacs_abort ();
4266 else
4267 return Qunbound;
4269 return Fcdr (tem);
4272 static Lisp_Object
4273 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
4274 const char *attribute, const char *class,
4275 enum resource_types type)
4277 return x_get_arg (FRAME_DISPLAY_INFO (f),
4278 alist, param, attribute, class, type);
4281 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
4283 Lisp_Object
4284 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
4285 Lisp_Object param,
4286 const char *attribute, const char *class,
4287 enum resource_types type)
4289 Lisp_Object value;
4291 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
4292 attribute, class, type);
4293 if (! NILP (value) && ! EQ (value, Qunbound))
4294 store_frame_param (f, param, value);
4296 return value;
4300 /* Record in frame F the specified or default value according to ALIST
4301 of the parameter named PROP (a Lisp symbol).
4302 If no value is specified for PROP, look for an X default for XPROP
4303 on the frame named NAME.
4304 If that is not found either, use the value DEFLT. */
4306 Lisp_Object
4307 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
4308 Lisp_Object deflt, const char *xprop, const char *xclass,
4309 enum resource_types type)
4311 Lisp_Object tem;
4313 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
4314 if (EQ (tem, Qunbound))
4315 tem = deflt;
4316 AUTO_FRAME_ARG (arg, prop, tem);
4317 x_set_frame_parameters (f, arg);
4318 return tem;
4322 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
4325 * XParseGeometry parses strings of the form
4326 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
4327 * width, height, xoffset, and yoffset are unsigned integers.
4328 * Example: "=80x24+300-49"
4329 * The equal sign is optional.
4330 * It returns a bitmask that indicates which of the four values
4331 * were actually found in the string. For each value found,
4332 * the corresponding argument is updated; for each value
4333 * not found, the corresponding argument is left unchanged.
4336 static int
4337 XParseGeometry (char *string,
4338 int *x, int *y,
4339 unsigned int *width, unsigned int *height)
4341 int mask = NoValue;
4342 char *strind;
4343 unsigned long tempWidth, tempHeight;
4344 long int tempX, tempY;
4345 char *nextCharacter;
4347 if (string == NULL || *string == '\0')
4348 return mask;
4349 if (*string == '=')
4350 string++; /* ignore possible '=' at beg of geometry spec */
4352 strind = string;
4353 if (*strind != '+' && *strind != '-' && *strind != 'x')
4355 tempWidth = strtoul (strind, &nextCharacter, 10);
4356 if (strind == nextCharacter)
4357 return 0;
4358 strind = nextCharacter;
4359 mask |= WidthValue;
4362 if (*strind == 'x' || *strind == 'X')
4364 strind++;
4365 tempHeight = strtoul (strind, &nextCharacter, 10);
4366 if (strind == nextCharacter)
4367 return 0;
4368 strind = nextCharacter;
4369 mask |= HeightValue;
4372 if (*strind == '+' || *strind == '-')
4374 if (*strind == '-')
4375 mask |= XNegative;
4376 tempX = strtol (strind, &nextCharacter, 10);
4377 if (strind == nextCharacter)
4378 return 0;
4379 strind = nextCharacter;
4380 mask |= XValue;
4381 if (*strind == '+' || *strind == '-')
4383 if (*strind == '-')
4384 mask |= YNegative;
4385 tempY = strtol (strind, &nextCharacter, 10);
4386 if (strind == nextCharacter)
4387 return 0;
4388 strind = nextCharacter;
4389 mask |= YValue;
4393 /* If strind isn't at the end of the string then it's an invalid
4394 geometry specification. */
4396 if (*strind != '\0')
4397 return 0;
4399 if (mask & XValue)
4400 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
4401 if (mask & YValue)
4402 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
4403 if (mask & WidthValue)
4404 *width = min (tempWidth, UINT_MAX);
4405 if (mask & HeightValue)
4406 *height = min (tempHeight, UINT_MAX);
4407 return mask;
4410 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
4413 /* NS used to define x-parse-geometry in ns-win.el, but that confused
4414 make-docfile: the documentation string in ns-win.el was used for
4415 x-parse-geometry even in non-NS builds.
4417 With two definitions of x-parse-geometry in this file, various
4418 things still get confused (eg M-x apropos documentation), so that
4419 it is best if the two definitions just share the same doc-string.
4421 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
4422 doc: /* Parse a display geometry string STRING.
4423 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
4424 The properties returned may include `top', `left', `height', and `width'.
4425 For X, the value of `left' or `top' may be an integer,
4426 or a list (+ N) meaning N pixels relative to top/left corner,
4427 or a list (- N) meaning -N pixels relative to bottom/right corner.
4428 On Nextstep, this just calls `ns-parse-geometry'. */)
4429 (Lisp_Object string)
4431 int geometry, x, y;
4432 unsigned int width, height;
4433 Lisp_Object result;
4435 CHECK_STRING (string);
4437 #ifdef HAVE_NS
4438 if (strchr (SSDATA (string), ' ') != NULL)
4439 return call1 (Qns_parse_geometry, string);
4440 #endif
4441 geometry = XParseGeometry (SSDATA (string),
4442 &x, &y, &width, &height);
4443 result = Qnil;
4444 if (geometry & XValue)
4446 Lisp_Object element;
4448 if (x >= 0 && (geometry & XNegative))
4449 element = list3 (Qleft, Qminus, make_number (-x));
4450 else if (x < 0 && ! (geometry & XNegative))
4451 element = list3 (Qleft, Qplus, make_number (x));
4452 else
4453 element = Fcons (Qleft, make_number (x));
4454 result = Fcons (element, result);
4457 if (geometry & YValue)
4459 Lisp_Object element;
4461 if (y >= 0 && (geometry & YNegative))
4462 element = list3 (Qtop, Qminus, make_number (-y));
4463 else if (y < 0 && ! (geometry & YNegative))
4464 element = list3 (Qtop, Qplus, make_number (y));
4465 else
4466 element = Fcons (Qtop, make_number (y));
4467 result = Fcons (element, result);
4470 if (geometry & WidthValue)
4471 result = Fcons (Fcons (Qwidth, make_number (width)), result);
4472 if (geometry & HeightValue)
4473 result = Fcons (Fcons (Qheight, make_number (height)), result);
4475 return result;
4479 /* Calculate the desired size and position of frame F.
4480 Return the flags saying which aspects were specified.
4482 Also set the win_gravity and size_hint_flags of F.
4484 Adjust height for toolbar if TOOLBAR_P is 1.
4486 This function does not make the coordinates positive. */
4488 #define DEFAULT_ROWS 35
4489 #define DEFAULT_COLS 80
4491 long
4492 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
4494 Lisp_Object height, width, user_size, top, left, user_position;
4495 long window_prompting = 0;
4496 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
4498 /* Default values if we fall through.
4499 Actually, if that happens we should get
4500 window manager prompting. */
4501 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
4502 SET_FRAME_COLS (f, DEFAULT_COLS);
4503 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
4504 SET_FRAME_LINES (f, DEFAULT_ROWS);
4506 /* Window managers expect that if program-specified
4507 positions are not (0,0), they're intentional, not defaults. */
4508 f->top_pos = 0;
4509 f->left_pos = 0;
4511 /* Ensure that earlier new_width and new_height settings won't
4512 override what we specify below. */
4513 f->new_width = f->new_height = 0;
4515 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4516 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4517 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
4519 if (!EQ (width, Qunbound))
4521 CHECK_NUMBER (width);
4522 if (! (0 <= XINT (width) && XINT (width) <= INT_MAX))
4523 xsignal1 (Qargs_out_of_range, width);
4525 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
4528 if (!EQ (height, Qunbound))
4530 CHECK_NUMBER (height);
4531 if (! (0 <= XINT (height) && XINT (height) <= INT_MAX))
4532 xsignal1 (Qargs_out_of_range, height);
4534 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
4537 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4538 if (!NILP (user_size) && !EQ (user_size, Qunbound))
4539 window_prompting |= USSize;
4540 else
4541 window_prompting |= PSize;
4544 /* Add a tool bar height to the initial frame height so that the user
4545 gets a text display area of the size he specified with -g or via
4546 .Xdefaults. Later changes of the tool bar height don't change the
4547 frame size. This is done so that users can create tall Emacs
4548 frames without having to guess how tall the tool bar will get. */
4549 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4551 int margin, relief;
4553 relief = (tool_bar_button_relief >= 0
4554 ? tool_bar_button_relief
4555 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4557 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
4558 margin = XFASTINT (Vtool_bar_button_margin);
4559 else if (CONSP (Vtool_bar_button_margin)
4560 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
4561 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4562 else
4563 margin = 0;
4565 FRAME_TOOL_BAR_HEIGHT (f)
4566 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4567 Vframe_initial_frame_tool_bar_height = make_number (FRAME_TOOL_BAR_HEIGHT (f));
4570 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4571 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4572 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4573 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
4575 if (EQ (top, Qminus))
4577 f->top_pos = 0;
4578 window_prompting |= YNegative;
4580 else if (CONSP (top) && EQ (XCAR (top), Qminus)
4581 && CONSP (XCDR (top))
4582 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
4584 f->top_pos = - XINT (XCAR (XCDR (top)));
4585 window_prompting |= YNegative;
4587 else if (CONSP (top) && EQ (XCAR (top), Qplus)
4588 && CONSP (XCDR (top))
4589 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
4591 f->top_pos = XINT (XCAR (XCDR (top)));
4593 else if (EQ (top, Qunbound))
4594 f->top_pos = 0;
4595 else
4597 CHECK_TYPE_RANGED_INTEGER (int, top);
4598 f->top_pos = XINT (top);
4599 if (f->top_pos < 0)
4600 window_prompting |= YNegative;
4603 if (EQ (left, Qminus))
4605 f->left_pos = 0;
4606 window_prompting |= XNegative;
4608 else if (CONSP (left) && EQ (XCAR (left), Qminus)
4609 && CONSP (XCDR (left))
4610 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
4612 f->left_pos = - XINT (XCAR (XCDR (left)));
4613 window_prompting |= XNegative;
4615 else if (CONSP (left) && EQ (XCAR (left), Qplus)
4616 && CONSP (XCDR (left))
4617 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
4619 f->left_pos = XINT (XCAR (XCDR (left)));
4621 else if (EQ (left, Qunbound))
4622 f->left_pos = 0;
4623 else
4625 CHECK_TYPE_RANGED_INTEGER (int, left);
4626 f->left_pos = XINT (left);
4627 if (f->left_pos < 0)
4628 window_prompting |= XNegative;
4631 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
4632 window_prompting |= USPosition;
4633 else
4634 window_prompting |= PPosition;
4637 if (window_prompting & XNegative)
4639 if (window_prompting & YNegative)
4640 f->win_gravity = SouthEastGravity;
4641 else
4642 f->win_gravity = NorthEastGravity;
4644 else
4646 if (window_prompting & YNegative)
4647 f->win_gravity = SouthWestGravity;
4648 else
4649 f->win_gravity = NorthWestGravity;
4652 f->size_hint_flags = window_prompting;
4654 return window_prompting;
4659 #endif /* HAVE_WINDOW_SYSTEM */
4661 void
4662 frame_make_pointer_invisible (struct frame *f)
4664 if (! NILP (Vmake_pointer_invisible))
4666 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
4667 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4669 f->mouse_moved = 0;
4670 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
4671 f->pointer_invisible = 1;
4676 void
4677 frame_make_pointer_visible (struct frame *f)
4679 /* We don't check Vmake_pointer_invisible here in case the
4680 pointer was invisible when Vmake_pointer_invisible was set to nil. */
4681 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
4682 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4684 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
4685 f->pointer_invisible = 0;
4689 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
4690 Sframe_pointer_visible_p, 0, 1, 0,
4691 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
4692 Otherwise it returns nil. FRAME omitted or nil means the
4693 selected frame. This is useful when `make-pointer-invisible' is set. */)
4694 (Lisp_Object frame)
4696 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
4701 /***********************************************************************
4702 Multimonitor data
4703 ***********************************************************************/
4705 #ifdef HAVE_WINDOW_SYSTEM
4707 # if (defined HAVE_NS \
4708 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
4709 void
4710 free_monitors (struct MonitorInfo *monitors, int n_monitors)
4712 int i;
4713 for (i = 0; i < n_monitors; ++i)
4714 xfree (monitors[i].name);
4715 xfree (monitors);
4717 # endif
4719 Lisp_Object
4720 make_monitor_attribute_list (struct MonitorInfo *monitors,
4721 int n_monitors,
4722 int primary_monitor,
4723 Lisp_Object monitor_frames,
4724 const char *source)
4726 Lisp_Object attributes_list = Qnil;
4727 Lisp_Object primary_monitor_attributes = Qnil;
4728 int i;
4730 for (i = 0; i < n_monitors; ++i)
4732 Lisp_Object geometry, workarea, attributes = Qnil;
4733 struct MonitorInfo *mi = &monitors[i];
4735 if (mi->geom.width == 0) continue;
4737 workarea = list4i (mi->work.x, mi->work.y,
4738 mi->work.width, mi->work.height);
4739 geometry = list4i (mi->geom.x, mi->geom.y,
4740 mi->geom.width, mi->geom.height);
4741 attributes = Fcons (Fcons (Qsource, build_string (source)),
4742 attributes);
4743 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
4744 attributes);
4745 attributes = Fcons (Fcons (Qmm_size,
4746 list2i (mi->mm_width, mi->mm_height)),
4747 attributes);
4748 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
4749 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
4750 if (mi->name)
4751 attributes = Fcons (Fcons (Qname, make_string (mi->name,
4752 strlen (mi->name))),
4753 attributes);
4755 if (i == primary_monitor)
4756 primary_monitor_attributes = attributes;
4757 else
4758 attributes_list = Fcons (attributes, attributes_list);
4761 if (!NILP (primary_monitor_attributes))
4762 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
4763 return attributes_list;
4766 #endif /* HAVE_WINDOW_SYSTEM */
4769 /***********************************************************************
4770 Initialization
4771 ***********************************************************************/
4773 void
4774 syms_of_frame (void)
4776 DEFSYM (Qframep, "framep");
4777 DEFSYM (Qframe_live_p, "frame-live-p");
4778 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
4779 DEFSYM (Qexplicit_name, "explicit-name");
4780 DEFSYM (Qheight, "height");
4781 DEFSYM (Qicon, "icon");
4782 DEFSYM (Qminibuffer, "minibuffer");
4783 DEFSYM (Qmodeline, "modeline");
4784 DEFSYM (Qonly, "only");
4785 DEFSYM (Qnone, "none");
4786 DEFSYM (Qwidth, "width");
4787 DEFSYM (Qgeometry, "geometry");
4788 DEFSYM (Qicon_left, "icon-left");
4789 DEFSYM (Qicon_top, "icon-top");
4790 DEFSYM (Qtooltip, "tooltip");
4791 DEFSYM (Quser_position, "user-position");
4792 DEFSYM (Quser_size, "user-size");
4793 DEFSYM (Qwindow_id, "window-id");
4794 #ifdef HAVE_X_WINDOWS
4795 DEFSYM (Qouter_window_id, "outer-window-id");
4796 #endif
4797 DEFSYM (Qparent_id, "parent-id");
4798 DEFSYM (Qx, "x");
4799 DEFSYM (Qw32, "w32");
4800 DEFSYM (Qpc, "pc");
4801 DEFSYM (Qns, "ns");
4802 DEFSYM (Qvisible, "visible");
4803 DEFSYM (Qbuffer_predicate, "buffer-predicate");
4804 DEFSYM (Qbuffer_list, "buffer-list");
4805 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
4806 DEFSYM (Qdisplay_type, "display-type");
4807 DEFSYM (Qbackground_mode, "background-mode");
4808 DEFSYM (Qnoelisp, "noelisp");
4809 DEFSYM (Qtty_color_mode, "tty-color-mode");
4810 DEFSYM (Qtty, "tty");
4811 DEFSYM (Qtty_type, "tty-type");
4813 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
4815 DEFSYM (Qfullwidth, "fullwidth");
4816 DEFSYM (Qfullheight, "fullheight");
4817 DEFSYM (Qfullboth, "fullboth");
4818 DEFSYM (Qmaximized, "maximized");
4819 DEFSYM (Qx_resource_name, "x-resource-name");
4820 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
4822 DEFSYM (Qterminal, "terminal");
4824 DEFSYM (Qworkarea, "workarea");
4825 DEFSYM (Qmm_size, "mm-size");
4826 DEFSYM (Qframes, "frames");
4827 DEFSYM (Qsource, "source");
4829 DEFSYM (Qframe_position, "frame-position");
4830 DEFSYM (Qframe_outer_size, "frame-outer-size");
4831 DEFSYM (Qexternal_border_size, "external-border-size");
4832 DEFSYM (Qtitle_height, "title-height");
4833 DEFSYM (Qmenu_bar_external, "menu-bar-external");
4834 DEFSYM (Qmenu_bar_size, "menu-bar-size");
4835 DEFSYM (Qtool_bar_external, "tool-bar-external");
4836 DEFSYM (Qtool_bar_size, "tool-bar-size");
4837 DEFSYM (Qframe_inner_size, "frame-inner-size");
4839 #ifdef HAVE_NS
4840 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
4841 #endif
4844 int i;
4846 for (i = 0; i < ARRAYELTS (frame_parms); i++)
4848 Lisp_Object v = intern_c_string (frame_parms[i].name);
4849 if (frame_parms[i].variable)
4851 *frame_parms[i].variable = v;
4852 staticpro (frame_parms[i].variable);
4854 Fput (v, Qx_frame_parameter, make_number (i));
4858 #ifdef HAVE_WINDOW_SYSTEM
4859 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
4860 doc: /* The name Emacs uses to look up X resources.
4861 `x-get-resource' uses this as the first component of the instance name
4862 when requesting resource values.
4863 Emacs initially sets `x-resource-name' to the name under which Emacs
4864 was invoked, or to the value specified with the `-name' or `-rn'
4865 switches, if present.
4867 It may be useful to bind this variable locally around a call
4868 to `x-get-resource'. See also the variable `x-resource-class'. */);
4869 Vx_resource_name = Qnil;
4871 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
4872 doc: /* The class Emacs uses to look up X resources.
4873 `x-get-resource' uses this as the first component of the instance class
4874 when requesting resource values.
4876 Emacs initially sets `x-resource-class' to "Emacs".
4878 Setting this variable permanently is not a reasonable thing to do,
4879 but binding this variable locally around a call to `x-get-resource'
4880 is a reasonable practice. See also the variable `x-resource-name'. */);
4881 Vx_resource_class = build_string (EMACS_CLASS);
4883 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
4884 doc: /* The lower limit of the frame opacity (alpha transparency).
4885 The value should range from 0 (invisible) to 100 (completely opaque).
4886 You can also use a floating number between 0.0 and 1.0. */);
4887 Vframe_alpha_lower_limit = make_number (20);
4888 #endif
4890 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
4891 doc: /* Alist of default values for frame creation.
4892 These may be set in your init file, like this:
4893 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
4894 These override values given in window system configuration data,
4895 including X Windows' defaults database.
4896 For values specific to the first Emacs frame, see `initial-frame-alist'.
4897 For window-system specific values, see `window-system-default-frame-alist'.
4898 For values specific to the separate minibuffer frame, see
4899 `minibuffer-frame-alist'.
4900 The `menu-bar-lines' element of the list controls whether new frames
4901 have menu bars; `menu-bar-mode' works by altering this element.
4902 Setting this variable does not affect existing frames, only new ones. */);
4903 Vdefault_frame_alist = Qnil;
4905 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
4906 doc: /* Default position of vertical scroll bars on this window-system. */);
4907 #ifdef HAVE_WINDOW_SYSTEM
4908 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
4909 /* MS-Windows, Mac OS X, and GTK have scroll bars on the right by
4910 default. */
4911 Vdefault_frame_scroll_bars = Qright;
4912 #else
4913 Vdefault_frame_scroll_bars = Qleft;
4914 #endif
4915 #else
4916 Vdefault_frame_scroll_bars = Qnil;
4917 #endif
4919 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
4920 scroll_bar_adjust_thumb_portion_p,
4921 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
4922 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
4923 even if the end of the buffer is shown (i.e. overscrolling).
4924 Set to nil if you want the thumb to be at the bottom when the end of the buffer
4925 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
4926 is visible. In this case you can not overscroll. */);
4927 scroll_bar_adjust_thumb_portion_p = 1;
4929 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
4930 doc: /* The initial frame-object, which represents Emacs's stdout. */);
4932 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
4933 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4934 `mouse-position' and `mouse-pixel-position' call this function, passing their
4935 usual return value as argument, and return whatever this function returns.
4936 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4937 which need to do mouse handling at the Lisp level. */);
4938 Vmouse_position_function = Qnil;
4940 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
4941 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4942 If the value is an integer, highlighting is only shown after moving the
4943 mouse, while keyboard input turns off the highlight even when the mouse
4944 is over the clickable text. However, the mouse shape still indicates
4945 when the mouse is over clickable text. */);
4946 Vmouse_highlight = Qt;
4948 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
4949 doc: /* If non-nil, make pointer invisible while typing.
4950 The pointer becomes visible again when the mouse is moved. */);
4951 Vmake_pointer_invisible = Qt;
4953 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
4954 doc: /* Normal hook run when a frame gains input focus. */);
4955 Vfocus_in_hook = Qnil;
4956 DEFSYM (Qfocus_in_hook, "focus-in-hook");
4958 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
4959 doc: /* Normal hook run when a frame loses input focus. */);
4960 Vfocus_out_hook = Qnil;
4961 DEFSYM (Qfocus_out_hook, "focus-out-hook");
4963 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
4964 doc: /* Functions run before deleting a frame.
4965 The functions are run with one arg, the frame to be deleted.
4966 See `delete-frame'.
4968 Note that functions in this list may be called just before the frame is
4969 actually deleted, or some time later (or even both when an earlier function
4970 in `delete-frame-functions' (indirectly) calls `delete-frame'
4971 recursively). */);
4972 Vdelete_frame_functions = Qnil;
4973 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
4975 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
4976 doc: /* Non-nil if Menu-Bar mode is enabled.
4977 See the command `menu-bar-mode' for a description of this minor mode.
4978 Setting this variable directly does not take effect;
4979 either customize it (see the info node `Easy Customization')
4980 or call the function `menu-bar-mode'. */);
4981 Vmenu_bar_mode = Qt;
4983 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
4984 doc: /* Non-nil if Tool-Bar mode is enabled.
4985 See the command `tool-bar-mode' for a description of this minor mode.
4986 Setting this variable directly does not take effect;
4987 either customize it (see the info node `Easy Customization')
4988 or call the function `tool-bar-mode'. */);
4989 #ifdef HAVE_WINDOW_SYSTEM
4990 Vtool_bar_mode = Qt;
4991 #else
4992 Vtool_bar_mode = Qnil;
4993 #endif
4995 DEFVAR_LISP ("frame-initial-frame-tool-bar-height", Vframe_initial_frame_tool_bar_height,
4996 doc: /* Height of tool bar of initial frame. */);
4997 Vframe_initial_frame_tool_bar_height = make_number (0);
4999 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
5000 doc: /* Minibufferless frames use this frame's minibuffer.
5001 Emacs cannot create minibufferless frames unless this is set to an
5002 appropriate surrogate.
5004 Emacs consults this variable only when creating minibufferless
5005 frames; once the frame is created, it sticks with its assigned
5006 minibuffer, no matter what this variable is set to. This means that
5007 this variable doesn't necessarily say anything meaningful about the
5008 current set of frames, or where the minibuffer is currently being
5009 displayed.
5011 This variable is local to the current terminal and cannot be buffer-local. */);
5013 DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse,
5014 doc: /* Non-nil if window system changes focus when you move the mouse.
5015 You should set this variable to tell Emacs how your window manager
5016 handles focus, since there is no way in general for Emacs to find out
5017 automatically. See also `mouse-autoselect-window'. */);
5018 focus_follows_mouse = 0;
5020 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5021 doc: /* Non-nil means resize frames pixelwise.
5022 If this option is nil, resizing a frame rounds its sizes to the frame's
5023 current values of `frame-char-height' and `frame-char-width'. If this
5024 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5025 by one pixel.
5027 With some window managers you may have to set this to non-nil in order
5028 to set the size of a frame in pixels, to maximize frames or to make them
5029 fullscreen. To resize your initial frame pixelwise, set this option to
5030 a non-nil value in your init file. */);
5031 frame_resize_pixelwise = 0;
5033 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
5034 doc: /* Whether frames should be resized implicitly.
5035 If this option is nil, setting font, menu bar, tool bar, internal
5036 borders, fringes or scroll bars of a specific frame may resize the frame
5037 in order to preserve the number of columns or lines it displays. If
5038 this option is `t', no such resizing is done. Note that the size of
5039 fullscreen and maximized frames, the height of fullheight frames and the
5040 width of fullwidth frames never change implicitly.
5042 The value of this option can be also be a list of frame parameters. In
5043 this case, resizing is inhibited when changing a parameter that appears
5044 in that list. The parameters currently handled by this option include
5045 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
5046 `tool-bar-lines'.
5048 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
5049 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
5050 `right-fringe' is handled as if the frame contained just one live
5051 window. This means, for example, that removing vertical scroll bars on
5052 a frame containing several side by side windows will shrink the frame
5053 width by the width of one scroll bar provided this option is nil and
5054 keep it unchanged if this option is either `t' or a list containing
5055 `vertical-scroll-bars'.
5057 The default value is '(tool-bar-lines) on Lucid, Motif and Windows
5058 (which means that adding/removing a tool bar does not change the frame
5059 height), nil on all other window systems including GTK+ (which means
5060 that changing any of the parameters listed above may change the size of
5061 the frame), and `t' otherwise (which means the frame size never changes
5062 implicitly when there's no window system support).
5064 Note that when a frame is not large enough to accommodate a change of
5065 any of the parameters listed above, Emacs may try to enlarge the frame
5066 even if this option is non-nil. */);
5067 #if defined (HAVE_WINDOW_SYSTEM)
5068 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
5069 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
5070 #else
5071 frame_inhibit_implied_resize = Qnil;
5072 #endif
5073 #else
5074 frame_inhibit_implied_resize = Qt;
5075 #endif
5077 staticpro (&Vframe_list);
5079 defsubr (&Sframep);
5080 defsubr (&Sframe_live_p);
5081 defsubr (&Swindow_system);
5082 defsubr (&Smake_terminal_frame);
5083 defsubr (&Shandle_switch_frame);
5084 defsubr (&Sselect_frame);
5085 defsubr (&Sselected_frame);
5086 defsubr (&Sframe_list);
5087 defsubr (&Snext_frame);
5088 defsubr (&Sprevious_frame);
5089 defsubr (&Slast_nonminibuf_frame);
5090 defsubr (&Sdelete_frame);
5091 defsubr (&Smouse_position);
5092 defsubr (&Smouse_pixel_position);
5093 defsubr (&Sset_mouse_position);
5094 defsubr (&Sset_mouse_pixel_position);
5095 #if 0
5096 defsubr (&Sframe_configuration);
5097 defsubr (&Srestore_frame_configuration);
5098 #endif
5099 defsubr (&Smake_frame_visible);
5100 defsubr (&Smake_frame_invisible);
5101 defsubr (&Siconify_frame);
5102 defsubr (&Sframe_visible_p);
5103 defsubr (&Svisible_frame_list);
5104 defsubr (&Sraise_frame);
5105 defsubr (&Slower_frame);
5106 defsubr (&Sx_focus_frame);
5107 defsubr (&Scan_run_window_configuration_change_hook);
5108 defsubr (&Sredirect_frame_focus);
5109 defsubr (&Sframe_focus);
5110 defsubr (&Sframe_parameters);
5111 defsubr (&Sframe_parameter);
5112 defsubr (&Smodify_frame_parameters);
5113 defsubr (&Sframe_char_height);
5114 defsubr (&Sframe_char_width);
5115 defsubr (&Sframe_pixel_height);
5116 defsubr (&Sframe_pixel_width);
5117 defsubr (&Sframe_text_cols);
5118 defsubr (&Sframe_text_lines);
5119 defsubr (&Sframe_total_cols);
5120 defsubr (&Sframe_total_lines);
5121 defsubr (&Sframe_text_width);
5122 defsubr (&Sframe_text_height);
5123 defsubr (&Sscroll_bar_width);
5124 defsubr (&Sscroll_bar_height);
5125 defsubr (&Sfringe_width);
5126 defsubr (&Sborder_width);
5127 defsubr (&Sright_divider_width);
5128 defsubr (&Sbottom_divider_width);
5129 defsubr (&Stool_bar_pixel_width);
5130 defsubr (&Sset_frame_height);
5131 defsubr (&Sset_frame_width);
5132 defsubr (&Sset_frame_size);
5133 defsubr (&Sset_frame_position);
5134 defsubr (&Sframe_pointer_visible_p);
5136 #ifdef HAVE_WINDOW_SYSTEM
5137 defsubr (&Sx_get_resource);
5138 defsubr (&Sx_parse_geometry);
5139 #endif