(eww): Don't interpret "org/foo" as an URL.
[emacs.git] / src / frame.c
blobfb9bf2e9cbb843de3ec612b0efdb0461232fc7fc
1 /* Generic frame functions.
3 Copyright (C) 1993-1995, 1997, 1999-2015 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 /* The currently selected frame. */
60 Lisp_Object selected_frame;
62 /* A frame which is not just a mini-buffer, or NULL if there are no such
63 frames. This is usually the most recent such frame that was selected. */
65 static struct frame *last_nonminibuf_frame;
67 /* False means there are no visible garbaged frames. */
68 bool frame_garbaged;
70 #ifdef HAVE_WINDOW_SYSTEM
71 static void x_report_frame_params (struct frame *, Lisp_Object *);
72 #endif
74 /* These setters are used only in this file, so they can be private. */
75 static void
76 fset_buffer_predicate (struct frame *f, Lisp_Object val)
78 f->buffer_predicate = val;
80 static void
81 fset_minibuffer_window (struct frame *f, Lisp_Object val)
83 f->minibuffer_window = val;
86 struct frame *
87 decode_live_frame (register Lisp_Object frame)
89 if (NILP (frame))
90 frame = selected_frame;
91 CHECK_LIVE_FRAME (frame);
92 return XFRAME (frame);
95 struct frame *
96 decode_any_frame (register Lisp_Object frame)
98 if (NILP (frame))
99 frame = selected_frame;
100 CHECK_FRAME (frame);
101 return XFRAME (frame);
104 #ifdef HAVE_WINDOW_SYSTEM
106 bool
107 window_system_available (struct frame *f)
109 return f ? FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f) : x_display_list != NULL;
112 #endif /* HAVE_WINDOW_SYSTEM */
114 struct frame *
115 decode_window_system_frame (Lisp_Object frame)
117 struct frame *f = decode_live_frame (frame);
119 if (!window_system_available (f))
120 error ("Window system frame should be used");
121 return f;
124 void
125 check_window_system (struct frame *f)
127 if (!window_system_available (f))
128 error (f ? "Window system frame should be used"
129 : "Window system is not in use or not initialized");
132 /* Return the value of frame parameter PROP in frame FRAME. */
134 Lisp_Object
135 get_frame_param (register struct frame *frame, Lisp_Object prop)
137 register Lisp_Object tem;
139 tem = Fassq (prop, frame->param_alist);
140 if (EQ (tem, Qnil))
141 return tem;
142 return Fcdr (tem);
145 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
146 state of frame F would be affected by a vertical (horizontal if
147 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
148 parameter that is changed. */
149 bool
150 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
152 return (EQ (frame_inhibit_implied_resize, Qt)
153 || (CONSP (frame_inhibit_implied_resize)
154 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
155 || !NILP (get_frame_param (f, Qfullscreen))
156 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
159 static void
160 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
162 int nlines;
163 int olines = FRAME_MENU_BAR_LINES (f);
165 /* Right now, menu bars don't work properly in minibuf-only frames;
166 most of the commands try to apply themselves to the minibuffer
167 frame itself, and get an error because you can't switch buffers
168 in or split the minibuffer window. */
169 if (FRAME_MINIBUF_ONLY_P (f))
170 return;
172 if (TYPE_RANGED_INTEGERP (int, value))
173 nlines = XINT (value);
174 else
175 nlines = 0;
177 if (nlines != olines)
179 windows_or_buffers_changed = 14;
180 FRAME_MENU_BAR_LINES (f) = nlines;
181 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
182 change_frame_size (f, FRAME_COLS (f),
183 FRAME_LINES (f) + olines - nlines,
184 0, 1, 0, 0);
188 Lisp_Object Vframe_list;
191 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
192 doc: /* Return non-nil if OBJECT is a frame.
193 Value is:
194 t for a termcap frame (a character-only terminal),
195 'x' for an Emacs frame that is really an X window,
196 'w32' for an Emacs frame that is a window on MS-Windows display,
197 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
198 'pc' for a direct-write MS-DOS frame.
199 See also `frame-live-p'. */)
200 (Lisp_Object object)
202 if (!FRAMEP (object))
203 return Qnil;
204 switch (XFRAME (object)->output_method)
206 case output_initial: /* The initial frame is like a termcap frame. */
207 case output_termcap:
208 return Qt;
209 case output_x_window:
210 return Qx;
211 case output_w32:
212 return Qw32;
213 case output_msdos_raw:
214 return Qpc;
215 case output_ns:
216 return Qns;
217 default:
218 emacs_abort ();
222 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
223 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
224 Value is nil if OBJECT is not a live frame. If object is a live
225 frame, the return value indicates what sort of terminal device it is
226 displayed on. See the documentation of `framep' for possible
227 return values. */)
228 (Lisp_Object object)
230 return ((FRAMEP (object)
231 && FRAME_LIVE_P (XFRAME (object)))
232 ? Fframep (object)
233 : Qnil);
236 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
237 doc: /* The name of the window system that FRAME is displaying through.
238 The value is a symbol:
239 nil for a termcap frame (a character-only terminal),
240 'x' for an Emacs frame that is really an X window,
241 'w32' for an Emacs frame that is a window on MS-Windows display,
242 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
243 'pc' for a direct-write MS-DOS frame.
245 FRAME defaults to the currently selected frame.
247 Use of this function as a predicate is deprecated. Instead,
248 use `display-graphic-p' or any of the other `display-*-p'
249 predicates which report frame's specific UI-related capabilities. */)
250 (Lisp_Object frame)
252 Lisp_Object type;
253 if (NILP (frame))
254 frame = selected_frame;
256 type = Fframep (frame);
258 if (NILP (type))
259 wrong_type_argument (Qframep, frame);
261 if (EQ (type, Qt))
262 return Qnil;
263 else
264 return type;
267 /* Placeholder used by temacs -nw before window.el is loaded. */
268 DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
269 Sframe_windows_min_size, 4, 4, 0,
270 doc: /* */)
271 (Lisp_Object frame, Lisp_Object horizontal,
272 Lisp_Object ignore, Lisp_Object pixelwise)
274 return make_number (0);
277 static int
278 frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
279 Lisp_Object ignore, Lisp_Object pixelwise)
281 return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
282 ignore, pixelwise));
286 /* Make sure windows sizes of frame F are OK. new_width and new_height
287 are in pixels. A value of -1 means no change is requested for that
288 size (but the frame may still have to be resized to accommodate
289 windows with their minimum sizes). This can either issue a request
290 to resize the frame externally (via x_set_window_size), to resize the
291 frame internally (via resize_frame_windows) or do nothing at all.
293 The argument INHIBIT can assume the following values:
295 0 means to unconditionally call x_set_window_size even if sizes
296 apparently do not change. Fx_create_frame uses this to pass the
297 initial size to the window manager.
299 1 means to call x_set_window_size if the outer frame size really
300 changes. Fset_frame_size, Fset_frame_height, ... use this.
302 2 means to call x_set_window_size provided frame_inhibit_resize
303 allows it. The menu and tool bar code use this ("3" won't work
304 here in general because menu and tool bar are often not counted in
305 the frame's text height).
307 3 means call x_set_window_size if window minimum sizes must be
308 preserved or frame_inhibit_resize allows it. x_set_left_fringe,
309 x_set_scroll_bar_width, x_new_font ... use (or should use) this.
311 4 means call x_set_window_size only if window minimum sizes must be
312 preserved. x_set_right_divider_width, x_set_border_width and the
313 code responsible for wrapping the tool bar use this.
315 5 means to never call x_set_window_size. change_frame_size uses
316 this.
318 Note that even when x_set_window_size is not called, individual
319 windows may have to be resized (via `window--sanitize-window-sizes')
320 in order to support minimum size constraints.
322 PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
323 symbol of the parameter changed (like `menu-bar-lines', `font', ...).
324 This is passed on to frame_inhibit_resize to let the latter decide on
325 a case-by-case basis whether the frame may be resized externally. */
326 void
327 adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
328 bool pretend, Lisp_Object parameter)
330 int unit_width = FRAME_COLUMN_WIDTH (f);
331 int unit_height = FRAME_LINE_HEIGHT (f);
332 int old_pixel_width = FRAME_PIXEL_WIDTH (f);
333 int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
334 int new_pixel_width, new_pixel_height;
335 /* The following two values are calculated from the old frame pixel
336 sizes and any "new" settings for tool bar, menu bar and internal
337 borders. We do it this way to detect whether we have to call
338 x_set_window_size as consequence of the new settings. */
339 int windows_width = FRAME_WINDOWS_WIDTH (f);
340 int windows_height = FRAME_WINDOWS_HEIGHT (f);
341 int min_windows_width, min_windows_height;
342 /* These are a bit tedious, maybe we should use a macro. */
343 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
344 int old_windows_width = WINDOW_PIXEL_WIDTH (r);
345 int old_windows_height
346 = (WINDOW_PIXEL_HEIGHT (r)
347 + (FRAME_HAS_MINIBUF_P (f)
348 ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
349 : 0));
350 int new_windows_width, new_windows_height;
351 int old_text_width = FRAME_TEXT_WIDTH (f);
352 int old_text_height = FRAME_TEXT_HEIGHT (f);
353 /* If a size is < 0 use the old value. */
354 int new_text_width = (new_width >= 0) ? new_width : old_text_width;
355 int new_text_height = (new_height >= 0) ? new_height : old_text_height;
356 int new_cols, new_lines;
357 bool inhibit_horizontal, inhibit_vertical;
358 Lisp_Object frame;
360 XSETFRAME (frame, f);
361 /* The following two values are calculated from the old window body
362 sizes and any "new" settings for scroll bars, dividers, fringes and
363 margins (though the latter should have been processed already). */
364 min_windows_width
365 = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
366 min_windows_height
367 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
369 if (inhibit >= 2 && inhibit <= 4)
370 /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay
371 within the limits and either frame_inhibit_resize tells us to do
372 so or INHIBIT equals 4. */
374 inhibit_horizontal = ((windows_width >= min_windows_width
375 && (inhibit == 4
376 || frame_inhibit_resize (f, true, parameter)))
377 ? true : false);
378 inhibit_vertical = ((windows_height >= min_windows_height
379 && (inhibit == 4
380 || frame_inhibit_resize (f, false, parameter)))
381 ? true : false);
383 else
384 /* Otherwise inhibit if INHIBIT equals 5. */
385 inhibit_horizontal = inhibit_vertical = inhibit == 5;
387 new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
388 ? old_pixel_width
389 : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
390 min_windows_width
391 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
392 new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
393 new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
394 new_cols = new_text_width / unit_width;
396 new_pixel_height = ((inhibit_vertical && (inhibit < 5))
397 ? old_pixel_height
398 : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
399 min_windows_height
400 + FRAME_TOP_MARGIN_HEIGHT (f)
401 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
402 new_windows_height = (new_pixel_height
403 - FRAME_TOP_MARGIN_HEIGHT (f)
404 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
405 new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
406 new_lines = new_text_height / unit_height;
408 #ifdef HAVE_WINDOW_SYSTEM
409 if (FRAME_WINDOW_P (f)
410 && f->can_x_set_window_size
411 && ((!inhibit_horizontal
412 && (new_pixel_width != old_pixel_width
413 || inhibit == 0 || inhibit == 2))
414 || (!inhibit_vertical
415 && (new_pixel_height != old_pixel_height
416 || inhibit == 0 || inhibit == 2))))
417 /* We are either allowed to change the frame size or the minimum
418 sizes request such a change. Do not care for fixing minimum
419 sizes here, we do that eventually when we're called from
420 change_frame_size. */
422 /* Make sure we respect fullheight and fullwidth. */
423 if (inhibit_horizontal)
424 new_text_width = old_text_width;
425 else if (inhibit_vertical)
426 new_text_height = old_text_height;
428 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
429 f->resized_p = true;
431 return;
433 #endif
435 if (new_text_width == old_text_width
436 && new_text_height == old_text_height
437 && new_windows_width == old_windows_width
438 && new_windows_height == old_windows_height
439 && new_pixel_width == old_pixel_width
440 && new_pixel_height == old_pixel_height)
441 /* No change. Sanitize window sizes and return. */
443 sanitize_window_sizes (frame, Qt);
444 sanitize_window_sizes (frame, Qnil);
446 return;
449 block_input ();
451 #ifdef MSDOS
452 /* We only can set screen dimensions to certain values supported
453 by our video hardware. Try to find the smallest size greater
454 or equal to the requested dimensions. */
455 dos_set_window_size (&new_lines, &new_cols);
456 #endif
458 if (new_windows_width != old_windows_width)
460 resize_frame_windows (f, new_windows_width, 1, 1);
462 /* MSDOS frames cannot PRETEND, as they change frame size by
463 manipulating video hardware. */
464 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
465 FrameCols (FRAME_TTY (f)) = new_cols;
467 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
468 if (WINDOWP (f->tool_bar_window))
470 XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
471 XWINDOW (f->tool_bar_window)->total_cols
472 = new_windows_width / unit_width;
474 #endif
477 if (new_windows_height != old_windows_height
478 /* When the top margin has changed we have to recalculate the top
479 edges of all windows. No such calculation is necessary for the
480 left edges. */
481 || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
483 resize_frame_windows (f, new_windows_height, 0, 1);
485 /* MSDOS frames cannot PRETEND, as they change frame size by
486 manipulating video hardware. */
487 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
488 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
491 /* Assign new sizes. */
492 FRAME_TEXT_WIDTH (f) = new_text_width;
493 FRAME_TEXT_HEIGHT (f) = new_text_height;
494 FRAME_PIXEL_WIDTH (f) = new_pixel_width;
495 FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
496 SET_FRAME_COLS (f, new_cols);
497 SET_FRAME_LINES (f, new_lines);
500 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
501 int text_area_x, text_area_y, text_area_width, text_area_height;
503 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
504 &text_area_height);
505 if (w->cursor.x >= text_area_x + text_area_width)
506 w->cursor.hpos = w->cursor.x = 0;
507 if (w->cursor.y >= text_area_y + text_area_height)
508 w->cursor.vpos = w->cursor.y = 0;
511 /* Sanitize window sizes. */
512 sanitize_window_sizes (frame, Qt);
513 sanitize_window_sizes (frame, Qnil);
515 adjust_frame_glyphs (f);
516 calculate_costs (f);
517 SET_FRAME_GARBAGED (f);
519 /* A frame was "resized" if one of its pixelsizes changed, even if its
520 X window wasn't resized at all. */
521 f->resized_p = (new_pixel_width != old_pixel_width
522 || new_pixel_height != old_pixel_height);
524 unblock_input ();
526 run_window_configuration_change_hook (f);
530 struct frame *
531 make_frame (bool mini_p)
533 Lisp_Object frame;
534 register struct frame *f;
535 register struct window *rw, *mw;
536 register Lisp_Object root_window;
537 register Lisp_Object mini_window;
539 f = allocate_frame ();
540 XSETFRAME (frame, f);
542 #ifdef USE_GTK
543 /* Initialize Lisp data. Note that allocate_frame initializes all
544 Lisp data to nil, so do it only for slots which should not be nil. */
545 fset_tool_bar_position (f, Qtop);
546 #endif
548 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
549 non-Lisp data, so do it only for slots which should not be zero.
550 To avoid subtle bugs and for the sake of readability, it's better to
551 initialize enum members explicitly even if their values are zero. */
552 f->wants_modeline = true;
553 f->redisplay = true;
554 f->garbaged = true;
555 f->can_x_set_window_size = false;
556 f->can_run_window_configuration_change_hook = false;
557 f->column_width = 1; /* !FRAME_WINDOW_P value. */
558 f->line_height = 1; /* !FRAME_WINDOW_P value. */
559 #ifdef HAVE_WINDOW_SYSTEM
560 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
561 f->horizontal_scroll_bars = false;
562 f->want_fullscreen = FULLSCREEN_NONE;
563 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
564 f->last_tool_bar_item = -1;
565 #endif
566 #endif
568 root_window = make_window ();
569 rw = XWINDOW (root_window);
570 if (mini_p)
572 mini_window = make_window ();
573 mw = XWINDOW (mini_window);
574 wset_next (rw, mini_window);
575 wset_prev (mw, root_window);
576 mw->mini = 1;
577 wset_frame (mw, frame);
578 fset_minibuffer_window (f, mini_window);
580 else
582 mini_window = Qnil;
583 wset_next (rw, Qnil);
584 fset_minibuffer_window (f, Qnil);
587 wset_frame (rw, frame);
589 /* 10 is arbitrary,
590 just so that there is "something there."
591 Correct size will be set up later with adjust_frame_size. */
593 SET_FRAME_COLS (f, 10);
594 SET_FRAME_LINES (f, 10);
595 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
596 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
598 rw->total_cols = 10;
599 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
600 rw->total_lines = mini_p ? 9 : 10;
601 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
603 if (mini_p)
605 mw->top_line = rw->total_lines;
606 mw->pixel_top = rw->pixel_height;
607 mw->total_cols = rw->total_cols;
608 mw->pixel_width = rw->pixel_width;
609 mw->total_lines = 1;
610 mw->pixel_height = FRAME_LINE_HEIGHT (f);
613 /* Choose a buffer for the frame's root window. */
615 Lisp_Object buf = Fcurrent_buffer ();
617 /* If current buffer is hidden, try to find another one. */
618 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
619 buf = other_buffer_safely (buf);
621 /* Use set_window_buffer, not Fset_window_buffer, and don't let
622 hooks be run by it. The reason is that the whole frame/window
623 arrangement is not yet fully initialized at this point. Windows
624 don't have the right size, glyph matrices aren't initialized
625 etc. Running Lisp functions at this point surely ends in a
626 SEGV. */
627 set_window_buffer (root_window, buf, 0, 0);
628 fset_buffer_list (f, list1 (buf));
631 if (mini_p)
633 set_window_buffer (mini_window,
634 (NILP (Vminibuffer_list)
635 ? get_minibuffer (0)
636 : Fcar (Vminibuffer_list)),
637 0, 0);
638 /* No horizontal scroll bars in minibuffers. */
639 wset_horizontal_scroll_bar (mw, Qnil);
642 fset_root_window (f, root_window);
643 fset_selected_window (f, root_window);
644 /* Make sure this window seems more recently used than
645 a newly-created, never-selected window. */
646 XWINDOW (f->selected_window)->use_time = ++window_select_count;
648 return f;
651 #ifdef HAVE_WINDOW_SYSTEM
652 /* Make a frame using a separate minibuffer window on another frame.
653 MINI_WINDOW is the minibuffer window to use. nil means use the
654 default (the global minibuffer). */
656 struct frame *
657 make_frame_without_minibuffer (register Lisp_Object mini_window, KBOARD *kb, Lisp_Object display)
659 register struct frame *f;
660 struct gcpro gcpro1;
662 if (!NILP (mini_window))
663 CHECK_LIVE_WINDOW (mini_window);
665 if (!NILP (mini_window)
666 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
667 error ("Frame and minibuffer must be on the same terminal");
669 /* Make a frame containing just a root window. */
670 f = make_frame (0);
672 if (NILP (mini_window))
674 /* Use default-minibuffer-frame if possible. */
675 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
676 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
678 Lisp_Object frame_dummy;
680 XSETFRAME (frame_dummy, f);
681 GCPRO1 (frame_dummy);
682 /* If there's no minibuffer frame to use, create one. */
683 kset_default_minibuffer_frame
684 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
685 UNGCPRO;
688 mini_window
689 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
692 fset_minibuffer_window (f, mini_window);
694 /* Make the chosen minibuffer window display the proper minibuffer,
695 unless it is already showing a minibuffer. */
696 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
697 /* Use set_window_buffer instead of Fset_window_buffer (see
698 discussion of bug#11984, bug#12025, bug#12026). */
699 set_window_buffer (mini_window,
700 (NILP (Vminibuffer_list)
701 ? get_minibuffer (0)
702 : Fcar (Vminibuffer_list)), 0, 0);
703 return f;
706 /* Make a frame containing only a minibuffer window. */
708 struct frame *
709 make_minibuffer_frame (void)
711 /* First make a frame containing just a root window, no minibuffer. */
713 register struct frame *f = make_frame (0);
714 register Lisp_Object mini_window;
715 register Lisp_Object frame;
717 XSETFRAME (frame, f);
719 f->auto_raise = 0;
720 f->auto_lower = 0;
721 f->no_split = 1;
722 f->wants_modeline = 0;
724 /* Now label the root window as also being the minibuffer.
725 Avoid infinite looping on the window chain by marking next pointer
726 as nil. */
728 mini_window = f->root_window;
729 fset_minibuffer_window (f, mini_window);
730 XWINDOW (mini_window)->mini = 1;
731 wset_next (XWINDOW (mini_window), Qnil);
732 wset_prev (XWINDOW (mini_window), Qnil);
733 wset_frame (XWINDOW (mini_window), frame);
735 /* Put the proper buffer in that window. */
737 /* Use set_window_buffer instead of Fset_window_buffer (see
738 discussion of bug#11984, bug#12025, bug#12026). */
739 set_window_buffer (mini_window,
740 (NILP (Vminibuffer_list)
741 ? get_minibuffer (0)
742 : Fcar (Vminibuffer_list)), 0, 0);
743 return f;
745 #endif /* HAVE_WINDOW_SYSTEM */
747 /* Construct a frame that refers to a terminal. */
749 static printmax_t tty_frame_count;
751 struct frame *
752 make_initial_frame (void)
754 struct frame *f;
755 struct terminal *terminal;
756 Lisp_Object frame;
758 eassert (initial_kboard);
760 /* The first call must initialize Vframe_list. */
761 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
762 Vframe_list = Qnil;
764 terminal = init_initial_terminal ();
766 f = make_frame (1);
767 XSETFRAME (frame, f);
769 Vframe_list = Fcons (frame, Vframe_list);
771 tty_frame_count = 1;
772 fset_name (f, build_pure_c_string ("F1"));
774 SET_FRAME_VISIBLE (f, 1);
776 f->output_method = terminal->type;
777 f->terminal = terminal;
778 f->terminal->reference_count++;
779 f->output_data.nothing = 0;
781 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
782 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
784 #ifdef HAVE_WINDOW_SYSTEM
785 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
786 f->horizontal_scroll_bars = false;
787 #endif
789 /* The default value of menu-bar-mode is t. */
790 set_menu_bar_lines (f, make_number (1), Qnil);
792 if (!noninteractive)
793 init_frame_faces (f);
795 last_nonminibuf_frame = f;
797 return f;
801 static struct frame *
802 make_terminal_frame (struct terminal *terminal)
804 register struct frame *f;
805 Lisp_Object frame;
806 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
808 if (!terminal->name)
809 error ("Terminal is not live, can't create new frames on it");
811 f = make_frame (1);
813 XSETFRAME (frame, f);
814 Vframe_list = Fcons (frame, Vframe_list);
816 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
818 SET_FRAME_VISIBLE (f, 1);
820 f->terminal = terminal;
821 f->terminal->reference_count++;
822 #ifdef MSDOS
823 f->output_data.tty->display_info = &the_only_display_info;
824 if (!inhibit_window_system
825 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
826 || XFRAME (selected_frame)->output_method == output_msdos_raw))
827 f->output_method = output_msdos_raw;
828 else
829 f->output_method = output_termcap;
830 #else /* not MSDOS */
831 f->output_method = output_termcap;
832 create_tty_output (f);
833 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
834 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
835 #endif /* not MSDOS */
837 #ifdef HAVE_WINDOW_SYSTEM
838 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
839 f->horizontal_scroll_bars = false;
840 #endif
842 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
843 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
844 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
845 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
847 /* Set the top frame to the newly created frame. */
848 if (FRAMEP (FRAME_TTY (f)->top_frame)
849 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
850 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
852 FRAME_TTY (f)->top_frame = frame;
854 if (!noninteractive)
855 init_frame_faces (f);
857 return f;
860 /* Get a suitable value for frame parameter PARAMETER for a newly
861 created frame, based on (1) the user-supplied frame parameter
862 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
864 static Lisp_Object
865 get_future_frame_param (Lisp_Object parameter,
866 Lisp_Object supplied_parms,
867 char *current_value)
869 Lisp_Object result;
871 result = Fassq (parameter, supplied_parms);
872 if (NILP (result))
873 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
874 if (NILP (result) && current_value != NULL)
875 result = build_string (current_value);
876 if (!NILP (result) && !STRINGP (result))
877 result = XCDR (result);
878 if (NILP (result) || !STRINGP (result))
879 result = Qnil;
881 return result;
884 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
885 1, 1, 0,
886 doc: /* Create an additional terminal frame, possibly on another terminal.
887 This function takes one argument, an alist specifying frame parameters.
889 You can create multiple frames on a single text terminal, but only one
890 of them (the selected terminal frame) is actually displayed.
892 In practice, generally you don't need to specify any parameters,
893 except when you want to create a new frame on another terminal.
894 In that case, the `tty' parameter specifies the device file to open,
895 and the `tty-type' parameter specifies the terminal type. Example:
897 (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
899 Note that changing the size of one terminal frame automatically
900 affects all frames on the same terminal device. */)
901 (Lisp_Object parms)
903 struct frame *f;
904 struct terminal *t = NULL;
905 Lisp_Object frame, tem;
906 struct frame *sf = SELECTED_FRAME ();
908 #ifdef MSDOS
909 if (sf->output_method != output_msdos_raw
910 && sf->output_method != output_termcap)
911 emacs_abort ();
912 #else /* not MSDOS */
914 #ifdef WINDOWSNT /* This should work now! */
915 if (sf->output_method != output_termcap)
916 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
917 #endif
918 #endif /* not MSDOS */
921 Lisp_Object terminal;
923 terminal = Fassq (Qterminal, parms);
924 if (CONSP (terminal))
926 terminal = XCDR (terminal);
927 t = decode_live_terminal (terminal);
929 #ifdef MSDOS
930 if (t && t != the_only_display_info.terminal)
931 /* msdos.c assumes a single tty_display_info object. */
932 error ("Multiple terminals are not supported on this platform");
933 if (!t)
934 t = the_only_display_info.terminal;
935 #endif
938 if (!t)
940 char *name = 0, *type = 0;
941 Lisp_Object tty, tty_type;
942 USE_SAFE_ALLOCA;
944 tty = get_future_frame_param
945 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
946 ? FRAME_TTY (XFRAME (selected_frame))->name
947 : NULL));
948 if (!NILP (tty))
949 SAFE_ALLOCA_STRING (name, tty);
951 tty_type = get_future_frame_param
952 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
953 ? FRAME_TTY (XFRAME (selected_frame))->type
954 : NULL));
955 if (!NILP (tty_type))
956 SAFE_ALLOCA_STRING (type, tty_type);
958 t = init_tty (name, type, 0); /* Errors are not fatal. */
959 SAFE_FREE ();
962 f = make_terminal_frame (t);
965 int width, height;
966 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
967 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil);
970 adjust_frame_glyphs (f);
971 calculate_costs (f);
972 XSETFRAME (frame, f);
974 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
975 store_in_alist (&parms, Qtty,
976 (t->display_info.tty->name
977 ? build_string (t->display_info.tty->name)
978 : Qnil));
979 Fmodify_frame_parameters (frame, parms);
981 /* Make the frame face alist be frame-specific, so that each
982 frame could change its face definitions independently. */
983 fset_face_alist (f, Fcopy_alist (sf->face_alist));
984 /* Simple Fcopy_alist isn't enough, because we need the contents of
985 the vectors which are the CDRs of associations in face_alist to
986 be copied as well. */
987 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
988 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
989 return frame;
993 /* Perform the switch to frame FRAME.
995 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
996 FRAME1 as frame.
998 If TRACK is non-zero and the frame that currently has the focus
999 redirects its focus to the selected frame, redirect that focused
1000 frame's focus to FRAME instead.
1002 FOR_DELETION non-zero means that the selected frame is being
1003 deleted, which includes the possibility that the frame's terminal
1004 is dead.
1006 The value of NORECORD is passed as argument to Fselect_window. */
1008 Lisp_Object
1009 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1011 struct frame *sf = SELECTED_FRAME ();
1013 /* If FRAME is a switch-frame event, extract the frame we should
1014 switch to. */
1015 if (CONSP (frame)
1016 && EQ (XCAR (frame), Qswitch_frame)
1017 && CONSP (XCDR (frame)))
1018 frame = XCAR (XCDR (frame));
1020 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1021 a switch-frame event to arrive after a frame is no longer live,
1022 especially when deleting the initial frame during startup. */
1023 CHECK_FRAME (frame);
1024 if (! FRAME_LIVE_P (XFRAME (frame)))
1025 return Qnil;
1027 if (sf == XFRAME (frame))
1028 return frame;
1030 /* If a frame's focus has been redirected toward the currently
1031 selected frame, we should change the redirection to point to the
1032 newly selected frame. This means that if the focus is redirected
1033 from a minibufferless frame to a surrogate minibuffer frame, we
1034 can use `other-window' to switch between all the frames using
1035 that minibuffer frame, and the focus redirection will follow us
1036 around. */
1037 #if 0
1038 /* This is too greedy; it causes inappropriate focus redirection
1039 that's hard to get rid of. */
1040 if (track)
1042 Lisp_Object tail;
1044 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1046 Lisp_Object focus;
1048 if (!FRAMEP (XCAR (tail)))
1049 emacs_abort ();
1051 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1053 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1054 Fredirect_frame_focus (XCAR (tail), frame);
1057 #else /* ! 0 */
1058 /* Instead, apply it only to the frame we're pointing to. */
1059 #ifdef HAVE_WINDOW_SYSTEM
1060 if (track && FRAME_WINDOW_P (XFRAME (frame)))
1062 Lisp_Object focus, xfocus;
1064 xfocus = x_get_focus_frame (XFRAME (frame));
1065 if (FRAMEP (xfocus))
1067 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1068 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1069 Fredirect_frame_focus (xfocus, frame);
1072 #endif /* HAVE_X_WINDOWS */
1073 #endif /* ! 0 */
1075 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1076 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1078 if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame)))
1080 struct frame *f = XFRAME (frame);
1081 struct tty_display_info *tty = FRAME_TTY (f);
1082 Lisp_Object top_frame = tty->top_frame;
1084 /* Don't mark the frame garbaged and/or obscured if we are
1085 switching to the frame that is already the top frame of that
1086 TTY. */
1087 if (!EQ (frame, top_frame))
1089 if (FRAMEP (top_frame))
1090 /* Mark previously displayed frame as now obscured. */
1091 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1092 SET_FRAME_VISIBLE (f, 1);
1093 /* If the new TTY frame changed dimensions, we need to
1094 resync term.c's idea of the frame size with the new
1095 frame's data. */
1096 if (FRAME_COLS (f) != FrameCols (tty))
1097 FrameCols (tty) = FRAME_COLS (f);
1098 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1099 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1101 tty->top_frame = frame;
1104 selected_frame = frame;
1105 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1106 last_nonminibuf_frame = XFRAME (selected_frame);
1108 Fselect_window (XFRAME (frame)->selected_window, norecord);
1110 /* We want to make sure that the next event generates a frame-switch
1111 event to the appropriate frame. This seems kludgy to me, but
1112 before you take it out, make sure that evaluating something like
1113 (select-window (frame-root-window (new-frame))) doesn't end up
1114 with your typing being interpreted in the new frame instead of
1115 the one you're actually typing in. */
1116 internal_last_event_frame = Qnil;
1118 return frame;
1121 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1122 doc: /* Select FRAME.
1123 Subsequent editing commands apply to its selected window.
1124 Optional argument NORECORD means to neither change the order of
1125 recently selected windows nor the buffer list.
1127 The selection of FRAME lasts until the next time the user does
1128 something to select a different frame, or until the next time
1129 this function is called. If you are using a window system, the
1130 previously selected frame may be restored as the selected frame
1131 when returning to the command loop, because it still may have
1132 the window system's input focus. On a text terminal, the next
1133 redisplay will display FRAME.
1135 This function returns FRAME, or nil if FRAME has been deleted. */)
1136 (Lisp_Object frame, Lisp_Object norecord)
1138 return do_switch_frame (frame, 1, 0, norecord);
1141 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1142 doc: /* Handle a switch-frame event EVENT.
1143 Switch-frame events are usually bound to this function.
1144 A switch-frame event tells Emacs that the window manager has requested
1145 that the user's events be directed to the frame mentioned in the event.
1146 This function selects the selected window of the frame of EVENT.
1148 If EVENT is frame object, handle it as if it were a switch-frame event
1149 to that frame. */)
1150 (Lisp_Object event)
1152 /* Preserve prefix arg that the command loop just cleared. */
1153 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1154 run_hook (Qmouse_leave_buffer_hook);
1155 /* `switch-frame' implies a focus in. */
1156 call1 (intern ("handle-focus-in"), event);
1157 return do_switch_frame (event, 0, 0, Qnil);
1160 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1161 doc: /* Return the frame that is now selected. */)
1162 (void)
1164 return selected_frame;
1167 DEFUN ("frame-list", Fframe_list, Sframe_list,
1168 0, 0, 0,
1169 doc: /* Return a list of all live frames. */)
1170 (void)
1172 Lisp_Object frames;
1173 frames = Fcopy_sequence (Vframe_list);
1174 #ifdef HAVE_WINDOW_SYSTEM
1175 if (FRAMEP (tip_frame))
1176 frames = Fdelq (tip_frame, frames);
1177 #endif
1178 return frames;
1181 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1182 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1183 If MINIBUF is nil, do not consider minibuffer-only candidate.
1184 If MINIBUF is `visible', do not consider an invisible candidate.
1185 If MINIBUF is a window, consider only its own frame and candidate now
1186 using that window as the minibuffer.
1187 If MINIBUF is 0, consider candidate if it is visible or iconified.
1188 Otherwise consider any candidate and return nil if CANDIDATE is not
1189 acceptable. */
1191 static Lisp_Object
1192 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1194 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1196 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1197 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1198 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1199 && FRAME_TTY (c) == FRAME_TTY (f)))
1201 if (NILP (minibuf))
1203 if (!FRAME_MINIBUF_ONLY_P (c))
1204 return candidate;
1206 else if (EQ (minibuf, Qvisible))
1208 if (FRAME_VISIBLE_P (c))
1209 return candidate;
1211 else if (WINDOWP (minibuf))
1213 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1214 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1215 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1216 FRAME_FOCUS_FRAME (c)))
1217 return candidate;
1219 else if (XFASTINT (minibuf) == 0)
1221 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1222 return candidate;
1224 else
1225 return candidate;
1227 return Qnil;
1230 /* Return the next frame in the frame list after FRAME. */
1232 static Lisp_Object
1233 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1235 Lisp_Object f, tail;
1236 int passed = 0;
1238 /* There must always be at least one frame in Vframe_list. */
1239 eassert (CONSP (Vframe_list));
1241 while (passed < 2)
1242 FOR_EACH_FRAME (tail, f)
1244 if (passed)
1246 f = candidate_frame (f, frame, minibuf);
1247 if (!NILP (f))
1248 return f;
1250 if (EQ (frame, f))
1251 passed++;
1253 return frame;
1256 /* Return the previous frame in the frame list before FRAME. */
1258 static Lisp_Object
1259 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1261 Lisp_Object f, tail, prev = Qnil;
1263 /* There must always be at least one frame in Vframe_list. */
1264 eassert (CONSP (Vframe_list));
1266 FOR_EACH_FRAME (tail, f)
1268 if (EQ (frame, f) && !NILP (prev))
1269 return prev;
1270 f = candidate_frame (f, frame, minibuf);
1271 if (!NILP (f))
1272 prev = f;
1275 /* We've scanned the entire list. */
1276 if (NILP (prev))
1277 /* We went through the whole frame list without finding a single
1278 acceptable frame. Return the original frame. */
1279 return frame;
1280 else
1281 /* There were no acceptable frames in the list before FRAME; otherwise,
1282 we would have returned directly from the loop. Since PREV is the last
1283 acceptable frame in the list, return it. */
1284 return prev;
1288 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1289 doc: /* Return the next frame in the frame list after FRAME.
1290 It considers only frames on the same terminal as FRAME.
1291 By default, skip minibuffer-only frames.
1292 If omitted, FRAME defaults to the selected frame.
1293 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1294 If MINIFRAME is a window, include only its own frame
1295 and any frame now using that window as the minibuffer.
1296 If MINIFRAME is `visible', include all visible frames.
1297 If MINIFRAME is 0, include all visible and iconified frames.
1298 Otherwise, include all frames. */)
1299 (Lisp_Object frame, Lisp_Object miniframe)
1301 if (NILP (frame))
1302 frame = selected_frame;
1303 CHECK_LIVE_FRAME (frame);
1304 return next_frame (frame, miniframe);
1307 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1308 doc: /* Return the previous frame in the frame list before FRAME.
1309 It considers only frames on the same terminal as FRAME.
1310 By default, skip minibuffer-only frames.
1311 If omitted, FRAME defaults to the selected frame.
1312 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1313 If MINIFRAME is a window, include only its own frame
1314 and any frame now using that window as the minibuffer.
1315 If MINIFRAME is `visible', include all visible frames.
1316 If MINIFRAME is 0, include all visible and iconified frames.
1317 Otherwise, include all frames. */)
1318 (Lisp_Object frame, Lisp_Object miniframe)
1320 if (NILP (frame))
1321 frame = selected_frame;
1322 CHECK_LIVE_FRAME (frame);
1323 return prev_frame (frame, miniframe);
1326 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1327 Slast_nonminibuf_frame, 0, 0, 0,
1328 doc: /* Return last non-minibuffer frame selected. */)
1329 (void)
1331 Lisp_Object frame = Qnil;
1333 if (last_nonminibuf_frame)
1334 XSETFRAME (frame, last_nonminibuf_frame);
1336 return frame;
1339 /* Return 1 if it is ok to delete frame F;
1340 0 if all frames aside from F are invisible.
1341 (Exception: if F is the terminal frame, and we are using X, return 1.) */
1343 static int
1344 other_visible_frames (struct frame *f)
1346 Lisp_Object frames, this;
1348 FOR_EACH_FRAME (frames, this)
1350 if (f == XFRAME (this))
1351 continue;
1353 /* Verify that we can still talk to the frame's X window,
1354 and note any recent change in visibility. */
1355 #ifdef HAVE_X_WINDOWS
1356 if (FRAME_WINDOW_P (XFRAME (this)))
1357 x_sync (XFRAME (this));
1358 #endif
1360 if (FRAME_VISIBLE_P (XFRAME (this))
1361 || FRAME_ICONIFIED_P (XFRAME (this))
1362 /* Allow deleting the terminal frame when at least one X
1363 frame exists. */
1364 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
1365 return 1;
1367 return 0;
1370 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1371 window. Preferably use the selected frame's minibuffer window
1372 instead. If the selected frame doesn't have one, get some other
1373 frame's minibuffer window. SELECT non-zero means select the new
1374 minibuffer window. */
1375 static void
1376 check_minibuf_window (Lisp_Object frame, int select)
1378 struct frame *f = decode_live_frame (frame);
1380 XSETFRAME (frame, f);
1382 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1384 Lisp_Object frames, this, window = make_number (0);
1386 if (!EQ (frame, selected_frame)
1387 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1388 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1389 else
1390 FOR_EACH_FRAME (frames, this)
1392 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1394 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1395 break;
1399 /* Don't abort if no window was found (Bug#15247). */
1400 if (WINDOWP (window))
1402 /* Use set_window_buffer instead of Fset_window_buffer (see
1403 discussion of bug#11984, bug#12025, bug#12026). */
1404 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1405 minibuf_window = window;
1407 /* SELECT non-zero usually means that FRAME's minibuffer
1408 window was selected; select the new one. */
1409 if (select)
1410 Fselect_window (minibuf_window, Qnil);
1416 /* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1417 unconditionally. x_connection_closed and delete_terminal use
1418 this. Any other value of FORCE implements the semantics
1419 described for Fdelete_frame. */
1420 Lisp_Object
1421 delete_frame (Lisp_Object frame, Lisp_Object force)
1423 struct frame *f = decode_any_frame (frame);
1424 struct frame *sf;
1425 struct kboard *kb;
1427 int minibuffer_selected, is_tooltip_frame;
1429 if (! FRAME_LIVE_P (f))
1430 return Qnil;
1432 if (NILP (force) && !other_visible_frames (f))
1433 error ("Attempt to delete the sole visible or iconified frame");
1435 /* x_connection_closed must have set FORCE to `noelisp' in order
1436 to delete the last frame, if it is gone. */
1437 if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp))
1438 error ("Attempt to delete the only frame");
1440 XSETFRAME (frame, f);
1442 /* Does this frame have a minibuffer, and is it the surrogate
1443 minibuffer for any other frame? */
1444 if (FRAME_HAS_MINIBUF_P (f))
1446 Lisp_Object frames, this;
1448 FOR_EACH_FRAME (frames, this)
1450 Lisp_Object fminiw;
1452 if (EQ (this, frame))
1453 continue;
1455 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (this));
1457 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1459 /* If we MUST delete this frame, delete the other first.
1460 But do this only if FORCE equals `noelisp'. */
1461 if (EQ (force, Qnoelisp))
1462 delete_frame (this, Qnoelisp);
1463 else
1464 error ("Attempt to delete a surrogate minibuffer frame");
1469 is_tooltip_frame = !NILP (Fframe_parameter (frame, intern ("tooltip")));
1471 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1472 frame is a tooltip. FORCE is set to `noelisp' when handling
1473 a disconnect from the terminal, so we don't dare call Lisp
1474 code. */
1475 if (NILP (Vrun_hooks) || is_tooltip_frame)
1477 else if (EQ (force, Qnoelisp))
1478 pending_funcalls
1479 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1480 pending_funcalls);
1481 else
1483 #ifdef HAVE_X_WINDOWS
1484 /* Also, save clipboard to the clipboard manager. */
1485 x_clipboard_manager_save_frame (frame);
1486 #endif
1488 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1491 /* The hook may sometimes (indirectly) cause the frame to be deleted. */
1492 if (! FRAME_LIVE_P (f))
1493 return Qnil;
1495 /* At this point, we are committed to deleting the frame.
1496 There is no more chance for errors to prevent it. */
1498 minibuffer_selected = EQ (minibuf_window, selected_window);
1499 sf = SELECTED_FRAME ();
1500 /* Don't let the frame remain selected. */
1501 if (f == sf)
1503 Lisp_Object tail;
1504 Lisp_Object frame1 = Qnil;
1506 /* Look for another visible frame on the same terminal.
1507 Do not call next_frame here because it may loop forever.
1508 See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1509 FOR_EACH_FRAME (tail, frame1)
1510 if (!EQ (frame, frame1)
1511 && (FRAME_TERMINAL (XFRAME (frame))
1512 == FRAME_TERMINAL (XFRAME (frame1)))
1513 && FRAME_VISIBLE_P (XFRAME (frame1)))
1514 break;
1516 /* If there is none, find *some* other frame. */
1517 if (NILP (frame1) || EQ (frame1, frame))
1519 FOR_EACH_FRAME (tail, frame1)
1521 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
1523 /* Do not change a text terminal's top-frame. */
1524 struct frame *f1 = XFRAME (frame1);
1525 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1527 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1528 if (!EQ (top_frame, frame))
1529 frame1 = top_frame;
1531 break;
1535 #ifdef NS_IMPL_COCOA
1536 else
1537 /* Under NS, there is no system mechanism for choosing a new
1538 window to get focus -- it is left to application code.
1539 So the portion of THIS application interfacing with NS
1540 needs to know about it. We call Fraise_frame, but the
1541 purpose is really to transfer focus. */
1542 Fraise_frame (frame1);
1543 #endif
1545 do_switch_frame (frame1, 0, 1, Qnil);
1546 sf = SELECTED_FRAME ();
1549 /* Don't allow minibuf_window to remain on a deleted frame. */
1550 check_minibuf_window (frame, minibuffer_selected);
1552 /* Don't let echo_area_window to remain on a deleted frame. */
1553 if (EQ (f->minibuffer_window, echo_area_window))
1554 echo_area_window = sf->minibuffer_window;
1556 /* Clear any X selections for this frame. */
1557 #ifdef HAVE_X_WINDOWS
1558 if (FRAME_X_P (f))
1559 x_clear_frame_selections (f);
1560 #endif
1562 /* Free glyphs.
1563 This function must be called before the window tree of the
1564 frame is deleted because windows contain dynamically allocated
1565 memory. */
1566 free_glyphs (f);
1568 #ifdef HAVE_WINDOW_SYSTEM
1569 /* Give chance to each font driver to free a frame specific data. */
1570 font_update_drivers (f, Qnil);
1571 #endif
1573 /* Mark all the windows that used to be on FRAME as deleted, and then
1574 remove the reference to them. */
1575 delete_all_child_windows (f->root_window);
1576 fset_root_window (f, Qnil);
1578 Vframe_list = Fdelq (frame, Vframe_list);
1579 SET_FRAME_VISIBLE (f, 0);
1581 /* Allow the vector of menu bar contents to be freed in the next
1582 garbage collection. The frame object itself may not be garbage
1583 collected until much later, because recent_keys and other data
1584 structures can still refer to it. */
1585 fset_menu_bar_vector (f, Qnil);
1587 /* If FRAME's buffer lists contains killed
1588 buffers, this helps GC to reclaim them. */
1589 fset_buffer_list (f, Qnil);
1590 fset_buried_buffer_list (f, Qnil);
1592 free_font_driver_list (f);
1593 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1594 xfree (f->namebuf);
1595 #endif
1596 xfree (f->decode_mode_spec_buffer);
1597 xfree (FRAME_INSERT_COST (f));
1598 xfree (FRAME_DELETEN_COST (f));
1599 xfree (FRAME_INSERTN_COST (f));
1600 xfree (FRAME_DELETE_COST (f));
1602 /* Since some events are handled at the interrupt level, we may get
1603 an event for f at any time; if we zero out the frame's terminal
1604 now, then we may trip up the event-handling code. Instead, we'll
1605 promise that the terminal of the frame must be valid until we
1606 have called the window-system-dependent frame destruction
1607 routine. */
1611 struct terminal *terminal;
1612 block_input ();
1613 if (FRAME_TERMINAL (f)->delete_frame_hook)
1614 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
1615 terminal = FRAME_TERMINAL (f);
1616 f->output_data.nothing = 0;
1617 f->terminal = 0; /* Now the frame is dead. */
1618 unblock_input ();
1620 /* If needed, delete the terminal that this frame was on.
1621 (This must be done after the frame is killed.) */
1622 terminal->reference_count--;
1623 #ifdef USE_GTK
1624 /* FIXME: Deleting the terminal crashes emacs because of a GTK
1625 bug.
1626 http://lists.gnu.org/archive/html/emacs-devel/2011-10/msg00363.html */
1627 if (terminal->reference_count == 0 && terminal->type == output_x_window)
1628 terminal->reference_count = 1;
1629 #endif /* USE_GTK */
1630 if (terminal->reference_count == 0)
1632 Lisp_Object tmp;
1633 XSETTERMINAL (tmp, terminal);
1635 kb = NULL;
1636 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
1638 else
1639 kb = terminal->kboard;
1642 /* If we've deleted the last_nonminibuf_frame, then try to find
1643 another one. */
1644 if (f == last_nonminibuf_frame)
1646 Lisp_Object frames, this;
1648 last_nonminibuf_frame = 0;
1650 FOR_EACH_FRAME (frames, this)
1652 f = XFRAME (this);
1653 if (!FRAME_MINIBUF_ONLY_P (f))
1655 last_nonminibuf_frame = f;
1656 break;
1661 /* If there's no other frame on the same kboard, get out of
1662 single-kboard state if we're in it for this kboard. */
1663 if (kb != NULL)
1665 Lisp_Object frames, this;
1666 /* Some frame we found on the same kboard, or nil if there are none. */
1667 Lisp_Object frame_on_same_kboard = Qnil;
1669 FOR_EACH_FRAME (frames, this)
1670 if (kb == FRAME_KBOARD (XFRAME (this)))
1671 frame_on_same_kboard = this;
1673 if (NILP (frame_on_same_kboard))
1674 not_single_kboard_state (kb);
1678 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1679 find another one. Prefer minibuffer-only frames, but also notice
1680 frames with other windows. */
1681 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
1683 Lisp_Object frames, this;
1685 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
1686 Lisp_Object frame_with_minibuf = Qnil;
1687 /* Some frame we found on the same kboard, or nil if there are none. */
1688 Lisp_Object frame_on_same_kboard = Qnil;
1690 FOR_EACH_FRAME (frames, this)
1692 struct frame *f1 = XFRAME (this);
1694 /* Consider only frames on the same kboard
1695 and only those with minibuffers. */
1696 if (kb == FRAME_KBOARD (f1)
1697 && FRAME_HAS_MINIBUF_P (f1))
1699 frame_with_minibuf = this;
1700 if (FRAME_MINIBUF_ONLY_P (f1))
1701 break;
1704 if (kb == FRAME_KBOARD (f1))
1705 frame_on_same_kboard = this;
1708 if (!NILP (frame_on_same_kboard))
1710 /* We know that there must be some frame with a minibuffer out
1711 there. If this were not true, all of the frames present
1712 would have to be minibufferless, which implies that at some
1713 point their minibuffer frames must have been deleted, but
1714 that is prohibited at the top; you can't delete surrogate
1715 minibuffer frames. */
1716 if (NILP (frame_with_minibuf))
1717 emacs_abort ();
1719 kset_default_minibuffer_frame (kb, frame_with_minibuf);
1721 else
1722 /* No frames left on this kboard--say no minibuffer either. */
1723 kset_default_minibuffer_frame (kb, Qnil);
1726 /* Cause frame titles to update--necessary if we now have just one frame. */
1727 if (!is_tooltip_frame)
1728 update_mode_lines = 15;
1730 return Qnil;
1733 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
1734 doc: /* Delete FRAME, permanently eliminating it from use.
1735 FRAME defaults to the selected frame.
1737 A frame may not be deleted if its minibuffer is used by other frames.
1738 Normally, you may not delete a frame if all other frames are invisible,
1739 but if the second optional argument FORCE is non-nil, you may do so.
1741 This function runs `delete-frame-functions' before actually
1742 deleting the frame, unless the frame is a tooltip.
1743 The functions are run with one argument, the frame to be deleted. */)
1744 (Lisp_Object frame, Lisp_Object force)
1746 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
1750 /* Return mouse position in character cell units. */
1752 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
1753 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1754 The position is given in canonical character cells, where (0, 0) is the
1755 upper-left corner of the frame, X is the horizontal offset, and Y is the
1756 vertical offset, measured in units of the frame's default character size.
1757 If Emacs is running on a mouseless terminal or hasn't been programmed
1758 to read the mouse position, it returns the selected frame for FRAME
1759 and nil for X and Y.
1760 If `mouse-position-function' is non-nil, `mouse-position' calls it,
1761 passing the normal return value to that function as an argument,
1762 and returns whatever that function returns. */)
1763 (void)
1765 struct frame *f;
1766 Lisp_Object lispy_dummy;
1767 Lisp_Object x, y, retval;
1768 struct gcpro gcpro1;
1770 f = SELECTED_FRAME ();
1771 x = y = Qnil;
1773 /* It's okay for the hook to refrain from storing anything. */
1774 if (FRAME_TERMINAL (f)->mouse_position_hook)
1776 enum scroll_bar_part party_dummy;
1777 Time time_dummy;
1778 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1779 &lispy_dummy, &party_dummy,
1780 &x, &y,
1781 &time_dummy);
1784 if (! NILP (x))
1786 int col = XINT (x);
1787 int row = XINT (y);
1788 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
1789 XSETINT (x, col);
1790 XSETINT (y, row);
1792 XSETFRAME (lispy_dummy, f);
1793 retval = Fcons (lispy_dummy, Fcons (x, y));
1794 GCPRO1 (retval);
1795 if (!NILP (Vmouse_position_function))
1796 retval = call1 (Vmouse_position_function, retval);
1797 RETURN_UNGCPRO (retval);
1800 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
1801 Smouse_pixel_position, 0, 0, 0,
1802 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1803 The position is given in pixel units, where (0, 0) is the
1804 upper-left corner of the frame, X is the horizontal offset, and Y is
1805 the vertical offset.
1806 If Emacs is running on a mouseless terminal or hasn't been programmed
1807 to read the mouse position, it returns the selected frame for FRAME
1808 and nil for X and Y. */)
1809 (void)
1811 struct frame *f;
1812 Lisp_Object lispy_dummy;
1813 Lisp_Object x, y, retval;
1814 struct gcpro gcpro1;
1816 f = SELECTED_FRAME ();
1817 x = y = Qnil;
1819 /* It's okay for the hook to refrain from storing anything. */
1820 if (FRAME_TERMINAL (f)->mouse_position_hook)
1822 enum scroll_bar_part party_dummy;
1823 Time time_dummy;
1824 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1825 &lispy_dummy, &party_dummy,
1826 &x, &y,
1827 &time_dummy);
1830 XSETFRAME (lispy_dummy, f);
1831 retval = Fcons (lispy_dummy, Fcons (x, y));
1832 GCPRO1 (retval);
1833 if (!NILP (Vmouse_position_function))
1834 retval = call1 (Vmouse_position_function, retval);
1835 RETURN_UNGCPRO (retval);
1838 #ifdef HAVE_WINDOW_SYSTEM
1840 /* On frame F, convert character coordinates X and Y to pixel
1841 coordinates *PIX_X and *PIX_Y. */
1843 static void
1844 frame_char_to_pixel_position (struct frame *f, int x, int y,
1845 int *pix_x, int *pix_y)
1847 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
1848 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
1850 if (*pix_x < 0)
1851 *pix_x = 0;
1852 if (*pix_x > FRAME_PIXEL_WIDTH (f))
1853 *pix_x = FRAME_PIXEL_WIDTH (f);
1855 if (*pix_y < 0)
1856 *pix_y = 0;
1857 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
1858 *pix_y = FRAME_PIXEL_HEIGHT (f);
1861 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
1863 static void
1864 frame_set_mouse_position (struct frame *f, int x, int y)
1866 int pix_x, pix_y;
1868 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
1869 frame_set_mouse_pixel_position (f, pix_x, pix_y);
1872 #endif /* HAVE_WINDOW_SYSTEM */
1874 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
1875 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
1876 Coordinates are relative to the frame, not a window,
1877 so the coordinates of the top left character in the frame
1878 may be nonzero due to left-hand scroll bars or the menu bar.
1880 The position is given in canonical character cells, where (0, 0) is
1881 the upper-left corner of the frame, X is the horizontal offset, and
1882 Y is the vertical offset, measured in units of the frame's default
1883 character size.
1885 This function is a no-op for an X frame that is not visible.
1886 If you have just created a frame, you must wait for it to become visible
1887 before calling this function on it, like this.
1888 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
1889 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
1891 CHECK_LIVE_FRAME (frame);
1892 CHECK_TYPE_RANGED_INTEGER (int, x);
1893 CHECK_TYPE_RANGED_INTEGER (int, y);
1895 /* I think this should be done with a hook. */
1896 #ifdef HAVE_WINDOW_SYSTEM
1897 if (FRAME_WINDOW_P (XFRAME (frame)))
1898 /* Warping the mouse will cause enternotify and focus events. */
1899 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
1900 #else
1901 #if defined (MSDOS)
1902 if (FRAME_MSDOS_P (XFRAME (frame)))
1904 Fselect_frame (frame, Qnil);
1905 mouse_moveto (XINT (x), XINT (y));
1907 #else
1908 #ifdef HAVE_GPM
1910 Fselect_frame (frame, Qnil);
1911 term_mouse_moveto (XINT (x), XINT (y));
1913 #endif
1914 #endif
1915 #endif
1917 return Qnil;
1920 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
1921 Sset_mouse_pixel_position, 3, 3, 0,
1922 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
1923 The position is given in pixels, where (0, 0) is the upper-left corner
1924 of the frame, X is the horizontal offset, and Y is the vertical offset.
1926 Note, this is a no-op for an X frame that is not visible.
1927 If you have just created a frame, you must wait for it to become visible
1928 before calling this function on it, like this.
1929 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
1930 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
1932 CHECK_LIVE_FRAME (frame);
1933 CHECK_TYPE_RANGED_INTEGER (int, x);
1934 CHECK_TYPE_RANGED_INTEGER (int, y);
1936 /* I think this should be done with a hook. */
1937 #ifdef HAVE_WINDOW_SYSTEM
1938 if (FRAME_WINDOW_P (XFRAME (frame)))
1939 /* Warping the mouse will cause enternotify and focus events. */
1940 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
1941 #else
1942 #if defined (MSDOS)
1943 if (FRAME_MSDOS_P (XFRAME (frame)))
1945 Fselect_frame (frame, Qnil);
1946 mouse_moveto (XINT (x), XINT (y));
1948 #else
1949 #ifdef HAVE_GPM
1951 Fselect_frame (frame, Qnil);
1952 term_mouse_moveto (XINT (x), XINT (y));
1954 #endif
1955 #endif
1956 #endif
1958 return Qnil;
1961 static void make_frame_visible_1 (Lisp_Object);
1963 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
1964 0, 1, "",
1965 doc: /* Make the frame FRAME visible (assuming it is an X window).
1966 If omitted, FRAME defaults to the currently selected frame. */)
1967 (Lisp_Object frame)
1969 struct frame *f = decode_live_frame (frame);
1971 /* I think this should be done with a hook. */
1972 #ifdef HAVE_WINDOW_SYSTEM
1973 if (FRAME_WINDOW_P (f))
1974 x_make_frame_visible (f);
1975 #endif
1977 make_frame_visible_1 (f->root_window);
1979 /* Make menu bar update for the Buffers and Frames menus. */
1980 /* windows_or_buffers_changed = 15; FIXME: Why? */
1982 XSETFRAME (frame, f);
1983 return frame;
1986 /* Update the display_time slot of the buffers shown in WINDOW
1987 and all its descendants. */
1989 static void
1990 make_frame_visible_1 (Lisp_Object window)
1992 struct window *w;
1994 for (; !NILP (window); window = w->next)
1996 w = XWINDOW (window);
1997 if (WINDOWP (w->contents))
1998 make_frame_visible_1 (w->contents);
1999 else
2000 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2004 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2005 0, 2, "",
2006 doc: /* Make the frame FRAME invisible.
2007 If omitted, FRAME defaults to the currently selected frame.
2008 On graphical displays, invisible frames are not updated and are
2009 usually not displayed at all, even in a window system's \"taskbar\".
2011 Normally you may not make FRAME invisible if all other frames are invisible,
2012 but if the second optional argument FORCE is non-nil, you may do so.
2014 This function has no effect on text terminal frames. Such frames are
2015 always considered visible, whether or not they are currently being
2016 displayed in the terminal. */)
2017 (Lisp_Object frame, Lisp_Object force)
2019 struct frame *f = decode_live_frame (frame);
2021 if (NILP (force) && !other_visible_frames (f))
2022 error ("Attempt to make invisible the sole visible or iconified frame");
2024 /* Don't allow minibuf_window to remain on an invisible frame. */
2025 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
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_invisible (f);
2031 #endif
2033 /* Make menu bar update for the Buffers and Frames menus. */
2034 windows_or_buffers_changed = 16;
2036 return Qnil;
2039 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2040 0, 1, "",
2041 doc: /* Make the frame FRAME into an icon.
2042 If omitted, FRAME defaults to the currently selected frame. */)
2043 (Lisp_Object frame)
2045 struct frame *f = decode_live_frame (frame);
2047 /* Don't allow minibuf_window to remain on an iconified frame. */
2048 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2050 /* I think this should be done with a hook. */
2051 #ifdef HAVE_WINDOW_SYSTEM
2052 if (FRAME_WINDOW_P (f))
2053 x_iconify_frame (f);
2054 #endif
2056 /* Make menu bar update for the Buffers and Frames menus. */
2057 windows_or_buffers_changed = 17;
2059 return Qnil;
2062 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2063 1, 1, 0,
2064 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2065 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2066 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2067 On graphical displays, invisible frames are not updated and are
2068 usually not displayed at all, even in a window system's \"taskbar\".
2070 If FRAME is a text terminal frame, this always returns t.
2071 Such frames are always considered visible, whether or not they are
2072 currently being displayed on the terminal. */)
2073 (Lisp_Object frame)
2075 CHECK_LIVE_FRAME (frame);
2077 if (FRAME_VISIBLE_P (XFRAME (frame)))
2078 return Qt;
2079 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2080 return Qicon;
2081 return Qnil;
2084 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2085 0, 0, 0,
2086 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2087 (void)
2089 Lisp_Object tail, frame, value = Qnil;
2091 FOR_EACH_FRAME (tail, frame)
2092 if (FRAME_VISIBLE_P (XFRAME (frame)))
2093 value = Fcons (frame, value);
2095 return value;
2099 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2100 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2101 If FRAME is invisible or iconified, make it visible.
2102 If you don't specify a frame, the selected frame is used.
2103 If Emacs is displaying on an ordinary terminal or some other device which
2104 doesn't support multiple overlapping frames, this function selects FRAME. */)
2105 (Lisp_Object frame)
2107 struct frame *f = decode_live_frame (frame);
2109 XSETFRAME (frame, f);
2111 if (FRAME_TERMCAP_P (f))
2112 /* On a text terminal select FRAME. */
2113 Fselect_frame (frame, Qnil);
2114 else
2115 /* Do like the documentation says. */
2116 Fmake_frame_visible (frame);
2118 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2119 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2121 return Qnil;
2124 /* Should we have a corresponding function called Flower_Power? */
2125 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2126 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2127 If you don't specify a frame, the selected frame is used.
2128 If Emacs is displaying on an ordinary terminal or some other device which
2129 doesn't support multiple overlapping frames, this function does nothing. */)
2130 (Lisp_Object frame)
2132 struct frame *f = decode_live_frame (frame);
2134 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2135 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2137 return Qnil;
2141 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2142 1, 2, 0,
2143 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2144 In other words, switch-frame events caused by events in FRAME will
2145 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2146 FOCUS-FRAME after reading an event typed at FRAME.
2148 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2149 frame again receives its own keystrokes.
2151 Focus redirection is useful for temporarily redirecting keystrokes to
2152 a surrogate minibuffer frame when a frame doesn't have its own
2153 minibuffer window.
2155 A frame's focus redirection can be changed by `select-frame'. If frame
2156 FOO is selected, and then a different frame BAR is selected, any
2157 frames redirecting their focus to FOO are shifted to redirect their
2158 focus to BAR. This allows focus redirection to work properly when the
2159 user switches from one frame to another using `select-window'.
2161 This means that a frame whose focus is redirected to itself is treated
2162 differently from a frame whose focus is redirected to nil; the former
2163 is affected by `select-frame', while the latter is not.
2165 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2166 (Lisp_Object frame, Lisp_Object focus_frame)
2168 /* Note that we don't check for a live frame here. It's reasonable
2169 to redirect the focus of a frame you're about to delete, if you
2170 know what other frame should receive those keystrokes. */
2171 struct frame *f = decode_any_frame (frame);
2173 if (! NILP (focus_frame))
2174 CHECK_LIVE_FRAME (focus_frame);
2176 fset_focus_frame (f, focus_frame);
2178 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2179 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2181 return Qnil;
2185 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2186 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2187 If FRAME is omitted or nil, the selected frame is used.
2188 Return nil if FRAME's focus is not redirected.
2189 See `redirect-frame-focus'. */)
2190 (Lisp_Object frame)
2192 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2195 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
2196 doc: /* Set the input focus to FRAME.
2197 FRAME nil means use the selected frame.
2198 If there is no window system support, this function does nothing. */)
2199 (Lisp_Object frame)
2201 #ifdef HAVE_WINDOW_SYSTEM
2202 x_focus_frame (decode_window_system_frame (frame));
2203 #endif
2204 return Qnil;
2207 DEFUN ("frame-can-run-window-configuration-change-hook",
2208 Fcan_run_window_configuration_change_hook,
2209 Scan_run_window_configuration_change_hook, 2, 2, 0,
2210 doc: /* Whether `window-configuration-change-hook' is run for frame FRAME.
2211 FRAME nil means use the selected frame. Second argument ALLOW non-nil
2212 means functions on `window-configuration-change-hook' are called
2213 whenever the window configuration of FRAME changes. ALLOW nil means
2214 these functions are not called.
2216 This function is currently called by `face-set-after-frame-default' only
2217 and should be otherwise used with utter care to avoid that running
2218 functions on `window-configuration-change-hook' is impeded forever. */)
2219 (Lisp_Object frame, Lisp_Object allow)
2221 struct frame *f = decode_live_frame (frame);
2223 f->can_run_window_configuration_change_hook = NILP (allow) ? false : true;
2224 return Qnil;
2228 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2230 void
2231 frames_discard_buffer (Lisp_Object buffer)
2233 Lisp_Object frame, tail;
2235 FOR_EACH_FRAME (tail, frame)
2237 fset_buffer_list
2238 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2239 fset_buried_buffer_list
2240 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2244 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2245 If the alist already has an element for PROP, we change it. */
2247 void
2248 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2250 register Lisp_Object tem;
2252 tem = Fassq (prop, *alistptr);
2253 if (EQ (tem, Qnil))
2254 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2255 else
2256 Fsetcdr (tem, val);
2259 static int
2260 frame_name_fnn_p (char *str, ptrdiff_t len)
2262 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2264 char *p = str + 2;
2265 while ('0' <= *p && *p <= '9')
2266 p++;
2267 if (p == str + len)
2268 return 1;
2270 return 0;
2273 /* Set the name of the terminal frame. Also used by MSDOS frames.
2274 Modeled after x_set_name which is used for WINDOW frames. */
2276 static void
2277 set_term_frame_name (struct frame *f, Lisp_Object name)
2279 f->explicit_name = ! NILP (name);
2281 /* If NAME is nil, set the name to F<num>. */
2282 if (NILP (name))
2284 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2286 /* Check for no change needed in this very common case
2287 before we do any consing. */
2288 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2289 return;
2291 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2293 else
2295 CHECK_STRING (name);
2297 /* Don't change the name if it's already NAME. */
2298 if (! NILP (Fstring_equal (name, f->name)))
2299 return;
2301 /* Don't allow the user to set the frame name to F<num>, so it
2302 doesn't clash with the names we generate for terminal frames. */
2303 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2304 error ("Frame names of the form F<num> are usurped by Emacs");
2307 fset_name (f, name);
2308 update_mode_lines = 16;
2311 void
2312 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2314 register Lisp_Object old_alist_elt;
2316 /* The buffer-list parameters are stored in a special place and not
2317 in the alist. All buffers must be live. */
2318 if (EQ (prop, Qbuffer_list))
2320 Lisp_Object list = Qnil;
2321 for (; CONSP (val); val = XCDR (val))
2322 if (!NILP (Fbuffer_live_p (XCAR (val))))
2323 list = Fcons (XCAR (val), list);
2324 fset_buffer_list (f, Fnreverse (list));
2325 return;
2327 if (EQ (prop, Qburied_buffer_list))
2329 Lisp_Object list = Qnil;
2330 for (; CONSP (val); val = XCDR (val))
2331 if (!NILP (Fbuffer_live_p (XCAR (val))))
2332 list = Fcons (XCAR (val), list);
2333 fset_buried_buffer_list (f, Fnreverse (list));
2334 return;
2337 /* If PROP is a symbol which is supposed to have frame-local values,
2338 and it is set up based on this frame, switch to the global
2339 binding. That way, we can create or alter the frame-local binding
2340 without messing up the symbol's status. */
2341 if (SYMBOLP (prop))
2343 struct Lisp_Symbol *sym = XSYMBOL (prop);
2344 start:
2345 switch (sym->redirect)
2347 case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
2348 case SYMBOL_PLAINVAL: case SYMBOL_FORWARDED: break;
2349 case SYMBOL_LOCALIZED:
2350 { struct Lisp_Buffer_Local_Value *blv = sym->val.blv;
2351 if (blv->frame_local && blv_found (blv) && XFRAME (blv->where) == f)
2352 swap_in_global_binding (sym);
2353 break;
2355 default: emacs_abort ();
2359 /* The tty color needed to be set before the frame's parameter
2360 alist was updated with the new value. This is not true any more,
2361 but we still do this test early on. */
2362 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2363 && f == FRAME_TTY (f)->previous_frame)
2364 /* Force redisplay of this tty. */
2365 FRAME_TTY (f)->previous_frame = NULL;
2367 /* Update the frame parameter alist. */
2368 old_alist_elt = Fassq (prop, f->param_alist);
2369 if (EQ (old_alist_elt, Qnil))
2370 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2371 else
2372 Fsetcdr (old_alist_elt, val);
2374 /* Update some other special parameters in their special places
2375 in addition to the alist. */
2377 if (EQ (prop, Qbuffer_predicate))
2378 fset_buffer_predicate (f, val);
2380 if (! FRAME_WINDOW_P (f))
2382 if (EQ (prop, Qmenu_bar_lines))
2383 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2384 else if (EQ (prop, Qname))
2385 set_term_frame_name (f, val);
2388 if (EQ (prop, Qminibuffer) && WINDOWP (val))
2390 if (! MINI_WINDOW_P (XWINDOW (val)))
2391 error ("Surrogate minibuffer windows must be minibuffer windows");
2393 if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
2394 && !EQ (val, f->minibuffer_window))
2395 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
2397 /* Install the chosen minibuffer window, with proper buffer. */
2398 fset_minibuffer_window (f, val);
2402 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2403 is not an unspecified foreground or background color. */
2405 static Lisp_Object
2406 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
2408 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
2409 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
2410 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
2411 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
2414 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
2415 doc: /* Return the parameters-alist of frame FRAME.
2416 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2417 The meaningful PARMs depend on the kind of frame.
2418 If FRAME is omitted or nil, return information on the currently selected frame. */)
2419 (Lisp_Object frame)
2421 Lisp_Object alist;
2422 struct frame *f = decode_any_frame (frame);
2423 int height, width;
2424 struct gcpro gcpro1;
2426 if (!FRAME_LIVE_P (f))
2427 return Qnil;
2429 alist = Fcopy_alist (f->param_alist);
2430 GCPRO1 (alist);
2432 if (!FRAME_WINDOW_P (f))
2434 Lisp_Object elt;
2436 /* If the frame's parameter alist says the colors are
2437 unspecified and reversed, take the frame's background pixel
2438 for foreground and vice versa. */
2439 elt = Fassq (Qforeground_color, alist);
2440 if (CONSP (elt) && STRINGP (XCDR (elt)))
2442 elt = frame_unspecified_color (f, XCDR (elt));
2443 if (!NILP (elt))
2444 store_in_alist (&alist, Qforeground_color, elt);
2446 else
2447 store_in_alist (&alist, Qforeground_color,
2448 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
2449 elt = Fassq (Qbackground_color, alist);
2450 if (CONSP (elt) && STRINGP (XCDR (elt)))
2452 elt = frame_unspecified_color (f, XCDR (elt));
2453 if (!NILP (elt))
2454 store_in_alist (&alist, Qbackground_color, elt);
2456 else
2457 store_in_alist (&alist, Qbackground_color,
2458 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
2459 store_in_alist (&alist, intern ("font"),
2460 build_string (FRAME_MSDOS_P (f)
2461 ? "ms-dos"
2462 : FRAME_W32_P (f) ? "w32term"
2463 :"tty"));
2465 store_in_alist (&alist, Qname, f->name);
2466 height = (f->new_height
2467 ? (f->new_pixelwise
2468 ? (f->new_height / FRAME_LINE_HEIGHT (f))
2469 : f->new_height)
2470 : FRAME_LINES (f));
2471 store_in_alist (&alist, Qheight, make_number (height));
2472 width = (f->new_width
2473 ? (f->new_pixelwise
2474 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
2475 : f->new_width)
2476 : FRAME_COLS (f));
2477 store_in_alist (&alist, Qwidth, make_number (width));
2478 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
2479 store_in_alist (&alist, Qminibuffer,
2480 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
2481 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2482 : FRAME_MINIBUF_WINDOW (f)));
2483 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
2484 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
2485 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
2487 /* I think this should be done with a hook. */
2488 #ifdef HAVE_WINDOW_SYSTEM
2489 if (FRAME_WINDOW_P (f))
2490 x_report_frame_params (f, &alist);
2491 else
2492 #endif
2494 /* This ought to be correct in f->param_alist for an X frame. */
2495 Lisp_Object lines;
2496 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
2497 store_in_alist (&alist, Qmenu_bar_lines, lines);
2500 UNGCPRO;
2501 return alist;
2505 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
2506 doc: /* Return FRAME's value for parameter PARAMETER.
2507 If FRAME is nil, describe the currently selected frame. */)
2508 (Lisp_Object frame, Lisp_Object parameter)
2510 struct frame *f = decode_any_frame (frame);
2511 Lisp_Object value = Qnil;
2513 CHECK_SYMBOL (parameter);
2515 XSETFRAME (frame, f);
2517 if (FRAME_LIVE_P (f))
2519 /* Avoid consing in frequent cases. */
2520 if (EQ (parameter, Qname))
2521 value = f->name;
2522 #ifdef HAVE_X_WINDOWS
2523 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2524 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
2525 #endif /* HAVE_X_WINDOWS */
2526 else if (EQ (parameter, Qbackground_color)
2527 || EQ (parameter, Qforeground_color))
2529 value = Fassq (parameter, f->param_alist);
2530 if (CONSP (value))
2532 value = XCDR (value);
2533 /* Fframe_parameters puts the actual fg/bg color names,
2534 even if f->param_alist says otherwise. This is
2535 important when param_alist's notion of colors is
2536 "unspecified". We need to do the same here. */
2537 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2538 value = frame_unspecified_color (f, value);
2540 else
2541 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2543 else if (EQ (parameter, Qdisplay_type)
2544 || EQ (parameter, Qbackground_mode))
2545 value = Fcdr (Fassq (parameter, f->param_alist));
2546 else
2547 /* FIXME: Avoid this code path at all (as well as code duplication)
2548 by sharing more code with Fframe_parameters. */
2549 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2552 return value;
2556 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
2557 Smodify_frame_parameters, 2, 2, 0,
2558 doc: /* Modify the parameters of frame FRAME according to ALIST.
2559 If FRAME is nil, it defaults to the selected frame.
2560 ALIST is an alist of parameters to change and their new values.
2561 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
2562 The meaningful PARMs depend on the kind of frame.
2563 Undefined PARMs are ignored, but stored in the frame's parameter list
2564 so that `frame-parameters' will return them.
2566 The value of frame parameter FOO can also be accessed
2567 as a frame-local binding for the variable FOO, if you have
2568 enabled such bindings for that variable with `make-variable-frame-local'.
2569 Note that this functionality is obsolete as of Emacs 22.2, and its
2570 use is not recommended. Explicitly check for a frame-parameter instead. */)
2571 (Lisp_Object frame, Lisp_Object alist)
2573 struct frame *f = decode_live_frame (frame);
2574 register Lisp_Object prop, val;
2576 CHECK_LIST (alist);
2578 /* I think this should be done with a hook. */
2579 #ifdef HAVE_WINDOW_SYSTEM
2580 if (FRAME_WINDOW_P (f))
2581 x_set_frame_parameters (f, alist);
2582 else
2583 #endif
2584 #ifdef MSDOS
2585 if (FRAME_MSDOS_P (f))
2586 IT_set_frame_parameters (f, alist);
2587 else
2588 #endif
2591 EMACS_INT length = XFASTINT (Flength (alist));
2592 ptrdiff_t i;
2593 Lisp_Object *parms;
2594 Lisp_Object *values;
2595 USE_SAFE_ALLOCA;
2596 SAFE_ALLOCA_LISP (parms, 2 * length);
2597 values = parms + length;
2599 /* Extract parm names and values into those vectors. */
2601 for (i = 0; CONSP (alist); alist = XCDR (alist))
2603 Lisp_Object elt;
2605 elt = XCAR (alist);
2606 parms[i] = Fcar (elt);
2607 values[i] = Fcdr (elt);
2608 i++;
2611 /* Now process them in reverse of specified order. */
2612 while (--i >= 0)
2614 prop = parms[i];
2615 val = values[i];
2616 store_frame_param (f, prop, val);
2618 if (EQ (prop, Qforeground_color)
2619 || EQ (prop, Qbackground_color))
2620 update_face_from_frame_parameter (f, prop, val);
2623 SAFE_FREE ();
2625 return Qnil;
2628 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
2629 0, 1, 0,
2630 doc: /* Height in pixels of a line in the font in frame FRAME.
2631 If FRAME is omitted or nil, the selected frame is used.
2632 For a terminal frame, the value is always 1. */)
2633 (Lisp_Object frame)
2635 #ifdef HAVE_WINDOW_SYSTEM
2636 struct frame *f = decode_any_frame (frame);
2638 if (FRAME_WINDOW_P (f))
2639 return make_number (FRAME_LINE_HEIGHT (f));
2640 else
2641 #endif
2642 return make_number (1);
2646 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
2647 0, 1, 0,
2648 doc: /* Width in pixels of characters in the font in frame FRAME.
2649 If FRAME is omitted or nil, the selected frame is used.
2650 On a graphical screen, the width is the standard width of the default font.
2651 For a terminal screen, the value is always 1. */)
2652 (Lisp_Object frame)
2654 #ifdef HAVE_WINDOW_SYSTEM
2655 struct frame *f = decode_any_frame (frame);
2657 if (FRAME_WINDOW_P (f))
2658 return make_number (FRAME_COLUMN_WIDTH (f));
2659 else
2660 #endif
2661 return make_number (1);
2664 DEFUN ("frame-pixel-height", Fframe_pixel_height,
2665 Sframe_pixel_height, 0, 1, 0,
2666 doc: /* Return a FRAME's height in pixels.
2667 If FRAME is omitted or nil, the selected frame is used. The exact value
2668 of the result depends on the window-system and toolkit in use:
2670 In the Gtk+ version of Emacs, it includes only any window (including
2671 the minibuffer or echo area), mode line, and header line. It does not
2672 include the tool bar or menu bar.
2674 With other graphical versions, it also includes the tool bar and the
2675 menu bar.
2677 For a text terminal, it includes the menu bar. In this case, the
2678 result is really in characters rather than pixels (i.e., is identical
2679 to `frame-height'). */)
2680 (Lisp_Object frame)
2682 struct frame *f = decode_any_frame (frame);
2684 #ifdef HAVE_WINDOW_SYSTEM
2685 if (FRAME_WINDOW_P (f))
2686 return make_number (FRAME_PIXEL_HEIGHT (f));
2687 else
2688 #endif
2689 return make_number (FRAME_TOTAL_LINES (f));
2692 DEFUN ("frame-pixel-width", Fframe_pixel_width,
2693 Sframe_pixel_width, 0, 1, 0,
2694 doc: /* Return FRAME's width in pixels.
2695 For a terminal frame, the result really gives the width in characters.
2696 If FRAME is omitted or nil, the selected frame is used. */)
2697 (Lisp_Object frame)
2699 struct frame *f = decode_any_frame (frame);
2701 #ifdef HAVE_WINDOW_SYSTEM
2702 if (FRAME_WINDOW_P (f))
2703 return make_number (FRAME_PIXEL_WIDTH (f));
2704 else
2705 #endif
2706 return make_number (FRAME_TOTAL_COLS (f));
2709 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
2710 Stool_bar_pixel_width, 0, 1, 0,
2711 doc: /* Return width in pixels of FRAME's tool bar.
2712 The result is greater than zero only when the tool bar is on the left
2713 or right side of FRAME. If FRAME is omitted or nil, the selected frame
2714 is used. */)
2715 (Lisp_Object frame)
2717 #ifdef FRAME_TOOLBAR_WIDTH
2718 struct frame *f = decode_any_frame (frame);
2720 if (FRAME_WINDOW_P (f))
2721 return make_number (FRAME_TOOLBAR_WIDTH (f));
2722 #endif
2723 return make_number (0);
2726 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
2727 doc: /* Return width in columns of FRAME's text area. */)
2728 (Lisp_Object frame)
2730 return make_number (FRAME_COLS (decode_any_frame (frame)));
2733 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
2734 doc: /* Return height in lines of FRAME's text area. */)
2735 (Lisp_Object frame)
2737 return make_number (FRAME_LINES (decode_any_frame (frame)));
2740 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
2741 doc: /* Return number of total columns of FRAME. */)
2742 (Lisp_Object frame)
2744 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
2747 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
2748 doc: /* Return number of total lines of FRAME. */)
2749 (Lisp_Object frame)
2751 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
2754 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
2755 doc: /* Return text area width of FRAME in pixels. */)
2756 (Lisp_Object frame)
2758 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
2761 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
2762 doc: /* Return text area height of FRAME in pixels. */)
2763 (Lisp_Object frame)
2765 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
2768 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
2769 doc: /* Return scroll bar width of FRAME in pixels. */)
2770 (Lisp_Object frame)
2772 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
2775 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
2776 doc: /* Return scroll bar height of FRAME in pixels. */)
2777 (Lisp_Object frame)
2779 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
2782 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
2783 doc: /* Return fringe width of FRAME in pixels. */)
2784 (Lisp_Object frame)
2786 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
2789 DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0,
2790 doc: /* Return border width of FRAME in pixels. */)
2791 (Lisp_Object frame)
2793 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
2796 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
2797 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
2798 (Lisp_Object frame)
2800 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
2803 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
2804 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
2805 (Lisp_Object frame)
2807 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
2810 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
2811 doc: /* Set height of frame FRAME to HEIGHT lines.
2812 Optional third arg PRETEND non-nil means that redisplay should use
2813 HEIGHT lines but that the idea of the actual height of the frame should
2814 not be changed.
2816 Optional fourth argument PIXELWISE non-nil means that FRAME should be
2817 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
2818 window managers may refuse to honor a HEIGHT that is not an integer
2819 multiple of the default frame font height. */)
2820 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
2822 struct frame *f = decode_live_frame (frame);
2823 int pixel_height;
2825 CHECK_TYPE_RANGED_INTEGER (int, height);
2827 pixel_height = (!NILP (pixelwise)
2828 ? XINT (height)
2829 : XINT (height) * FRAME_LINE_HEIGHT (f));
2830 if (pixel_height != FRAME_TEXT_HEIGHT (f))
2831 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
2833 return Qnil;
2836 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
2837 doc: /* Set width of frame FRAME to WIDTH columns.
2838 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
2839 columns but that the idea of the actual width of the frame should not
2840 be changed.
2842 Optional fourth argument PIXELWISE non-nil means that FRAME should be
2843 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
2844 window managers may refuse to honor a WIDTH that is not an integer
2845 multiple of the default frame font width. */)
2846 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
2848 struct frame *f = decode_live_frame (frame);
2849 int pixel_width;
2851 CHECK_TYPE_RANGED_INTEGER (int, width);
2853 pixel_width = (!NILP (pixelwise)
2854 ? XINT (width)
2855 : XINT (width) * FRAME_COLUMN_WIDTH (f));
2856 if (pixel_width != FRAME_TEXT_WIDTH (f))
2857 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
2859 return Qnil;
2862 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
2863 doc: /* Set size of FRAME to WIDTH by HEIGHT, measured in characters.
2864 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
2865 When `frame-resize-pixelwise' is nil, some window managers may refuse to
2866 honor a WIDTH that is not an integer multiple of the default frame font
2867 width or a HEIGHT that is not an integer multiple of the default frame
2868 font height. */)
2869 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
2871 struct frame *f = decode_live_frame (frame);
2872 int pixel_width, pixel_height;
2874 CHECK_TYPE_RANGED_INTEGER (int, width);
2875 CHECK_TYPE_RANGED_INTEGER (int, height);
2877 pixel_width = (!NILP (pixelwise)
2878 ? XINT (width)
2879 : XINT (width) * FRAME_COLUMN_WIDTH (f));
2880 pixel_height = (!NILP (pixelwise)
2881 ? XINT (height)
2882 : XINT (height) * FRAME_LINE_HEIGHT (f));
2884 if (pixel_width != FRAME_TEXT_WIDTH (f)
2885 || pixel_height != FRAME_TEXT_HEIGHT (f))
2886 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
2888 return Qnil;
2891 DEFUN ("set-frame-position", Fset_frame_position,
2892 Sset_frame_position, 3, 3, 0,
2893 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2894 If FRAME is nil, the selected frame is used. XOFFSET and YOFFSET are
2895 actually the position of the upper left corner of the frame. Negative
2896 values for XOFFSET or YOFFSET are interpreted relative to the rightmost
2897 or bottommost possible position (that stays within the screen). */)
2898 (Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
2900 register struct frame *f = decode_live_frame (frame);
2902 CHECK_TYPE_RANGED_INTEGER (int, xoffset);
2903 CHECK_TYPE_RANGED_INTEGER (int, yoffset);
2905 /* I think this should be done with a hook. */
2906 #ifdef HAVE_WINDOW_SYSTEM
2907 if (FRAME_WINDOW_P (f))
2908 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
2909 #endif
2911 return Qt;
2915 /***********************************************************************
2916 Frame Parameters
2917 ***********************************************************************/
2919 /* Connect the frame-parameter names for X frames
2920 to the ways of passing the parameter values to the window system.
2922 The name of a parameter, as a Lisp symbol,
2923 has an `x-frame-parameter' property which is an integer in Lisp
2924 that is an index in this table. */
2926 struct frame_parm_table {
2927 const char *name;
2928 struct Lisp_Symbol *sym;
2931 static const struct frame_parm_table frame_parms[] =
2933 {"auto-raise", XSYMBOL_INIT (Qauto_raise)},
2934 {"auto-lower", XSYMBOL_INIT (Qauto_lower)},
2935 {"background-color", 0},
2936 {"border-color", XSYMBOL_INIT (Qborder_color)},
2937 {"border-width", XSYMBOL_INIT (Qborder_width)},
2938 {"cursor-color", XSYMBOL_INIT (Qcursor_color)},
2939 {"cursor-type", XSYMBOL_INIT (Qcursor_type)},
2940 {"font", 0},
2941 {"foreground-color", 0},
2942 {"icon-name", XSYMBOL_INIT (Qicon_name)},
2943 {"icon-type", XSYMBOL_INIT (Qicon_type)},
2944 {"internal-border-width", XSYMBOL_INIT (Qinternal_border_width)},
2945 {"right-divider-width", XSYMBOL_INIT (Qright_divider_width)},
2946 {"bottom-divider-width", XSYMBOL_INIT (Qbottom_divider_width)},
2947 {"menu-bar-lines", XSYMBOL_INIT (Qmenu_bar_lines)},
2948 {"mouse-color", XSYMBOL_INIT (Qmouse_color)},
2949 {"name", XSYMBOL_INIT (Qname)},
2950 {"scroll-bar-width", XSYMBOL_INIT (Qscroll_bar_width)},
2951 {"scroll-bar-height", XSYMBOL_INIT (Qscroll_bar_height)},
2952 {"title", XSYMBOL_INIT (Qtitle)},
2953 {"unsplittable", XSYMBOL_INIT (Qunsplittable)},
2954 {"vertical-scroll-bars", XSYMBOL_INIT (Qvertical_scroll_bars)},
2955 {"horizontal-scroll-bars", XSYMBOL_INIT (Qhorizontal_scroll_bars)},
2956 {"visibility", XSYMBOL_INIT (Qvisibility)},
2957 {"tool-bar-lines", XSYMBOL_INIT (Qtool_bar_lines)},
2958 {"scroll-bar-foreground", XSYMBOL_INIT (Qscroll_bar_foreground)},
2959 {"scroll-bar-background", XSYMBOL_INIT (Qscroll_bar_background)},
2960 {"screen-gamma", XSYMBOL_INIT (Qscreen_gamma)},
2961 {"line-spacing", XSYMBOL_INIT (Qline_spacing)},
2962 {"left-fringe", XSYMBOL_INIT (Qleft_fringe)},
2963 {"right-fringe", XSYMBOL_INIT (Qright_fringe)},
2964 {"wait-for-wm", XSYMBOL_INIT (Qwait_for_wm)},
2965 {"fullscreen", XSYMBOL_INIT (Qfullscreen)},
2966 {"font-backend", XSYMBOL_INIT (Qfont_backend)},
2967 {"alpha", XSYMBOL_INIT (Qalpha)},
2968 {"sticky", XSYMBOL_INIT (Qsticky)},
2969 {"tool-bar-position", XSYMBOL_INIT (Qtool_bar_position)},
2972 #ifdef HAVE_WINDOW_SYSTEM
2974 /* Change the parameters of frame F as specified by ALIST.
2975 If a parameter is not specially recognized, do nothing special;
2976 otherwise call the `x_set_...' function for that parameter.
2977 Except for certain geometry properties, always call store_frame_param
2978 to store the new value in the parameter alist. */
2980 void
2981 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
2983 Lisp_Object tail;
2985 /* If both of these parameters are present, it's more efficient to
2986 set them both at once. So we wait until we've looked at the
2987 entire list before we set them. */
2988 int width IF_LINT (= 0), height IF_LINT (= 0);
2989 bool width_change = 0, height_change = 0;
2991 /* Same here. */
2992 Lisp_Object left, top;
2994 /* Same with these. */
2995 Lisp_Object icon_left, icon_top;
2997 /* Record in these vectors all the parms specified. */
2998 Lisp_Object *parms;
2999 Lisp_Object *values;
3000 ptrdiff_t i, p;
3001 bool left_no_change = 0, top_no_change = 0;
3002 #ifdef HAVE_X_WINDOWS
3003 bool icon_left_no_change = 0, icon_top_no_change = 0;
3004 #endif
3006 i = 0;
3007 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3008 i++;
3010 USE_SAFE_ALLOCA;
3011 SAFE_ALLOCA_LISP (parms, 2 * i);
3012 values = parms + i;
3014 /* Extract parm names and values into those vectors. */
3016 i = 0;
3017 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3019 Lisp_Object elt;
3021 elt = XCAR (tail);
3022 parms[i] = Fcar (elt);
3023 values[i] = Fcdr (elt);
3024 i++;
3026 /* TAIL and ALIST are not used again below here. */
3027 alist = tail = Qnil;
3029 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
3030 because their values appear in VALUES and strings are not valid. */
3031 top = left = Qunbound;
3032 icon_left = icon_top = Qunbound;
3034 /* Process foreground_color and background_color before anything else.
3035 They are independent of other properties, but other properties (e.g.,
3036 cursor_color) are dependent upon them. */
3037 /* Process default font as well, since fringe widths depends on it. */
3038 for (p = 0; p < i; p++)
3040 Lisp_Object prop, val;
3042 prop = parms[p];
3043 val = values[p];
3044 if (EQ (prop, Qforeground_color)
3045 || EQ (prop, Qbackground_color)
3046 || EQ (prop, Qfont))
3048 register Lisp_Object param_index, old_value;
3050 old_value = get_frame_param (f, prop);
3051 if (NILP (Fequal (val, old_value)))
3053 store_frame_param (f, prop, val);
3055 param_index = Fget (prop, Qx_frame_parameter);
3056 if (NATNUMP (param_index)
3057 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3058 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3059 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3064 /* Now process them in reverse of specified order. */
3065 while (i-- != 0)
3067 Lisp_Object prop, val;
3069 prop = parms[i];
3070 val = values[i];
3072 if (EQ (prop, Qwidth) && RANGED_INTEGERP (0, val, INT_MAX))
3074 width_change = 1;
3075 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3077 else if (EQ (prop, Qheight) && RANGED_INTEGERP (0, val, INT_MAX))
3079 height_change = 1;
3080 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3082 else if (EQ (prop, Qtop))
3083 top = val;
3084 else if (EQ (prop, Qleft))
3085 left = val;
3086 else if (EQ (prop, Qicon_top))
3087 icon_top = val;
3088 else if (EQ (prop, Qicon_left))
3089 icon_left = val;
3090 else if (EQ (prop, Qforeground_color)
3091 || EQ (prop, Qbackground_color)
3092 || EQ (prop, Qfont))
3093 /* Processed above. */
3094 continue;
3095 else
3097 register Lisp_Object param_index, old_value;
3099 old_value = get_frame_param (f, prop);
3101 store_frame_param (f, prop, val);
3103 param_index = Fget (prop, Qx_frame_parameter);
3104 if (NATNUMP (param_index)
3105 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3106 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3107 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3111 /* Don't die if just one of these was set. */
3112 if (EQ (left, Qunbound))
3114 left_no_change = 1;
3115 if (f->left_pos < 0)
3116 left = list2 (Qplus, make_number (f->left_pos));
3117 else
3118 XSETINT (left, f->left_pos);
3120 if (EQ (top, Qunbound))
3122 top_no_change = 1;
3123 if (f->top_pos < 0)
3124 top = list2 (Qplus, make_number (f->top_pos));
3125 else
3126 XSETINT (top, f->top_pos);
3129 /* If one of the icon positions was not set, preserve or default it. */
3130 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3132 #ifdef HAVE_X_WINDOWS
3133 icon_left_no_change = 1;
3134 #endif
3135 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3136 if (NILP (icon_left))
3137 XSETINT (icon_left, 0);
3139 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3141 #ifdef HAVE_X_WINDOWS
3142 icon_top_no_change = 1;
3143 #endif
3144 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3145 if (NILP (icon_top))
3146 XSETINT (icon_top, 0);
3149 /* Don't set these parameters unless they've been explicitly
3150 specified. The window might be mapped or resized while we're in
3151 this function, and we don't want to override that unless the lisp
3152 code has asked for it.
3154 Don't set these parameters unless they actually differ from the
3155 window's current parameters; the window may not actually exist
3156 yet. */
3158 Lisp_Object frame;
3160 XSETFRAME (frame, f);
3162 if ((width_change && width != FRAME_TEXT_WIDTH (f))
3163 || (height_change && height != FRAME_TEXT_HEIGHT (f))
3164 || (f->can_x_set_window_size && (f->new_height || f->new_width)))
3166 /* If necessary provide default values for HEIGHT and WIDTH. Do
3167 that here since otherwise a size change implied by an
3168 intermittent font change may get lost as in Bug#17142. */
3169 if (!width_change)
3170 width = (f->new_width
3171 ? (f->new_pixelwise
3172 ? f->new_width
3173 : (f->new_width * FRAME_COLUMN_WIDTH (f)))
3174 : FRAME_TEXT_WIDTH (f));
3176 if (!height_change)
3177 height = (f->new_height
3178 ? (f->new_pixelwise
3179 ? f->new_height
3180 : (f->new_height * FRAME_LINE_HEIGHT (f)))
3181 : FRAME_TEXT_HEIGHT (f));
3183 Fset_frame_size (frame, make_number (width), make_number (height), Qt);
3186 if ((!NILP (left) || !NILP (top))
3187 && ! (left_no_change && top_no_change)
3188 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3189 && NUMBERP (top) && XINT (top) == f->top_pos))
3191 int leftpos = 0;
3192 int toppos = 0;
3194 /* Record the signs. */
3195 f->size_hint_flags &= ~ (XNegative | YNegative);
3196 if (EQ (left, Qminus))
3197 f->size_hint_flags |= XNegative;
3198 else if (TYPE_RANGED_INTEGERP (int, left))
3200 leftpos = XINT (left);
3201 if (leftpos < 0)
3202 f->size_hint_flags |= XNegative;
3204 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3205 && CONSP (XCDR (left))
3206 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3208 leftpos = - XINT (XCAR (XCDR (left)));
3209 f->size_hint_flags |= XNegative;
3211 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3212 && CONSP (XCDR (left))
3213 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3215 leftpos = XINT (XCAR (XCDR (left)));
3218 if (EQ (top, Qminus))
3219 f->size_hint_flags |= YNegative;
3220 else if (TYPE_RANGED_INTEGERP (int, top))
3222 toppos = XINT (top);
3223 if (toppos < 0)
3224 f->size_hint_flags |= YNegative;
3226 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3227 && CONSP (XCDR (top))
3228 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3230 toppos = - XINT (XCAR (XCDR (top)));
3231 f->size_hint_flags |= YNegative;
3233 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3234 && CONSP (XCDR (top))
3235 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
3237 toppos = XINT (XCAR (XCDR (top)));
3241 /* Store the numeric value of the position. */
3242 f->top_pos = toppos;
3243 f->left_pos = leftpos;
3245 f->win_gravity = NorthWestGravity;
3247 /* Actually set that position, and convert to absolute. */
3248 x_set_offset (f, leftpos, toppos, -1);
3250 #ifdef HAVE_X_WINDOWS
3251 if ((!NILP (icon_left) || !NILP (icon_top))
3252 && ! (icon_left_no_change && icon_top_no_change))
3253 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3254 #endif /* HAVE_X_WINDOWS */
3257 SAFE_FREE ();
3261 /* Insert a description of internally-recorded parameters of frame X
3262 into the parameter alist *ALISTPTR that is to be given to the user.
3263 Only parameters that are specific to the X window system
3264 and whose values are not correctly recorded in the frame's
3265 param_alist need to be considered here. */
3267 void
3268 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
3270 Lisp_Object tem;
3271 uprintmax_t w;
3272 char buf[INT_BUFSIZE_BOUND (w)];
3274 /* Represent negative positions (off the top or left screen edge)
3275 in a way that Fmodify_frame_parameters will understand correctly. */
3276 XSETINT (tem, f->left_pos);
3277 if (f->left_pos >= 0)
3278 store_in_alist (alistptr, Qleft, tem);
3279 else
3280 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
3282 XSETINT (tem, f->top_pos);
3283 if (f->top_pos >= 0)
3284 store_in_alist (alistptr, Qtop, tem);
3285 else
3286 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
3288 store_in_alist (alistptr, Qborder_width,
3289 make_number (f->border_width));
3290 store_in_alist (alistptr, Qinternal_border_width,
3291 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
3292 store_in_alist (alistptr, Qright_divider_width,
3293 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
3294 store_in_alist (alistptr, Qbottom_divider_width,
3295 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
3296 store_in_alist (alistptr, Qleft_fringe,
3297 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
3298 store_in_alist (alistptr, Qright_fringe,
3299 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
3300 store_in_alist (alistptr, Qscroll_bar_width,
3301 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3302 ? make_number (0)
3303 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3304 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
3305 /* nil means "use default width"
3306 for non-toolkit scroll bar.
3307 ruler-mode.el depends on this. */
3308 : Qnil));
3309 store_in_alist (alistptr, Qscroll_bar_height,
3310 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
3311 ? make_number (0)
3312 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
3313 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
3314 /* nil means "use default height"
3315 for non-toolkit scroll bar. */
3316 : Qnil));
3317 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
3318 MS-Windows it returns a value whose type is HANDLE, which is
3319 actually a pointer. Explicit casting avoids compiler
3320 warnings. */
3321 w = (uintptr_t) FRAME_X_WINDOW (f);
3322 store_in_alist (alistptr, Qwindow_id,
3323 make_formatted_string (buf, "%"pMu, w));
3324 #ifdef HAVE_X_WINDOWS
3325 #ifdef USE_X_TOOLKIT
3326 /* Tooltip frame may not have this widget. */
3327 if (FRAME_X_OUTPUT (f)->widget)
3328 #endif
3329 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
3330 store_in_alist (alistptr, Qouter_window_id,
3331 make_formatted_string (buf, "%"pMu, w));
3332 #endif
3333 store_in_alist (alistptr, Qicon_name, f->icon_name);
3334 store_in_alist (alistptr, Qvisibility,
3335 (FRAME_VISIBLE_P (f) ? Qt
3336 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3337 store_in_alist (alistptr, Qdisplay,
3338 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
3340 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
3341 tem = Qnil;
3342 else
3343 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
3344 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
3345 store_in_alist (alistptr, Qparent_id, tem);
3346 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
3350 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3351 the previous value of that parameter, NEW_VALUE is the new value. */
3353 void
3354 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3356 if (NILP (new_value))
3357 f->want_fullscreen = FULLSCREEN_NONE;
3358 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
3359 f->want_fullscreen = FULLSCREEN_BOTH;
3360 else if (EQ (new_value, Qfullwidth))
3361 f->want_fullscreen = FULLSCREEN_WIDTH;
3362 else if (EQ (new_value, Qfullheight))
3363 f->want_fullscreen = FULLSCREEN_HEIGHT;
3364 else if (EQ (new_value, Qmaximized))
3365 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
3367 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
3368 FRAME_TERMINAL (f)->fullscreen_hook (f);
3372 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3373 the previous value of that parameter, NEW_VALUE is the new value. */
3375 void
3376 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3378 if (NILP (new_value))
3379 f->extra_line_spacing = 0;
3380 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
3381 f->extra_line_spacing = XFASTINT (new_value);
3382 else if (FLOATP (new_value))
3384 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
3386 if (new_spacing >= 0)
3387 f->extra_line_spacing = new_spacing;
3388 else
3389 signal_error ("Invalid line-spacing", new_value);
3391 else
3392 signal_error ("Invalid line-spacing", new_value);
3393 if (FRAME_VISIBLE_P (f))
3394 redraw_frame (f);
3398 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3399 the previous value of that parameter, NEW_VALUE is the new value. */
3401 void
3402 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3404 Lisp_Object bgcolor;
3406 if (NILP (new_value))
3407 f->gamma = 0;
3408 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
3409 /* The value 0.4545 is the normal viewing gamma. */
3410 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
3411 else
3412 signal_error ("Invalid screen-gamma", new_value);
3414 /* Apply the new gamma value to the frame background. */
3415 bgcolor = Fassq (Qbackground_color, f->param_alist);
3416 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3418 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
3419 if (NATNUMP (parm_index)
3420 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
3421 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3422 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3423 (f, bgcolor, Qnil);
3426 Fclear_face_cache (Qnil);
3430 void
3431 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3433 Lisp_Object font_object;
3434 int fontset = -1;
3435 #ifdef HAVE_X_WINDOWS
3436 Lisp_Object font_param = arg;
3437 #endif
3439 /* Set the frame parameter back to the old value because we may
3440 fail to use ARG as the new parameter value. */
3441 store_frame_param (f, Qfont, oldval);
3443 /* ARG is a fontset name, a font name, a cons of fontset name and a
3444 font object, or a font object. In the last case, this function
3445 never fail. */
3446 if (STRINGP (arg))
3448 fontset = fs_query_fontset (arg, 0);
3449 if (fontset < 0)
3451 font_object = font_open_by_name (f, arg);
3452 if (NILP (font_object))
3453 error ("Font `%s' is not defined", SSDATA (arg));
3454 arg = AREF (font_object, FONT_NAME_INDEX);
3456 else if (fontset > 0)
3458 font_object = font_open_by_name (f, fontset_ascii (fontset));
3459 if (NILP (font_object))
3460 error ("Font `%s' is not defined", SDATA (arg));
3461 arg = AREF (font_object, FONT_NAME_INDEX);
3463 else
3464 error ("The default fontset can't be used for a frame font");
3466 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
3468 /* This is the case that the ASCII font of F's fontset XCAR
3469 (arg) is changed to the font XCDR (arg) by
3470 `set-fontset-font'. */
3471 fontset = fs_query_fontset (XCAR (arg), 0);
3472 if (fontset < 0)
3473 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
3474 font_object = XCDR (arg);
3475 arg = AREF (font_object, FONT_NAME_INDEX);
3476 #ifdef HAVE_X_WINDOWS
3477 font_param = Ffont_get (font_object, QCname);
3478 #endif
3480 else if (FONT_OBJECT_P (arg))
3482 font_object = arg;
3483 #ifdef HAVE_X_WINDOWS
3484 font_param = Ffont_get (font_object, QCname);
3485 #endif
3486 /* This is to store the XLFD font name in the frame parameter for
3487 backward compatibility. We should store the font-object
3488 itself in the future. */
3489 arg = AREF (font_object, FONT_NAME_INDEX);
3490 fontset = FRAME_FONTSET (f);
3491 /* Check if we can use the current fontset. If not, set FONTSET
3492 to -1 to generate a new fontset from FONT-OBJECT. */
3493 if (fontset >= 0)
3495 Lisp_Object ascii_font = fontset_ascii (fontset);
3496 Lisp_Object spec = font_spec_from_name (ascii_font);
3498 if (NILP (spec))
3499 signal_error ("Invalid font name", ascii_font);
3501 if (! font_match_p (spec, font_object))
3502 fontset = -1;
3505 else
3506 signal_error ("Invalid font", arg);
3508 if (! NILP (Fequal (font_object, oldval)))
3509 return;
3511 x_new_font (f, font_object, fontset);
3512 store_frame_param (f, Qfont, arg);
3513 #ifdef HAVE_X_WINDOWS
3514 store_frame_param (f, Qfont_param, font_param);
3515 #endif
3516 /* Recalculate toolbar height. */
3517 f->n_tool_bar_rows = 0;
3519 /* Ensure we redraw it. */
3520 clear_current_matrices (f);
3522 /* Attempt to hunt down bug#16028. */
3523 SET_FRAME_GARBAGED (f);
3525 recompute_basic_faces (f);
3527 do_pending_window_change (0);
3529 /* We used to call face-set-after-frame-default here, but it leads to
3530 recursive calls (since that function can set the `default' face's
3531 font which in turns changes the frame's `font' parameter).
3532 Also I don't know what this call is meant to do, but it seems the
3533 wrong way to do it anyway (it does a lot more work than what seems
3534 reasonable in response to a change to `font'). */
3538 void
3539 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3541 if (! NILP (new_value)
3542 && !CONSP (new_value))
3544 char *p0, *p1;
3546 CHECK_STRING (new_value);
3547 p0 = p1 = SSDATA (new_value);
3548 new_value = Qnil;
3549 while (*p0)
3551 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
3552 if (p0 < p1)
3553 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
3554 new_value);
3555 if (*p1)
3557 int c;
3559 while ((c = *++p1) && c_isspace (c));
3561 p0 = p1;
3563 new_value = Fnreverse (new_value);
3566 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
3567 return;
3569 if (FRAME_FONT (f))
3570 free_all_realized_faces (Qnil);
3572 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
3573 if (NILP (new_value))
3575 if (NILP (old_value))
3576 error ("No font backend available");
3577 font_update_drivers (f, old_value);
3578 error ("None of specified font backends are available");
3580 store_frame_param (f, Qfont_backend, new_value);
3582 if (FRAME_FONT (f))
3584 Lisp_Object frame;
3586 XSETFRAME (frame, f);
3587 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
3588 ++face_change_count;
3589 windows_or_buffers_changed = 18;
3593 void
3594 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3596 int unit = FRAME_COLUMN_WIDTH (f);
3597 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
3598 int new_width;
3600 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3601 ? eabs (XINT (new_value)) : 8);
3603 if (new_width != old_width)
3605 FRAME_LEFT_FRINGE_WIDTH (f) = new_width;
3606 FRAME_FRINGE_COLS (f) /* Round up. */
3607 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
3609 if (FRAME_X_WINDOW (f) != 0)
3610 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
3612 SET_FRAME_GARBAGED (f);
3617 void
3618 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3620 int unit = FRAME_COLUMN_WIDTH (f);
3621 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
3622 int new_width;
3624 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3625 ? eabs (XINT (new_value)) : 8);
3627 if (new_width != old_width)
3629 FRAME_RIGHT_FRINGE_WIDTH (f) = new_width;
3630 FRAME_FRINGE_COLS (f) /* Round up. */
3631 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
3633 if (FRAME_X_WINDOW (f) != 0)
3634 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
3636 SET_FRAME_GARBAGED (f);
3641 void
3642 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3644 CHECK_TYPE_RANGED_INTEGER (int, arg);
3646 if (XINT (arg) == f->border_width)
3647 return;
3649 if (FRAME_X_WINDOW (f) != 0)
3650 error ("Cannot change the border width of a frame");
3652 f->border_width = XINT (arg);
3655 void
3656 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3658 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
3660 CHECK_TYPE_RANGED_INTEGER (int, arg);
3661 FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg);
3662 if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0)
3663 FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
3664 if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old)
3666 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
3667 adjust_frame_glyphs (f);
3668 SET_FRAME_GARBAGED (f);
3673 void
3674 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3676 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
3678 CHECK_TYPE_RANGED_INTEGER (int, arg);
3679 FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg);
3680 if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0)
3681 FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
3682 if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old)
3684 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
3685 adjust_frame_glyphs (f);
3686 SET_FRAME_GARBAGED (f);
3690 void
3691 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
3693 Lisp_Object frame;
3694 XSETFRAME (frame, f);
3696 if (NILP (value))
3697 Fmake_frame_invisible (frame, Qt);
3698 else if (EQ (value, Qicon))
3699 Ficonify_frame (frame);
3700 else
3701 Fmake_frame_visible (frame);
3704 void
3705 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3707 f->auto_raise = !EQ (Qnil, arg);
3710 void
3711 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3713 f->auto_lower = !EQ (Qnil, arg);
3716 void
3717 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3719 f->no_split = !NILP (arg);
3722 void
3723 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3725 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3726 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3727 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3728 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3730 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3731 = (NILP (arg)
3732 ? vertical_scroll_bar_none
3733 : EQ (Qleft, arg)
3734 ? vertical_scroll_bar_left
3735 : EQ (Qright, arg)
3736 ? vertical_scroll_bar_right
3737 : EQ (Qleft, Vdefault_frame_scroll_bars)
3738 ? vertical_scroll_bar_left
3739 : EQ (Qright, Vdefault_frame_scroll_bars)
3740 ? vertical_scroll_bar_right
3741 : vertical_scroll_bar_none);
3743 /* We set this parameter before creating the X window for the
3744 frame, so we can get the geometry right from the start.
3745 However, if the window hasn't been created yet, we shouldn't
3746 call x_set_window_size. */
3747 if (FRAME_X_WINDOW (f))
3748 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
3750 SET_FRAME_GARBAGED (f);
3754 void
3755 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3757 #if USE_HORIZONTAL_SCROLL_BARS
3758 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
3759 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
3761 f->horizontal_scroll_bars = NILP (arg) ? false : true;
3763 /* We set this parameter before creating the X window for the
3764 frame, so we can get the geometry right from the start.
3765 However, if the window hasn't been created yet, we shouldn't
3766 call x_set_window_size. */
3767 if (FRAME_X_WINDOW (f))
3768 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
3770 SET_FRAME_GARBAGED (f);
3772 #endif
3775 void
3776 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3778 int unit = FRAME_COLUMN_WIDTH (f);
3780 if (NILP (arg))
3782 x_set_scroll_bar_default_width (f);
3784 if (FRAME_X_WINDOW (f))
3785 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
3787 SET_FRAME_GARBAGED (f);
3789 else if (RANGED_INTEGERP (1, arg, INT_MAX)
3790 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
3792 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3793 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
3794 if (FRAME_X_WINDOW (f))
3795 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
3797 SET_FRAME_GARBAGED (f);
3800 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3801 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3804 void
3805 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3807 #if USE_HORIZONTAL_SCROLL_BARS
3808 int unit = FRAME_LINE_HEIGHT (f);
3810 if (NILP (arg))
3812 x_set_scroll_bar_default_height (f);
3814 if (FRAME_X_WINDOW (f))
3815 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
3817 SET_FRAME_GARBAGED (f);
3819 else if (RANGED_INTEGERP (1, arg, INT_MAX)
3820 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
3822 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
3823 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
3824 if (FRAME_X_WINDOW (f))
3825 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
3827 SET_FRAME_GARBAGED (f);
3830 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
3831 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
3832 #endif
3835 void
3836 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3838 double alpha = 1.0;
3839 double newval[2];
3840 int i;
3841 Lisp_Object item;
3843 for (i = 0; i < 2; i++)
3845 newval[i] = 1.0;
3846 if (CONSP (arg))
3848 item = CAR (arg);
3849 arg = CDR (arg);
3851 else
3852 item = arg;
3854 if (NILP (item))
3855 alpha = - 1.0;
3856 else if (FLOATP (item))
3858 alpha = XFLOAT_DATA (item);
3859 if (! (0 <= alpha && alpha <= 1.0))
3860 args_out_of_range (make_float (0.0), make_float (1.0));
3862 else if (INTEGERP (item))
3864 EMACS_INT ialpha = XINT (item);
3865 if (! (0 <= ialpha && alpha <= 100))
3866 args_out_of_range (make_number (0), make_number (100));
3867 alpha = ialpha / 100.0;
3869 else
3870 wrong_type_argument (Qnumberp, item);
3871 newval[i] = alpha;
3874 for (i = 0; i < 2; i++)
3875 f->alpha[i] = newval[i];
3877 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
3878 block_input ();
3879 x_set_frame_alpha (f);
3880 unblock_input ();
3881 #endif
3883 return;
3886 #ifndef HAVE_NS
3888 /* Non-zero if mouse is grabbed on DPYINFO
3889 and we know the frame where it is. */
3891 bool x_mouse_grabbed (Display_Info *dpyinfo)
3893 return (dpyinfo->grabbed
3894 && dpyinfo->last_mouse_frame
3895 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
3898 /* Re-highlight something with mouse-face properties
3899 on DPYINFO using saved frame and mouse position. */
3901 void
3902 x_redo_mouse_highlight (Display_Info *dpyinfo)
3904 if (dpyinfo->last_mouse_motion_frame
3905 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
3906 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
3907 dpyinfo->last_mouse_motion_x,
3908 dpyinfo->last_mouse_motion_y);
3911 #endif /* HAVE_NS */
3913 /* Subroutines of creating an X frame. */
3915 /* Make sure that Vx_resource_name is set to a reasonable value.
3916 Fix it up, or set it to `emacs' if it is too hopeless. */
3918 void
3919 validate_x_resource_name (void)
3921 ptrdiff_t len = 0;
3922 /* Number of valid characters in the resource name. */
3923 ptrdiff_t good_count = 0;
3924 /* Number of invalid characters in the resource name. */
3925 ptrdiff_t bad_count = 0;
3926 Lisp_Object new;
3927 ptrdiff_t i;
3929 if (!STRINGP (Vx_resource_class))
3930 Vx_resource_class = build_string (EMACS_CLASS);
3932 if (STRINGP (Vx_resource_name))
3934 unsigned char *p = SDATA (Vx_resource_name);
3936 len = SBYTES (Vx_resource_name);
3938 /* Only letters, digits, - and _ are valid in resource names.
3939 Count the valid characters and count the invalid ones. */
3940 for (i = 0; i < len; i++)
3942 int c = p[i];
3943 if (! ((c >= 'a' && c <= 'z')
3944 || (c >= 'A' && c <= 'Z')
3945 || (c >= '0' && c <= '9')
3946 || c == '-' || c == '_'))
3947 bad_count++;
3948 else
3949 good_count++;
3952 else
3953 /* Not a string => completely invalid. */
3954 bad_count = 5, good_count = 0;
3956 /* If name is valid already, return. */
3957 if (bad_count == 0)
3958 return;
3960 /* If name is entirely invalid, or nearly so, or is so implausibly
3961 large that alloca might not work, use `emacs'. */
3962 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
3964 Vx_resource_name = build_string ("emacs");
3965 return;
3968 /* Name is partly valid. Copy it and replace the invalid characters
3969 with underscores. */
3971 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3973 for (i = 0; i < len; i++)
3975 int c = SREF (new, i);
3976 if (! ((c >= 'a' && c <= 'z')
3977 || (c >= 'A' && c <= 'Z')
3978 || (c >= '0' && c <= '9')
3979 || c == '-' || c == '_'))
3980 SSET (new, i, '_');
3984 /* Get specified attribute from resource database RDB.
3985 See Fx_get_resource below for other parameters. */
3987 static Lisp_Object
3988 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
3990 CHECK_STRING (attribute);
3991 CHECK_STRING (class);
3993 if (!NILP (component))
3994 CHECK_STRING (component);
3995 if (!NILP (subclass))
3996 CHECK_STRING (subclass);
3997 if (NILP (component) != NILP (subclass))
3998 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
4000 validate_x_resource_name ();
4002 /* Allocate space for the components, the dots which separate them,
4003 and the final '\0'. Make them big enough for the worst case. */
4004 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4005 + (STRINGP (component)
4006 ? SBYTES (component) : 0)
4007 + SBYTES (attribute)
4008 + 3);
4010 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4011 + SBYTES (class)
4012 + (STRINGP (subclass)
4013 ? SBYTES (subclass) : 0)
4014 + 3);
4015 USE_SAFE_ALLOCA;
4016 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4017 char *class_key = name_key + name_keysize;
4019 /* Start with emacs.FRAMENAME for the name (the specific one)
4020 and with `Emacs' for the class key (the general one). */
4021 char *nz = lispstpcpy (name_key, Vx_resource_name);
4022 char *cz = lispstpcpy (class_key, Vx_resource_class);
4024 *cz++ = '.';
4025 cz = lispstpcpy (cz, class);
4027 if (!NILP (component))
4029 *cz++ = '.';
4030 lispstpcpy (cz, subclass);
4032 *nz++ = '.';
4033 nz = lispstpcpy (nz, component);
4036 *nz++ = '.';
4037 lispstpcpy (nz, attribute);
4039 char *value = x_get_string_resource (rdb, name_key, class_key);
4040 SAFE_FREE();
4042 if (value && *value)
4043 return build_string (value);
4044 else
4045 return Qnil;
4049 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4050 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4051 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4052 class, where INSTANCE is the name under which Emacs was invoked, or
4053 the name specified by the `-name' or `-rn' command-line arguments.
4055 The optional arguments COMPONENT and SUBCLASS add to the key and the
4056 class, respectively. You must specify both of them or neither.
4057 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4058 and the class is `Emacs.CLASS.SUBCLASS'. */)
4059 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4060 Lisp_Object subclass)
4062 check_window_system (NULL);
4064 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4065 attribute, class, component, subclass);
4068 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4070 Lisp_Object
4071 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4072 Lisp_Object class, Lisp_Object component,
4073 Lisp_Object subclass)
4075 return xrdb_get_resource (dpyinfo->xrdb,
4076 attribute, class, component, subclass);
4079 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT
4080 /* Used when C code wants a resource value. */
4081 /* Called from oldXMenu/Create.c. */
4082 char *
4083 x_get_resource_string (const char *attribute, const char *class)
4085 char *result;
4086 struct frame *sf = SELECTED_FRAME ();
4087 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4088 USE_SAFE_ALLOCA;
4090 /* Allocate space for the components, the dots which separate them,
4091 and the final '\0'. */
4092 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4093 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4094 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4095 char *class_key = name_key + name_keysize;
4097 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4098 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4100 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4101 name_key, class_key);
4102 SAFE_FREE ();
4103 return result;
4105 #endif
4107 /* Return the value of parameter PARAM.
4109 First search ALIST, then Vdefault_frame_alist, then the X defaults
4110 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4112 Convert the resource to the type specified by desired_type.
4114 If no default is specified, return Qunbound. If you call
4115 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4116 and don't let it get stored in any Lisp-visible variables! */
4118 Lisp_Object
4119 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4120 const char *attribute, const char *class, enum resource_types type)
4122 Lisp_Object tem;
4124 tem = Fassq (param, alist);
4126 if (!NILP (tem))
4128 /* If we find this parm in ALIST, clear it out
4129 so that it won't be "left over" at the end. */
4130 Lisp_Object tail;
4131 XSETCAR (tem, Qnil);
4132 /* In case the parameter appears more than once in the alist,
4133 clear it out. */
4134 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4135 if (CONSP (XCAR (tail))
4136 && EQ (XCAR (XCAR (tail)), param))
4137 XSETCAR (XCAR (tail), Qnil);
4139 else
4140 tem = Fassq (param, Vdefault_frame_alist);
4142 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4143 look in the X resources. */
4144 if (EQ (tem, Qnil))
4146 if (attribute && dpyinfo)
4148 AUTO_STRING (at, attribute);
4149 AUTO_STRING (cl, class);
4150 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4152 if (NILP (tem))
4153 return Qunbound;
4155 switch (type)
4157 case RES_TYPE_NUMBER:
4158 return make_number (atoi (SSDATA (tem)));
4160 case RES_TYPE_BOOLEAN_NUMBER:
4161 if (!strcmp (SSDATA (tem), "on")
4162 || !strcmp (SSDATA (tem), "true"))
4163 return make_number (1);
4164 return make_number (atoi (SSDATA (tem)));
4165 break;
4167 case RES_TYPE_FLOAT:
4168 return make_float (atof (SSDATA (tem)));
4170 case RES_TYPE_BOOLEAN:
4171 tem = Fdowncase (tem);
4172 if (!strcmp (SSDATA (tem), "on")
4173 #ifdef HAVE_NS
4174 || !strcmp (SSDATA (tem), "yes")
4175 #endif
4176 || !strcmp (SSDATA (tem), "true"))
4177 return Qt;
4178 else
4179 return Qnil;
4181 case RES_TYPE_STRING:
4182 return tem;
4184 case RES_TYPE_SYMBOL:
4185 /* As a special case, we map the values `true' and `on'
4186 to Qt, and `false' and `off' to Qnil. */
4188 Lisp_Object lower;
4189 lower = Fdowncase (tem);
4190 if (!strcmp (SSDATA (lower), "on")
4191 #ifdef HAVE_NS
4192 || !strcmp (SSDATA (lower), "yes")
4193 #endif
4194 || !strcmp (SSDATA (lower), "true"))
4195 return Qt;
4196 else if (!strcmp (SSDATA (lower), "off")
4197 #ifdef HAVE_NS
4198 || !strcmp (SSDATA (lower), "no")
4199 #endif
4200 || !strcmp (SSDATA (lower), "false"))
4201 return Qnil;
4202 else
4203 return Fintern (tem, Qnil);
4206 default:
4207 emacs_abort ();
4210 else
4211 return Qunbound;
4213 return Fcdr (tem);
4216 static Lisp_Object
4217 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
4218 const char *attribute, const char *class,
4219 enum resource_types type)
4221 return x_get_arg (FRAME_DISPLAY_INFO (f),
4222 alist, param, attribute, class, type);
4225 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
4227 Lisp_Object
4228 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
4229 Lisp_Object param,
4230 const char *attribute, const char *class,
4231 enum resource_types type)
4233 Lisp_Object value;
4235 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
4236 attribute, class, type);
4237 if (! NILP (value) && ! EQ (value, Qunbound))
4238 store_frame_param (f, param, value);
4240 return value;
4244 /* Record in frame F the specified or default value according to ALIST
4245 of the parameter named PROP (a Lisp symbol).
4246 If no value is specified for PROP, look for an X default for XPROP
4247 on the frame named NAME.
4248 If that is not found either, use the value DEFLT. */
4250 Lisp_Object
4251 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
4252 Lisp_Object deflt, const char *xprop, const char *xclass,
4253 enum resource_types type)
4255 Lisp_Object tem;
4257 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
4258 if (EQ (tem, Qunbound))
4259 tem = deflt;
4260 AUTO_FRAME_ARG (arg, prop, tem);
4261 x_set_frame_parameters (f, arg);
4262 return tem;
4266 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
4269 * XParseGeometry parses strings of the form
4270 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
4271 * width, height, xoffset, and yoffset are unsigned integers.
4272 * Example: "=80x24+300-49"
4273 * The equal sign is optional.
4274 * It returns a bitmask that indicates which of the four values
4275 * were actually found in the string. For each value found,
4276 * the corresponding argument is updated; for each value
4277 * not found, the corresponding argument is left unchanged.
4280 static int
4281 XParseGeometry (char *string,
4282 int *x, int *y,
4283 unsigned int *width, unsigned int *height)
4285 int mask = NoValue;
4286 char *strind;
4287 unsigned long tempWidth, tempHeight;
4288 long int tempX, tempY;
4289 char *nextCharacter;
4291 if (string == NULL || *string == '\0')
4292 return mask;
4293 if (*string == '=')
4294 string++; /* ignore possible '=' at beg of geometry spec */
4296 strind = string;
4297 if (*strind != '+' && *strind != '-' && *strind != 'x')
4299 tempWidth = strtoul (strind, &nextCharacter, 10);
4300 if (strind == nextCharacter)
4301 return 0;
4302 strind = nextCharacter;
4303 mask |= WidthValue;
4306 if (*strind == 'x' || *strind == 'X')
4308 strind++;
4309 tempHeight = strtoul (strind, &nextCharacter, 10);
4310 if (strind == nextCharacter)
4311 return 0;
4312 strind = nextCharacter;
4313 mask |= HeightValue;
4316 if (*strind == '+' || *strind == '-')
4318 if (*strind == '-')
4319 mask |= XNegative;
4320 tempX = strtol (strind, &nextCharacter, 10);
4321 if (strind == nextCharacter)
4322 return 0;
4323 strind = nextCharacter;
4324 mask |= XValue;
4325 if (*strind == '+' || *strind == '-')
4327 if (*strind == '-')
4328 mask |= YNegative;
4329 tempY = strtol (strind, &nextCharacter, 10);
4330 if (strind == nextCharacter)
4331 return 0;
4332 strind = nextCharacter;
4333 mask |= YValue;
4337 /* If strind isn't at the end of the string then it's an invalid
4338 geometry specification. */
4340 if (*strind != '\0')
4341 return 0;
4343 if (mask & XValue)
4344 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
4345 if (mask & YValue)
4346 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
4347 if (mask & WidthValue)
4348 *width = min (tempWidth, UINT_MAX);
4349 if (mask & HeightValue)
4350 *height = min (tempHeight, UINT_MAX);
4351 return mask;
4354 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
4357 /* NS used to define x-parse-geometry in ns-win.el, but that confused
4358 make-docfile: the documentation string in ns-win.el was used for
4359 x-parse-geometry even in non-NS builds.
4361 With two definitions of x-parse-geometry in this file, various
4362 things still get confused (eg M-x apropos documentation), so that
4363 it is best if the two definitions just share the same doc-string.
4365 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
4366 doc: /* Parse a display geometry string STRING.
4367 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
4368 The properties returned may include `top', `left', `height', and `width'.
4369 For X, the value of `left' or `top' may be an integer,
4370 or a list (+ N) meaning N pixels relative to top/left corner,
4371 or a list (- N) meaning -N pixels relative to bottom/right corner.
4372 On Nextstep, this just calls `ns-parse-geometry'. */)
4373 (Lisp_Object string)
4375 int geometry, x, y;
4376 unsigned int width, height;
4377 Lisp_Object result;
4379 CHECK_STRING (string);
4381 #ifdef HAVE_NS
4382 if (strchr (SSDATA (string), ' ') != NULL)
4383 return call1 (Qns_parse_geometry, string);
4384 #endif
4385 geometry = XParseGeometry (SSDATA (string),
4386 &x, &y, &width, &height);
4387 result = Qnil;
4388 if (geometry & XValue)
4390 Lisp_Object element;
4392 if (x >= 0 && (geometry & XNegative))
4393 element = list3 (Qleft, Qminus, make_number (-x));
4394 else if (x < 0 && ! (geometry & XNegative))
4395 element = list3 (Qleft, Qplus, make_number (x));
4396 else
4397 element = Fcons (Qleft, make_number (x));
4398 result = Fcons (element, result);
4401 if (geometry & YValue)
4403 Lisp_Object element;
4405 if (y >= 0 && (geometry & YNegative))
4406 element = list3 (Qtop, Qminus, make_number (-y));
4407 else if (y < 0 && ! (geometry & YNegative))
4408 element = list3 (Qtop, Qplus, make_number (y));
4409 else
4410 element = Fcons (Qtop, make_number (y));
4411 result = Fcons (element, result);
4414 if (geometry & WidthValue)
4415 result = Fcons (Fcons (Qwidth, make_number (width)), result);
4416 if (geometry & HeightValue)
4417 result = Fcons (Fcons (Qheight, make_number (height)), result);
4419 return result;
4423 /* Calculate the desired size and position of frame F.
4424 Return the flags saying which aspects were specified.
4426 Also set the win_gravity and size_hint_flags of F.
4428 Adjust height for toolbar if TOOLBAR_P is 1.
4430 This function does not make the coordinates positive. */
4432 #define DEFAULT_ROWS 35
4433 #define DEFAULT_COLS 80
4435 long
4436 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
4438 Lisp_Object height, width, user_size, top, left, user_position;
4439 long window_prompting = 0;
4440 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
4442 /* Default values if we fall through.
4443 Actually, if that happens we should get
4444 window manager prompting. */
4445 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
4446 SET_FRAME_COLS (f, DEFAULT_COLS);
4447 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
4448 SET_FRAME_LINES (f, DEFAULT_ROWS);
4450 /* Window managers expect that if program-specified
4451 positions are not (0,0), they're intentional, not defaults. */
4452 f->top_pos = 0;
4453 f->left_pos = 0;
4455 /* Ensure that earlier new_width and new_height settings won't
4456 override what we specify below. */
4457 f->new_width = f->new_height = 0;
4459 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4460 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4461 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
4463 if (!EQ (width, Qunbound))
4465 CHECK_NUMBER (width);
4466 if (! (0 <= XINT (width) && XINT (width) <= INT_MAX))
4467 xsignal1 (Qargs_out_of_range, width);
4469 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
4472 if (!EQ (height, Qunbound))
4474 CHECK_NUMBER (height);
4475 if (! (0 <= XINT (height) && XINT (height) <= INT_MAX))
4476 xsignal1 (Qargs_out_of_range, height);
4478 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
4481 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4482 if (!NILP (user_size) && !EQ (user_size, Qunbound))
4483 window_prompting |= USSize;
4484 else
4485 window_prompting |= PSize;
4488 /* Add a tool bar height to the initial frame height so that the user
4489 gets a text display area of the size he specified with -g or via
4490 .Xdefaults. Later changes of the tool bar height don't change the
4491 frame size. This is done so that users can create tall Emacs
4492 frames without having to guess how tall the tool bar will get. */
4493 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4495 int margin, relief;
4497 relief = (tool_bar_button_relief >= 0
4498 ? tool_bar_button_relief
4499 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4501 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
4502 margin = XFASTINT (Vtool_bar_button_margin);
4503 else if (CONSP (Vtool_bar_button_margin)
4504 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
4505 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4506 else
4507 margin = 0;
4509 FRAME_TOOL_BAR_HEIGHT (f)
4510 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4511 Vframe_initial_frame_tool_bar_height = make_number (FRAME_TOOL_BAR_HEIGHT (f));
4514 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4515 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4516 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4517 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
4519 if (EQ (top, Qminus))
4521 f->top_pos = 0;
4522 window_prompting |= YNegative;
4524 else if (CONSP (top) && EQ (XCAR (top), Qminus)
4525 && CONSP (XCDR (top))
4526 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
4528 f->top_pos = - XINT (XCAR (XCDR (top)));
4529 window_prompting |= YNegative;
4531 else if (CONSP (top) && EQ (XCAR (top), Qplus)
4532 && CONSP (XCDR (top))
4533 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
4535 f->top_pos = XINT (XCAR (XCDR (top)));
4537 else if (EQ (top, Qunbound))
4538 f->top_pos = 0;
4539 else
4541 CHECK_TYPE_RANGED_INTEGER (int, top);
4542 f->top_pos = XINT (top);
4543 if (f->top_pos < 0)
4544 window_prompting |= YNegative;
4547 if (EQ (left, Qminus))
4549 f->left_pos = 0;
4550 window_prompting |= XNegative;
4552 else if (CONSP (left) && EQ (XCAR (left), Qminus)
4553 && CONSP (XCDR (left))
4554 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
4556 f->left_pos = - XINT (XCAR (XCDR (left)));
4557 window_prompting |= XNegative;
4559 else if (CONSP (left) && EQ (XCAR (left), Qplus)
4560 && CONSP (XCDR (left))
4561 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
4563 f->left_pos = XINT (XCAR (XCDR (left)));
4565 else if (EQ (left, Qunbound))
4566 f->left_pos = 0;
4567 else
4569 CHECK_TYPE_RANGED_INTEGER (int, left);
4570 f->left_pos = XINT (left);
4571 if (f->left_pos < 0)
4572 window_prompting |= XNegative;
4575 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
4576 window_prompting |= USPosition;
4577 else
4578 window_prompting |= PPosition;
4581 if (window_prompting & XNegative)
4583 if (window_prompting & YNegative)
4584 f->win_gravity = SouthEastGravity;
4585 else
4586 f->win_gravity = NorthEastGravity;
4588 else
4590 if (window_prompting & YNegative)
4591 f->win_gravity = SouthWestGravity;
4592 else
4593 f->win_gravity = NorthWestGravity;
4596 f->size_hint_flags = window_prompting;
4598 return window_prompting;
4603 #endif /* HAVE_WINDOW_SYSTEM */
4605 void
4606 frame_make_pointer_invisible (struct frame *f)
4608 if (! NILP (Vmake_pointer_invisible))
4610 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
4611 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4613 f->mouse_moved = 0;
4614 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
4615 f->pointer_invisible = 1;
4620 void
4621 frame_make_pointer_visible (struct frame *f)
4623 /* We don't check Vmake_pointer_invisible here in case the
4624 pointer was invisible when Vmake_pointer_invisible was set to nil. */
4625 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
4626 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4628 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
4629 f->pointer_invisible = 0;
4633 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
4634 Sframe_pointer_visible_p, 0, 1, 0,
4635 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
4636 Otherwise it returns nil. FRAME omitted or nil means the
4637 selected frame. This is useful when `make-pointer-invisible' is set. */)
4638 (Lisp_Object frame)
4640 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
4645 /***********************************************************************
4646 Multimonitor data
4647 ***********************************************************************/
4649 #ifdef HAVE_WINDOW_SYSTEM
4651 # if (defined HAVE_NS \
4652 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
4653 void
4654 free_monitors (struct MonitorInfo *monitors, int n_monitors)
4656 int i;
4657 for (i = 0; i < n_monitors; ++i)
4658 xfree (monitors[i].name);
4659 xfree (monitors);
4661 # endif
4663 Lisp_Object
4664 make_monitor_attribute_list (struct MonitorInfo *monitors,
4665 int n_monitors,
4666 int primary_monitor,
4667 Lisp_Object monitor_frames,
4668 const char *source)
4670 Lisp_Object attributes_list = Qnil;
4671 Lisp_Object primary_monitor_attributes = Qnil;
4672 int i;
4674 for (i = 0; i < n_monitors; ++i)
4676 Lisp_Object geometry, workarea, attributes = Qnil;
4677 struct MonitorInfo *mi = &monitors[i];
4679 if (mi->geom.width == 0) continue;
4681 workarea = list4i (mi->work.x, mi->work.y,
4682 mi->work.width, mi->work.height);
4683 geometry = list4i (mi->geom.x, mi->geom.y,
4684 mi->geom.width, mi->geom.height);
4685 attributes = Fcons (Fcons (Qsource, build_string (source)),
4686 attributes);
4687 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
4688 attributes);
4689 attributes = Fcons (Fcons (Qmm_size,
4690 list2i (mi->mm_width, mi->mm_height)),
4691 attributes);
4692 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
4693 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
4694 if (mi->name)
4695 attributes = Fcons (Fcons (Qname, make_string (mi->name,
4696 strlen (mi->name))),
4697 attributes);
4699 if (i == primary_monitor)
4700 primary_monitor_attributes = attributes;
4701 else
4702 attributes_list = Fcons (attributes, attributes_list);
4705 if (!NILP (primary_monitor_attributes))
4706 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
4707 return attributes_list;
4710 #endif /* HAVE_WINDOW_SYSTEM */
4713 /***********************************************************************
4714 Initialization
4715 ***********************************************************************/
4717 void
4718 syms_of_frame (void)
4720 DEFSYM (Qframep, "framep");
4721 DEFSYM (Qframe_live_p, "frame-live-p");
4722 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
4723 DEFSYM (Qexplicit_name, "explicit-name");
4724 DEFSYM (Qheight, "height");
4725 DEFSYM (Qicon, "icon");
4726 DEFSYM (Qminibuffer, "minibuffer");
4727 DEFSYM (Qmodeline, "modeline");
4728 DEFSYM (Qonly, "only");
4729 DEFSYM (Qnone, "none");
4730 DEFSYM (Qwidth, "width");
4731 DEFSYM (Qgeometry, "geometry");
4732 DEFSYM (Qicon_left, "icon-left");
4733 DEFSYM (Qicon_top, "icon-top");
4734 DEFSYM (Qtooltip, "tooltip");
4735 DEFSYM (Quser_position, "user-position");
4736 DEFSYM (Quser_size, "user-size");
4737 DEFSYM (Qwindow_id, "window-id");
4738 #ifdef HAVE_X_WINDOWS
4739 DEFSYM (Qouter_window_id, "outer-window-id");
4740 #endif
4741 DEFSYM (Qparent_id, "parent-id");
4742 DEFSYM (Qx, "x");
4743 DEFSYM (Qw32, "w32");
4744 DEFSYM (Qpc, "pc");
4745 DEFSYM (Qns, "ns");
4746 DEFSYM (Qvisible, "visible");
4747 DEFSYM (Qbuffer_predicate, "buffer-predicate");
4748 DEFSYM (Qbuffer_list, "buffer-list");
4749 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
4750 DEFSYM (Qdisplay_type, "display-type");
4751 DEFSYM (Qbackground_mode, "background-mode");
4752 DEFSYM (Qnoelisp, "noelisp");
4753 DEFSYM (Qtty_color_mode, "tty-color-mode");
4754 DEFSYM (Qtty, "tty");
4755 DEFSYM (Qtty_type, "tty-type");
4757 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
4759 DEFSYM (Qfullwidth, "fullwidth");
4760 DEFSYM (Qfullheight, "fullheight");
4761 DEFSYM (Qfullboth, "fullboth");
4762 DEFSYM (Qmaximized, "maximized");
4763 DEFSYM (Qx_resource_name, "x-resource-name");
4764 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
4766 DEFSYM (Qterminal, "terminal");
4768 DEFSYM (Qworkarea, "workarea");
4769 DEFSYM (Qmm_size, "mm-size");
4770 DEFSYM (Qframes, "frames");
4771 DEFSYM (Qsource, "source");
4773 DEFSYM (Qframe_position, "frame-position");
4774 DEFSYM (Qframe_outer_size, "frame-outer-size");
4775 DEFSYM (Qexternal_border_size, "external-border-size");
4776 DEFSYM (Qtitle_height, "title-height");
4777 DEFSYM (Qmenu_bar_external, "menu-bar-external");
4778 DEFSYM (Qmenu_bar_size, "menu-bar-size");
4779 DEFSYM (Qtool_bar_external, "tool-bar-external");
4780 DEFSYM (Qtool_bar_size, "tool-bar-size");
4781 DEFSYM (Qframe_inner_size, "frame-inner-size");
4783 #ifdef HAVE_NS
4784 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
4785 #endif
4787 DEFSYM (Qalpha, "alpha");
4788 DEFSYM (Qauto_lower, "auto-lower");
4789 DEFSYM (Qauto_raise, "auto-raise");
4790 DEFSYM (Qborder_color, "border-color");
4791 DEFSYM (Qborder_width, "border-width");
4792 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
4793 DEFSYM (Qcursor_color, "cursor-color");
4794 DEFSYM (Qcursor_type, "cursor-type");
4795 DEFSYM (Qfont_backend, "font-backend");
4796 DEFSYM (Qfullscreen, "fullscreen");
4797 DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
4798 DEFSYM (Qicon_name, "icon-name");
4799 DEFSYM (Qicon_type, "icon-type");
4800 DEFSYM (Qinternal_border_width, "internal-border-width");
4801 DEFSYM (Qleft_fringe, "left-fringe");
4802 DEFSYM (Qline_spacing, "line-spacing");
4803 DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
4804 DEFSYM (Qmouse_color, "mouse-color");
4805 DEFSYM (Qname, "name");
4806 DEFSYM (Qright_divider_width, "right-divider-width");
4807 DEFSYM (Qright_fringe, "right-fringe");
4808 DEFSYM (Qscreen_gamma, "screen-gamma");
4809 DEFSYM (Qscroll_bar_background, "scroll-bar-background");
4810 DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
4811 DEFSYM (Qscroll_bar_height, "scroll-bar-height");
4812 DEFSYM (Qscroll_bar_width, "scroll-bar-width");
4813 DEFSYM (Qsticky, "sticky");
4814 DEFSYM (Qtitle, "title");
4815 DEFSYM (Qtool_bar_lines, "tool-bar-lines");
4816 DEFSYM (Qtool_bar_position, "tool-bar-position");
4817 DEFSYM (Qunsplittable, "unsplittable");
4818 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
4819 DEFSYM (Qvisibility, "visibility");
4820 DEFSYM (Qwait_for_wm, "wait-for-wm");
4823 int i;
4825 for (i = 0; i < ARRAYELTS (frame_parms); i++)
4827 Lisp_Object v = (frame_parms[i].sym
4828 ? make_lisp_symbol (frame_parms[i].sym)
4829 : intern_c_string (frame_parms[i].name));
4830 Fput (v, Qx_frame_parameter, make_number (i));
4834 #ifdef HAVE_WINDOW_SYSTEM
4835 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
4836 doc: /* The name Emacs uses to look up X resources.
4837 `x-get-resource' uses this as the first component of the instance name
4838 when requesting resource values.
4839 Emacs initially sets `x-resource-name' to the name under which Emacs
4840 was invoked, or to the value specified with the `-name' or `-rn'
4841 switches, if present.
4843 It may be useful to bind this variable locally around a call
4844 to `x-get-resource'. See also the variable `x-resource-class'. */);
4845 Vx_resource_name = Qnil;
4847 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
4848 doc: /* The class Emacs uses to look up X resources.
4849 `x-get-resource' uses this as the first component of the instance class
4850 when requesting resource values.
4852 Emacs initially sets `x-resource-class' to "Emacs".
4854 Setting this variable permanently is not a reasonable thing to do,
4855 but binding this variable locally around a call to `x-get-resource'
4856 is a reasonable practice. See also the variable `x-resource-name'. */);
4857 Vx_resource_class = build_string (EMACS_CLASS);
4859 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
4860 doc: /* The lower limit of the frame opacity (alpha transparency).
4861 The value should range from 0 (invisible) to 100 (completely opaque).
4862 You can also use a floating number between 0.0 and 1.0. */);
4863 Vframe_alpha_lower_limit = make_number (20);
4864 #endif
4866 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
4867 doc: /* Alist of default values for frame creation.
4868 These may be set in your init file, like this:
4869 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
4870 These override values given in window system configuration data,
4871 including X Windows' defaults database.
4872 For values specific to the first Emacs frame, see `initial-frame-alist'.
4873 For window-system specific values, see `window-system-default-frame-alist'.
4874 For values specific to the separate minibuffer frame, see
4875 `minibuffer-frame-alist'.
4876 The `menu-bar-lines' element of the list controls whether new frames
4877 have menu bars; `menu-bar-mode' works by altering this element.
4878 Setting this variable does not affect existing frames, only new ones. */);
4879 Vdefault_frame_alist = Qnil;
4881 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
4882 doc: /* Default position of vertical scroll bars on this window-system. */);
4883 #ifdef HAVE_WINDOW_SYSTEM
4884 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
4885 /* MS-Windows, Mac OS X, and GTK have scroll bars on the right by
4886 default. */
4887 Vdefault_frame_scroll_bars = Qright;
4888 #else
4889 Vdefault_frame_scroll_bars = Qleft;
4890 #endif
4891 #else
4892 Vdefault_frame_scroll_bars = Qnil;
4893 #endif
4895 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
4896 scroll_bar_adjust_thumb_portion_p,
4897 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
4898 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
4899 even if the end of the buffer is shown (i.e. overscrolling).
4900 Set to nil if you want the thumb to be at the bottom when the end of the buffer
4901 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
4902 is visible. In this case you can not overscroll. */);
4903 scroll_bar_adjust_thumb_portion_p = 1;
4905 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
4906 doc: /* The initial frame-object, which represents Emacs's stdout. */);
4908 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
4909 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4910 `mouse-position' and `mouse-pixel-position' call this function, passing their
4911 usual return value as argument, and return whatever this function returns.
4912 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4913 which need to do mouse handling at the Lisp level. */);
4914 Vmouse_position_function = Qnil;
4916 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
4917 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4918 If the value is an integer, highlighting is only shown after moving the
4919 mouse, while keyboard input turns off the highlight even when the mouse
4920 is over the clickable text. However, the mouse shape still indicates
4921 when the mouse is over clickable text. */);
4922 Vmouse_highlight = Qt;
4924 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
4925 doc: /* If non-nil, make pointer invisible while typing.
4926 The pointer becomes visible again when the mouse is moved. */);
4927 Vmake_pointer_invisible = Qt;
4929 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
4930 doc: /* Normal hook run when a frame gains input focus. */);
4931 Vfocus_in_hook = Qnil;
4932 DEFSYM (Qfocus_in_hook, "focus-in-hook");
4934 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
4935 doc: /* Normal hook run when a frame loses input focus. */);
4936 Vfocus_out_hook = Qnil;
4937 DEFSYM (Qfocus_out_hook, "focus-out-hook");
4939 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
4940 doc: /* Functions run before deleting a frame.
4941 The functions are run with one arg, the frame to be deleted.
4942 See `delete-frame'.
4944 Note that functions in this list may be called just before the frame is
4945 actually deleted, or some time later (or even both when an earlier function
4946 in `delete-frame-functions' (indirectly) calls `delete-frame'
4947 recursively). */);
4948 Vdelete_frame_functions = Qnil;
4949 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
4951 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
4952 doc: /* Non-nil if Menu-Bar mode is enabled.
4953 See the command `menu-bar-mode' for a description of this minor mode.
4954 Setting this variable directly does not take effect;
4955 either customize it (see the info node `Easy Customization')
4956 or call the function `menu-bar-mode'. */);
4957 Vmenu_bar_mode = Qt;
4959 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
4960 doc: /* Non-nil if Tool-Bar mode is enabled.
4961 See the command `tool-bar-mode' for a description of this minor mode.
4962 Setting this variable directly does not take effect;
4963 either customize it (see the info node `Easy Customization')
4964 or call the function `tool-bar-mode'. */);
4965 #ifdef HAVE_WINDOW_SYSTEM
4966 Vtool_bar_mode = Qt;
4967 #else
4968 Vtool_bar_mode = Qnil;
4969 #endif
4971 DEFVAR_LISP ("frame-initial-frame-tool-bar-height", Vframe_initial_frame_tool_bar_height,
4972 doc: /* Height of tool bar of initial frame. */);
4973 Vframe_initial_frame_tool_bar_height = make_number (0);
4975 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4976 doc: /* Minibufferless frames use this frame's minibuffer.
4977 Emacs cannot create minibufferless frames unless this is set to an
4978 appropriate surrogate.
4980 Emacs consults this variable only when creating minibufferless
4981 frames; once the frame is created, it sticks with its assigned
4982 minibuffer, no matter what this variable is set to. This means that
4983 this variable doesn't necessarily say anything meaningful about the
4984 current set of frames, or where the minibuffer is currently being
4985 displayed.
4987 This variable is local to the current terminal and cannot be buffer-local. */);
4989 DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse,
4990 doc: /* Non-nil if window system changes focus when you move the mouse.
4991 You should set this variable to tell Emacs how your window manager
4992 handles focus, since there is no way in general for Emacs to find out
4993 automatically. See also `mouse-autoselect-window'. */);
4994 focus_follows_mouse = 0;
4996 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
4997 doc: /* Non-nil means resize frames pixelwise.
4998 If this option is nil, resizing a frame rounds its sizes to the frame's
4999 current values of `frame-char-height' and `frame-char-width'. If this
5000 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5001 by one pixel.
5003 With some window managers you may have to set this to non-nil in order
5004 to set the size of a frame in pixels, to maximize frames or to make them
5005 fullscreen. To resize your initial frame pixelwise, set this option to
5006 a non-nil value in your init file. */);
5007 frame_resize_pixelwise = 0;
5009 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
5010 doc: /* Whether frames should be resized implicitly.
5011 If this option is nil, setting font, menu bar, tool bar, internal
5012 borders, fringes or scroll bars of a specific frame may resize the frame
5013 in order to preserve the number of columns or lines it displays. If
5014 this option is `t', no such resizing is done. Note that the size of
5015 fullscreen and maximized frames, the height of fullheight frames and the
5016 width of fullwidth frames never change implicitly.
5018 The value of this option can be also be a list of frame parameters. In
5019 this case, resizing is inhibited when changing a parameter that appears
5020 in that list. The parameters currently handled by this option include
5021 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
5022 `tool-bar-lines'.
5024 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
5025 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
5026 `right-fringe' is handled as if the frame contained just one live
5027 window. This means, for example, that removing vertical scroll bars on
5028 a frame containing several side by side windows will shrink the frame
5029 width by the width of one scroll bar provided this option is nil and
5030 keep it unchanged if this option is either `t' or a list containing
5031 `vertical-scroll-bars'.
5033 The default value is '(tool-bar-lines) on Lucid, Motif and Windows
5034 \(which means that adding/removing a tool bar does not change the frame
5035 height), nil on all other window systems including GTK+ (which means
5036 that changing any of the parameters listed above may change the size of
5037 the frame), and `t' otherwise (which means the frame size never changes
5038 implicitly when there's no window system support).
5040 Note that when a frame is not large enough to accommodate a change of
5041 any of the parameters listed above, Emacs may try to enlarge the frame
5042 even if this option is non-nil. */);
5043 #if defined (HAVE_WINDOW_SYSTEM)
5044 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
5045 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
5046 #else
5047 frame_inhibit_implied_resize = Qnil;
5048 #endif
5049 #else
5050 frame_inhibit_implied_resize = Qt;
5051 #endif
5053 staticpro (&Vframe_list);
5055 defsubr (&Sframep);
5056 defsubr (&Sframe_live_p);
5057 defsubr (&Swindow_system);
5058 defsubr (&Sframe_windows_min_size);
5059 defsubr (&Smake_terminal_frame);
5060 defsubr (&Shandle_switch_frame);
5061 defsubr (&Sselect_frame);
5062 defsubr (&Sselected_frame);
5063 defsubr (&Sframe_list);
5064 defsubr (&Snext_frame);
5065 defsubr (&Sprevious_frame);
5066 defsubr (&Slast_nonminibuf_frame);
5067 defsubr (&Sdelete_frame);
5068 defsubr (&Smouse_position);
5069 defsubr (&Smouse_pixel_position);
5070 defsubr (&Sset_mouse_position);
5071 defsubr (&Sset_mouse_pixel_position);
5072 #if 0
5073 defsubr (&Sframe_configuration);
5074 defsubr (&Srestore_frame_configuration);
5075 #endif
5076 defsubr (&Smake_frame_visible);
5077 defsubr (&Smake_frame_invisible);
5078 defsubr (&Siconify_frame);
5079 defsubr (&Sframe_visible_p);
5080 defsubr (&Svisible_frame_list);
5081 defsubr (&Sraise_frame);
5082 defsubr (&Slower_frame);
5083 defsubr (&Sx_focus_frame);
5084 defsubr (&Scan_run_window_configuration_change_hook);
5085 defsubr (&Sredirect_frame_focus);
5086 defsubr (&Sframe_focus);
5087 defsubr (&Sframe_parameters);
5088 defsubr (&Sframe_parameter);
5089 defsubr (&Smodify_frame_parameters);
5090 defsubr (&Sframe_char_height);
5091 defsubr (&Sframe_char_width);
5092 defsubr (&Sframe_pixel_height);
5093 defsubr (&Sframe_pixel_width);
5094 defsubr (&Sframe_text_cols);
5095 defsubr (&Sframe_text_lines);
5096 defsubr (&Sframe_total_cols);
5097 defsubr (&Sframe_total_lines);
5098 defsubr (&Sframe_text_width);
5099 defsubr (&Sframe_text_height);
5100 defsubr (&Sscroll_bar_width);
5101 defsubr (&Sscroll_bar_height);
5102 defsubr (&Sfringe_width);
5103 defsubr (&Sborder_width);
5104 defsubr (&Sright_divider_width);
5105 defsubr (&Sbottom_divider_width);
5106 defsubr (&Stool_bar_pixel_width);
5107 defsubr (&Sset_frame_height);
5108 defsubr (&Sset_frame_width);
5109 defsubr (&Sset_frame_size);
5110 defsubr (&Sset_frame_position);
5111 defsubr (&Sframe_pointer_visible_p);
5113 #ifdef HAVE_WINDOW_SYSTEM
5114 defsubr (&Sx_get_resource);
5115 defsubr (&Sx_parse_geometry);
5116 #endif