root/src/frame.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fset_buffer_predicate
  2. fset_minibuffer_window
  3. decode_live_frame
  4. decode_any_frame
  5. display_available
  6. decode_window_system_frame
  7. check_window_system
  8. get_frame_param
  9. frame_inhibit_resize
  10. set_menu_bar_lines
  11. set_tab_bar_lines
  12. DEFUN
  13. DEFUN
  14. DEFUN
  15. frame_windows_min_size
  16. keep_ratio
  17. frame_size_history_adjust
  18. frame_size_history_plain
  19. frame_size_history_extra
  20. adjust_frame_size
  21. allocate_frame
  22. make_frame
  23. make_frame_without_minibuffer
  24. make_minibuffer_frame
  25. make_initial_frame
  26. make_terminal_frame
  27. get_future_frame_param
  28. DEFUN
  29. do_switch_frame
  30. DEFUN
  31. DEFUN
  32. DEFUN
  33. DEFUN
  34. DEFUN
  35. frame_ancestor_p
  36. candidate_frame
  37. next_frame
  38. prev_frame
  39. DEFUN
  40. other_frames
  41. delete_frame
  42. frame_internal_border_part
  43. DEFUN
  44. mouse_position
  45. DEFUN
  46. frame_char_to_pixel_position
  47. frame_set_mouse_position
  48. DEFUN
  49. make_frame_visible_1
  50. DEFUN
  51. DEFUN
  52. DEFUN
  53. DEFUN
  54. DEFUN
  55. DEFUN
  56. frames_discard_buffer
  57. store_in_alist
  58. frame_name_fnn_p
  59. set_term_frame_name
  60. store_frame_param
  61. frame_unspecified_color
  62. DEFUN
  63. DEFUN
  64. DEFUN
  65. DEFUN
  66. DEFUN
  67. DEFUN
  68. DEFUN
  69. DEFUN
  70. DEFUN
  71. DEFUN
  72. DEFUN
  73. DEFUN
  74. DEFUN
  75. DEFUN
  76. DEFUN
  77. DEFUN
  78. DEFUN
  79. DEFUN
  80. DEFUN
  81. check_frame_pixels
  82. DEFUN
  83. DEFUN
  84. DEFUN
  85. frame_float
  86. gui_set_frame_parameters_1
  87. gui_set_frame_parameters
  88. gui_report_frame_params
  89. gui_set_fullscreen
  90. gui_set_line_spacing
  91. gui_set_screen_gamma
  92. gui_set_font
  93. gui_set_font_backend
  94. gui_set_left_fringe
  95. gui_set_right_fringe
  96. gui_set_border_width
  97. gui_set_right_divider_width
  98. gui_set_bottom_divider_width
  99. gui_set_visibility
  100. gui_set_autoraise
  101. gui_set_autolower
  102. gui_set_unsplittable
  103. gui_set_vertical_scroll_bars
  104. gui_set_horizontal_scroll_bars
  105. gui_set_scroll_bar_width
  106. gui_set_scroll_bar_height
  107. gui_set_alpha
  108. gui_set_alpha_background
  109. gui_set_no_special_glyphs
  110. gui_mouse_grabbed
  111. gui_redo_mouse_highlight
  112. validate_x_resource_name
  113. gui_display_get_resource
  114. x_get_resource_string
  115. gui_display_get_arg
  116. gui_frame_get_arg
  117. gui_frame_get_and_record_arg
  118. gui_default_parameter
  119. XParseGeometry
  120. DEFUN
  121. gui_figure_window_size
  122. frame_make_pointer_invisible
  123. frame_make_pointer_visible
  124. DEFUN
  125. DEFUN
  126. free_monitors
  127. make_monitor_attribute_list
  128. init_frame_once
  129. init_frame_once_for_pdumper
  130. syms_of_frame

     1 /* Generic frame functions.
     2 
     3 Copyright (C) 1993-1995, 1997, 1999-2023 Free Software Foundation, Inc.
     4 
     5 This file is part of GNU Emacs.
     6 
     7 GNU Emacs is free software: you can redistribute it and/or modify
     8 it under the terms of the GNU General Public License as published by
     9 the Free Software Foundation, either version 3 of the License, or (at
    10 your option) any later version.
    11 
    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.
    16 
    17 You should have received a copy of the GNU General Public License
    18 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    19 
    20 #include <config.h>
    21 
    22 #include <stdio.h>
    23 #include <stdlib.h>
    24 #include <errno.h>
    25 #include <limits.h>
    26 
    27 #include <c-ctype.h>
    28 
    29 #include "lisp.h"
    30 
    31 #ifdef HAVE_WINDOW_SYSTEM
    32 #include TERM_HEADER
    33 #endif /* HAVE_WINDOW_SYSTEM */
    34 
    35 #include "buffer.h"
    36 /* These help us bind and responding to switch-frame events.  */
    37 #include "keyboard.h"
    38 #include "frame.h"
    39 #include "blockinput.h"
    40 #include "termchar.h"
    41 #include "termhooks.h"
    42 #include "dispextern.h"
    43 #include "window.h"
    44 #ifdef HAVE_WINDOW_SYSTEM
    45 #include "fontset.h"
    46 #endif
    47 #include "cm.h"
    48 #ifdef MSDOS
    49 #include "msdos.h"
    50 #include "dosfns.h"
    51 #endif
    52 #ifdef USE_X_TOOLKIT
    53 #include "widget.h"
    54 #endif
    55 #include "pdumper.h"
    56 
    57 /* The currently selected frame.  */
    58 Lisp_Object selected_frame;
    59 
    60 /* The selected frame the last time window change functions were run.  */
    61 Lisp_Object old_selected_frame;
    62 
    63 /* A frame which is not just a mini-buffer, or NULL if there are no such
    64    frames.  This is usually the most recent such frame that was selected.  */
    65 
    66 static struct frame *last_nonminibuf_frame;
    67 
    68 /* False means there are no visible garbaged frames.  */
    69 bool frame_garbaged;
    70 
    71 /* The default tab bar height for future frames.  */
    72 int frame_default_tab_bar_height;
    73 
    74 /* The default tool bar height for future frames.  */
    75 #ifdef HAVE_EXT_TOOL_BAR
    76 enum { frame_default_tool_bar_height = 0 };
    77 #else
    78 int frame_default_tool_bar_height;
    79 #endif
    80 
    81 #ifdef HAVE_WINDOW_SYSTEM
    82 static void gui_report_frame_params (struct frame *, Lisp_Object *);
    83 #endif
    84 
    85 /* These setters are used only in this file, so they can be private.  */
    86 static void
    87 fset_buffer_predicate (struct frame *f, Lisp_Object val)
    88 {
    89   f->buffer_predicate = val;
    90 }
    91 static void
    92 fset_minibuffer_window (struct frame *f, Lisp_Object val)
    93 {
    94   f->minibuffer_window = val;
    95 }
    96 
    97 struct frame *
    98 decode_live_frame (register Lisp_Object frame)
    99 {
   100   if (NILP (frame))
   101     frame = selected_frame;
   102   CHECK_LIVE_FRAME (frame);
   103   return XFRAME (frame);
   104 }
   105 
   106 struct frame *
   107 decode_any_frame (register Lisp_Object frame)
   108 {
   109   if (NILP (frame))
   110     frame = selected_frame;
   111   CHECK_FRAME (frame);
   112   return XFRAME (frame);
   113 }
   114 
   115 #ifdef HAVE_WINDOW_SYSTEM
   116 bool
   117 display_available (void)
   118 {
   119   return x_display_list != NULL;
   120 }
   121 #endif
   122 
   123 struct frame *
   124 decode_window_system_frame (Lisp_Object frame)
   125 {
   126   struct frame *f = decode_live_frame (frame);
   127   check_window_system (f);
   128 #ifdef HAVE_WINDOW_SYSTEM
   129   return f;
   130 #endif
   131 }
   132 
   133 void
   134 check_window_system (struct frame *f)
   135 {
   136 #ifdef HAVE_WINDOW_SYSTEM
   137   if (window_system_available (f))
   138     return;
   139 #endif
   140   error (f ? "Window system frame should be used"
   141          : "Window system is not in use or not initialized");
   142 }
   143 
   144 /* Return the value of frame parameter PROP in frame FRAME.  */
   145 
   146 Lisp_Object
   147 get_frame_param (struct frame *frame, Lisp_Object prop)
   148 {
   149   return Fcdr (Fassq (prop, frame->param_alist));
   150 }
   151 
   152 
   153 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
   154    state of frame F would be affected by a vertical (horizontal if
   155    HORIZONTAL is true) resize.  PARAMETER is the symbol of the frame
   156    parameter that is changed.  */
   157 bool
   158 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
   159 {
   160   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
   161   bool inhibit
   162     = (f->after_make_frame
   163        ? (EQ (frame_inhibit_implied_resize, Qt)
   164           || (CONSP (frame_inhibit_implied_resize)
   165               && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
   166           || (horizontal
   167               && !NILP (fullscreen) && !EQ (fullscreen, Qfullheight))
   168           || (!horizontal
   169               && !NILP (fullscreen) && !EQ (fullscreen, Qfullwidth))
   170           || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
   171        : ((horizontal && f->inhibit_horizontal_resize)
   172           || (!horizontal && f->inhibit_vertical_resize)));
   173 
   174   return inhibit;
   175 }
   176 
   177 
   178 /** Set menu bar lines for a TTY frame.  */
   179 static void
   180 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   181 {
   182   int olines = FRAME_MENU_BAR_LINES (f);
   183   int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0;
   184 
   185   /* Right now, menu bars don't work properly in minibuf-only frames;
   186      most of the commands try to apply themselves to the minibuffer
   187      frame itself, and get an error because you can't switch buffers
   188      in or split the minibuffer window.  */
   189   if (!FRAME_MINIBUF_ONLY_P (f) && nlines != olines)
   190     {
   191       windows_or_buffers_changed = 14;
   192       FRAME_MENU_BAR_LINES (f) = FRAME_MENU_BAR_HEIGHT (f) = nlines;
   193       change_frame_size (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
   194                          false, true, false);
   195     }
   196 }
   197 
   198 
   199 /** Set tab bar lines for a TTY frame.  */
   200 static void
   201 set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   202 {
   203   int olines = FRAME_TAB_BAR_LINES (f);
   204   int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0;
   205 
   206   /* Right now, tab bars don't work properly in minibuf-only frames;
   207      most of the commands try to apply themselves to the minibuffer
   208      frame itself, and get an error because you can't switch buffers
   209      in or split the minibuffer window.  */
   210   if (!FRAME_MINIBUF_ONLY_P (f) && nlines != olines)
   211     {
   212       windows_or_buffers_changed = 14;
   213       FRAME_TAB_BAR_LINES (f) = FRAME_TAB_BAR_HEIGHT (f) = nlines;
   214       change_frame_size (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
   215                          false, true, false);
   216     }
   217 }
   218 
   219 Lisp_Object Vframe_list;
   220 
   221 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
   222        doc: /* Return non-nil if OBJECT is a frame.
   223 Value is:
   224   t for a termcap frame (a character-only terminal),
   225  `x' for an Emacs frame that is really an X window,
   226  `w32' for an Emacs frame that is a window on MS-Windows display,
   227  `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
   228  `pc' for a direct-write MS-DOS frame,
   229  `pgtk' for an Emacs frame running on pure GTK.
   230  `haiku' for an Emacs frame running in Haiku.
   231 See also `frame-live-p'.  */)
   232   (Lisp_Object object)
   233 {
   234   if (!FRAMEP (object))
   235     return Qnil;
   236   switch (XFRAME (object)->output_method)
   237     {
   238     case output_initial: /* The initial frame is like a termcap frame. */
   239     case output_termcap:
   240       return Qt;
   241     case output_x_window:
   242       return Qx;
   243     case output_w32:
   244       return Qw32;
   245     case output_msdos_raw:
   246       return Qpc;
   247     case output_ns:
   248       return Qns;
   249     case output_pgtk:
   250       return Qpgtk;
   251     case output_haiku:
   252       return Qhaiku;
   253     default:
   254       emacs_abort ();
   255     }
   256 }
   257 
   258 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
   259        doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
   260 Value is nil if OBJECT is not a live frame.  If object is a live
   261 frame, the return value indicates what sort of terminal device it is
   262 displayed on.  See the documentation of `framep' for possible
   263 return values.  */)
   264   (Lisp_Object object)
   265 {
   266   return ((FRAMEP (object)
   267            && FRAME_LIVE_P (XFRAME (object)))
   268           ? Fframep (object)
   269           : Qnil);
   270 }
   271 
   272 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
   273        doc: /* The name of the window system that FRAME is displaying through.
   274 The value is a symbol:
   275  nil for a termcap frame (a character-only terminal),
   276  `x' for an Emacs frame that is really an X window,
   277  `w32' for an Emacs frame that is a window on MS-Windows display,
   278  `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
   279  `pc' for a direct-write MS-DOS frame.
   280  `pgtk' for an Emacs frame using pure GTK facilities.
   281  `haiku' for an Emacs frame running in Haiku.
   282 
   283 FRAME defaults to the currently selected frame.
   284 
   285 Use of this function as a predicate is deprecated.  Instead,
   286 use `display-graphic-p' or any of the other `display-*-p'
   287 predicates which report frame's specific UI-related capabilities.  */)
   288   (Lisp_Object frame)
   289 {
   290   Lisp_Object type;
   291   if (NILP (frame))
   292     frame = selected_frame;
   293 
   294   type = Fframep (frame);
   295 
   296   if (NILP (type))
   297     wrong_type_argument (Qframep, frame);
   298 
   299   if (EQ (type, Qt))
   300     return Qnil;
   301   else
   302     return type;
   303 }
   304 
   305 /* Placeholder used by temacs -nw before window.el is loaded.  */
   306 DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
   307        Sframe_windows_min_size, 4, 4, 0,
   308        doc: /* SKIP: real doc in window.el.  */
   309        attributes: const)
   310      (Lisp_Object frame, Lisp_Object horizontal,
   311       Lisp_Object ignore, Lisp_Object pixelwise)
   312 {
   313   return make_fixnum (0);
   314 }
   315 
   316 /**
   317  * frame_windows_min_size:
   318  *
   319  * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
   320  * of FRAME.  If PIXELWISE is non-nil, return the minimum inner height
   321  * (width) of FRAME in pixels.
   322  *
   323  * This value is calculated by the function `frame-windows-min-size' in
   324  * window.el unless the `min-height' (`min-width' if HORIZONTAL is
   325  * non-nil) parameter of FRAME is non-nil thus explicitly specifying the
   326  * value to be returned.  In that latter case IGNORE is ignored.
   327  *
   328  * If `frame-windows-min-size' is called, it will make sure that the
   329  * return value accommodates all windows of FRAME respecting the values
   330  * of `window-min-height' (`window-min-width' if HORIZONTAL is
   331  * non-nil) and `window-safe-min-height' (`window-safe-min-width')
   332  * according to IGNORE (see `window-min-size').
   333  *
   334  * In either case, never return a value less than 1.  For TTY frames,
   335  * additionally limit the minimum frame height to a value large enough
   336  * to support menu bar, tab bar, mode line and echo area.
   337  */
   338 static int
   339 frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
   340                         Lisp_Object ignore, Lisp_Object pixelwise)
   341 {
   342   struct frame *f = XFRAME (frame);
   343   Lisp_Object par_size;
   344   int retval;
   345 
   346   if ((!NILP (horizontal)
   347        && RANGED_FIXNUMP (INT_MIN,
   348                           par_size = get_frame_param (f, Qmin_width),
   349                           INT_MAX))
   350       || (NILP (horizontal)
   351           && RANGED_FIXNUMP (INT_MIN,
   352                              par_size = get_frame_param (f, Qmin_height),
   353                              INT_MAX)))
   354     {
   355       int min_size = XFIXNUM (par_size);
   356 
   357       /* Don't allow phantom frames.  */
   358       if (min_size < 1)
   359         min_size = 1;
   360 
   361       retval = (NILP (pixelwise)
   362                 ? min_size
   363                 : min_size * (NILP (horizontal)
   364                               ? FRAME_LINE_HEIGHT (f)
   365                               : FRAME_COLUMN_WIDTH (f)));
   366     }
   367   else
   368     retval = XFIXNUM (call4 (Qframe_windows_min_size, frame, horizontal,
   369                           ignore, pixelwise));
   370 
   371   /* Don't allow too small height of text-mode frames, or else cm.c
   372      might abort in cmcheckmagic.  */
   373   if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
   374     {
   375       int min_height = (FRAME_MENU_BAR_LINES (f)
   376                         + FRAME_TAB_BAR_LINES (f)
   377                         + FRAME_WANTS_MODELINE_P (f)
   378                         + 2);   /* one text line and one echo-area line */
   379 
   380       if (retval < min_height)
   381         retval = min_height;
   382     }
   383 
   384   return retval;
   385 }
   386 
   387 
   388 #ifdef HAVE_WINDOW_SYSTEM
   389 /**
   390  * keep_ratio:
   391  *
   392  * Preserve ratios of frame F which usually happens after its parent
   393  * frame P got resized.  OLD_WIDTH, OLD_HEIGHT specifies the old native
   394  * size of F's parent, NEW_WIDTH and NEW_HEIGHT its new size.
   395  *
   396  * Adjust F's width if F's 'keep_ratio' parameter is non-nil and, if
   397  * it is a cons, its car is not 'height-only'.  Adjust F's height if F's
   398  * 'keep_ratio' parameter is non-nil and, if it is a cons, its car
   399  * is not 'width-only'.
   400  *
   401  * Adjust F's left position if F's 'keep_ratio' parameter is non-nil
   402  * and, if its is a cons, its cdr is non-nil and not 'top-only'.  Adjust
   403  * F's top position if F's 'keep_ratio' parameter is non-nil and, if
   404  * its is a cons, its cdr is non-nil and not 'left-only'.
   405  *
   406  * Note that when positional adjustment is requested but the size of F
   407  * should remain unaltered in the corresponding direction, this routine
   408  * tries to constrain F to its parent frame - something which usually
   409  * happens when the parent frame shrinks.  This means, however, that
   410  * when the parent frame is re-enlarged later, the child's original
   411  * position will not get restored to its pre-shrinking value.
   412  *
   413  * This routine is currently useful for child frames only.  It might be
   414  * eventually useful when moving non-child frames between monitors with
   415  * different resolutions.
   416  */
   417 static void
   418 keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
   419             int new_width, int new_height)
   420 {
   421   Lisp_Object keep_ratio = get_frame_param (f, Qkeep_ratio);
   422 
   423 
   424   if (!NILP (keep_ratio))
   425     {
   426       double width_factor = (double)new_width / (double)old_width;
   427       double height_factor = (double)new_height / (double)old_height;
   428       int pixel_width, pixel_height, pos_x, pos_y;
   429 
   430       if (!CONSP (keep_ratio) || !NILP (Fcdr (keep_ratio)))
   431         {
   432           if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qtop_only))
   433             pos_x = f->left_pos;
   434           else
   435             {
   436               pos_x = (int)(f->left_pos * width_factor + 0.5);
   437 
   438               if (CONSP (keep_ratio)
   439                   && (NILP (Fcar (keep_ratio))
   440                       || EQ (Fcar (keep_ratio), Qheight_only))
   441                   && FRAME_PIXEL_WIDTH (p) - FRAME_PIXEL_WIDTH (f) < pos_x)
   442                 {
   443                   int p_f_width
   444                     = FRAME_PIXEL_WIDTH (p) - FRAME_PIXEL_WIDTH (f);
   445 
   446                   if (p_f_width <= 0)
   447                     pos_x = 0;
   448                   else
   449                     pos_x = (int)(p_f_width * width_factor * 0.5 + 0.5);
   450                 }
   451 
   452               f->left_pos = pos_x;
   453             }
   454 
   455           if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qleft_only))
   456             pos_y = f->top_pos;
   457           else
   458             {
   459               pos_y = (int)(f->top_pos * height_factor + 0.5);
   460 
   461               if (CONSP (keep_ratio)
   462                   && (NILP (Fcar (keep_ratio))
   463                       || EQ (Fcar (keep_ratio), Qwidth_only))
   464                   && FRAME_PIXEL_HEIGHT (p) - FRAME_PIXEL_HEIGHT (f) < pos_y)
   465                 /* When positional adjustment was requested and the
   466                    width of F should remain unaltered, try to constrain
   467                    F to its parent.  This means that when the parent
   468                    frame is enlarged later the child's original position
   469                    won't get restored.  */
   470                 {
   471                   int p_f_height
   472                     = FRAME_PIXEL_HEIGHT (p) - FRAME_PIXEL_HEIGHT (f);
   473 
   474                   if (p_f_height <= 0)
   475                     pos_y = 0;
   476                   else
   477                     pos_y = (int)(p_f_height * height_factor * 0.5 + 0.5);
   478                 }
   479 
   480               f->top_pos = pos_y;
   481             }
   482 
   483           if (FRAME_TERMINAL (f)->set_frame_offset_hook)
   484             FRAME_TERMINAL (f)->set_frame_offset_hook (f, pos_x, pos_y, -1);
   485         }
   486 
   487       if (!CONSP (keep_ratio) || !NILP (Fcar (keep_ratio)))
   488         {
   489           if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qheight_only))
   490             pixel_width = -1;
   491           else
   492             pixel_width
   493               = (int)(FRAME_PIXEL_WIDTH (f) * width_factor + 0.5);
   494 
   495           if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qwidth_only))
   496             pixel_height = -1;
   497           else
   498             pixel_height
   499               = (int)(FRAME_PIXEL_HEIGHT (f) * height_factor + 0.5);
   500 
   501           adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixel_width),
   502                              FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixel_height), 1,
   503                              false, Qkeep_ratio);
   504         }
   505     }
   506 }
   507 #endif
   508 
   509 
   510 static void
   511 frame_size_history_adjust (struct frame *f, int inhibit, Lisp_Object parameter,
   512                            int old_text_width, int old_text_height,
   513                            int new_text_width, int new_text_height,
   514                            int old_text_cols, int old_text_lines,
   515                            int new_text_cols, int new_text_lines,
   516                            int old_native_width, int old_native_height,
   517                            int new_native_width, int new_native_height,
   518                            int old_inner_width, int old_inner_height,
   519                            int new_inner_width, int new_inner_height,
   520                            int min_inner_width, int min_inner_height,
   521                            bool inhibit_horizontal, bool inhibit_vertical)
   522 {
   523   Lisp_Object frame;
   524 
   525   XSETFRAME (frame, f);
   526   if (CONSP (frame_size_history)
   527       && FIXNUMP (XCAR (frame_size_history))
   528       && 0 < XFIXNUM (XCAR (frame_size_history)))
   529     frame_size_history =
   530       Fcons (make_fixnum (XFIXNUM (XCAR (frame_size_history)) - 1),
   531              Fcons (Fcons (list4 (frame, make_fixnum (5),
   532                                   make_fixnum (inhibit), parameter),
   533                            list5 (list4i (old_text_width, old_text_height,
   534                                           new_text_width, new_text_height),
   535                                   list4i (old_text_cols, old_text_lines,
   536                                           new_text_cols, new_text_lines),
   537                                   list4i (old_native_width, old_native_height,
   538                                           new_native_width, new_native_height),
   539                                   list4i (old_inner_width, old_inner_height,
   540                                           new_inner_width,  new_inner_height),
   541                                   list4 (make_fixnum (min_inner_width),
   542                                          make_fixnum (min_inner_height),
   543                                          inhibit_horizontal ? Qt : Qnil,
   544                                          inhibit_vertical ? Qt : Qnil))),
   545                     XCDR (frame_size_history)));
   546 }
   547 
   548 
   549 void
   550 frame_size_history_plain (struct frame *f, Lisp_Object parameter)
   551 {
   552   Lisp_Object frame;
   553 
   554   XSETFRAME (frame, f);
   555   if (CONSP (frame_size_history)
   556       && FIXNUMP (XCAR (frame_size_history))
   557       && 0 < XFIXNUM (XCAR (frame_size_history)))
   558     frame_size_history =
   559       Fcons (make_fixnum (XFIXNUM (XCAR (frame_size_history)) - 1),
   560              Fcons (Fcons (list3 (frame, make_fixnum (1), parameter), Qt),
   561                     XCDR (frame_size_history)));
   562 }
   563 
   564 
   565 void
   566 frame_size_history_extra (struct frame *f, Lisp_Object parameter,
   567                           int pixel_width, int pixel_height,
   568                           int extra_width, int extra_height,
   569                           int delayed_width, int delayed_height)
   570 {
   571   Lisp_Object frame;
   572 
   573   XSETFRAME (frame, f);
   574   if (CONSP (frame_size_history)
   575       && FIXNUMP (XCAR (frame_size_history))
   576       && 0 < XFIXNUM (XCAR (frame_size_history)))
   577     frame_size_history =
   578       Fcons (make_fixnum (XFIXNUM (XCAR (frame_size_history)) - 1),
   579              Fcons (Fcons (list3 (frame, make_fixnum (2), parameter),
   580                            list2 (list4i (pixel_width, pixel_height,
   581                                           extra_width, extra_height),
   582                                   list2i (delayed_width, delayed_height))),
   583                     XCDR (frame_size_history)));
   584 }
   585 
   586 
   587 /**
   588  * adjust_frame_size:
   589  *
   590  * Adjust size of frame F.  NEW_TEXT_WIDTH and NEW_TEXT_HEIGHT specify
   591  * the new text size of F in pixels.  When INHIBIT equals 2, 3 or 4, a
   592  * value of -1 means to leave the text size of F unchanged and adjust,
   593  * if necessary and possible, F's native size accordingly.  When INHIBIT
   594  * equals 0, 1 or 5, a negative value means that the frame has been (or
   595  * should be) made pathologically small which usually means that parts
   596  * of the frame's windows may not be entirely visible.
   597  *
   598  * The effect of calling this function can be to either issue a request
   599  * to resize the frame externally (via set_window_size_hook), to resize
   600  * the frame internally (via resize_frame_windows) or to do nothing.
   601  *
   602  * The argument INHIBIT controls whether set_window_size_hook may be
   603  * called and can assume the following values:
   604  *
   605  * 0 means to unconditionally call set_window_size_hook even if sizes
   606  *   apparently do not change.  Fx_create_frame uses this to pass the
   607  *   initial size to the window manager.
   608  *
   609  * 1 means to call set_window_size_hook if the native frame size should
   610  *   change.  Fset_frame_size and friends and width and height parameter
   611  *   changes use this.
   612  *
   613  * 2 means to call set_window_size_hook provided frame_inhibit_resize
   614  *   allows it.  The code updating external menu and tool bars uses this
   615  *   to keep the height of the native frame unaltered when one of these
   616  *   bars is added or removed.  This means that Emacs has to work
   617  *   against the window manager which usually tries to keep the combined
   618  *   height (native frame plus bar) unaltered.
   619  *
   620  * 3 means to call set_window_size_hook if window minimum sizes must be
   621  *   preserved or frame_inhibit_resize allows it.  This is the default
   622  *   for parameters accounted for in a frame's text size like fringes,
   623  *   scroll bars, internal border, tab bar, internal tool and menu bars.
   624  *   It's also used when the frame's default font changes.
   625  *
   626  * 4 means to call set_window_size_hook only if window minimum sizes
   627  *   must be preserved.  The code for setting up window dividers and
   628  *   that responsible for wrapping the (internal) tool bar use this.
   629  *
   630  * 5 means to never call set_window_size_hook.  Usually this means to
   631  *   call resize_frame_windows.  change_frame_size uses this.
   632  *
   633  * PRETEND is as for change_frame_size.  PARAMETER, if non-nil, is the
   634  * symbol of the parameter changed (like `menu-bar-lines', `font', ...).
   635  * This is passed on to frame_inhibit_resize to let the latter decide on
   636  * a case-by-case basis whether set_window_size_hook should be called.
   637  */
   638 void
   639 adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
   640                    int inhibit, bool pretend, Lisp_Object parameter)
   641 {
   642   int unit_width = FRAME_COLUMN_WIDTH (f);
   643   int unit_height = FRAME_LINE_HEIGHT (f);
   644   int old_native_width = FRAME_PIXEL_WIDTH (f);
   645   int old_native_height = FRAME_PIXEL_HEIGHT (f);
   646   int new_native_width, new_native_height;
   647   /* The desired minimum inner width and height of the frame calculated
   648      via 'frame-windows-min-size'.  */
   649   int min_inner_width, min_inner_height;
   650   /* Get the "old" inner width, height and position of F via its root
   651      window and the minibuffer window.  We cannot use FRAME_INNER_WIDTH
   652      and FRAME_INNER_HEIGHT here since the internal border and the top
   653      margin may have been already set to new values.  */
   654   struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
   655   int old_inner_width = WINDOW_PIXEL_WIDTH (r);
   656   int old_inner_height
   657     = (WINDOW_PIXEL_HEIGHT (r)
   658        + ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
   659           ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
   660           : 0));
   661   int new_inner_width, new_inner_height;
   662   int old_text_cols = FRAME_COLS (f);
   663   int old_text_lines = FRAME_LINES (f);
   664   int new_text_cols, new_text_lines;
   665   int old_text_width = FRAME_TEXT_WIDTH (f);
   666   int old_text_height = FRAME_TEXT_HEIGHT (f);
   667   bool inhibit_horizontal, inhibit_vertical;
   668   Lisp_Object frame;
   669 
   670   XSETFRAME (frame, f);
   671 
   672   min_inner_width
   673     = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qsafe : Qnil, Qt);
   674   min_inner_height
   675     = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qsafe : Qnil, Qt);
   676 
   677   if (inhibit >= 2 && inhibit <= 4)
   678     /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
   679        within the limits and either resizing is inhibited or INHIBIT
   680        equals 4.  */
   681     {
   682       if (new_text_width == -1)
   683         new_text_width = FRAME_TEXT_WIDTH (f);
   684       if (new_text_height == -1)
   685         new_text_height = FRAME_TEXT_HEIGHT (f);
   686 
   687       inhibit_horizontal = (FRAME_INNER_WIDTH (f) >= min_inner_width
   688                             && (inhibit == 4
   689                                 || frame_inhibit_resize (f, true, parameter)));
   690       inhibit_vertical = (FRAME_INNER_HEIGHT (f) >= min_inner_height
   691                           && (inhibit == 4
   692                               || frame_inhibit_resize (f, false, parameter)));
   693     }
   694   else
   695     /* Otherwise inhibit if INHIBIT equals 5.  If we wanted to overrule
   696        the WM do that here (could lead to some sort of eternal fight
   697        with the WM).  */
   698     inhibit_horizontal = inhibit_vertical = inhibit == 5;
   699 
   700   new_native_width = ((inhibit_horizontal && inhibit < 5)
   701                       ? old_native_width
   702                       : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
   703                              min_inner_width
   704                              + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
   705   new_inner_width = new_native_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
   706   new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_native_width);
   707   new_text_cols = new_text_width / unit_width;
   708 
   709   new_native_height = ((inhibit_vertical && inhibit < 5)
   710                        ? old_native_height
   711                        : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
   712                               min_inner_height
   713                               + FRAME_TOP_MARGIN_HEIGHT (f)
   714                               + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
   715   new_inner_height = (new_native_height
   716                       - FRAME_TOP_MARGIN_HEIGHT (f)
   717                       - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
   718   new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_native_height);
   719   new_text_lines = new_text_height / unit_height;
   720 
   721   if (FRAME_WINDOW_P (f)
   722       && f->can_set_window_size
   723       /* For inhibit == 1 call the window_size_hook only if a native
   724          size changes.  For inhibit == 0 or inhibit == 2 always call
   725          it.  */
   726       && ((!inhibit_horizontal
   727            && (new_native_width != old_native_width
   728                || inhibit == 0 || inhibit == 2))
   729           || (!inhibit_vertical
   730               && (new_native_height != old_native_height
   731                   || inhibit == 0 || inhibit == 2))))
   732     {
   733       if (inhibit == 2
   734 #ifdef USE_MOTIF
   735           && !EQ (parameter, Qmenu_bar_lines)
   736 #endif
   737           && (f->new_width >= 0 || f->new_height >= 0))
   738         /* For implied resizes with inhibit 2 (external menu and tool
   739            bar) pick up any new sizes the display engine has not
   740            processed yet.  Otherwise, we would request the old sizes
   741            which will make this request appear as a request to set new
   742            sizes and have the WM react accordingly which is not TRT.
   743 
   744            We don't that for the external menu bar on Motif.
   745            Otherwise, switching off the menu bar will shrink the frame
   746            and switching it on will not enlarge it.  */
   747         {
   748           if (f->new_width >= 0)
   749             new_native_width = f->new_width;
   750           if (f->new_height >= 0)
   751             new_native_height = f->new_height;
   752         }
   753 
   754       if (CONSP (frame_size_history))
   755         frame_size_history_adjust (f, inhibit, parameter,
   756                                    old_text_width, old_text_height,
   757                                    new_text_width, new_text_height,
   758                                    old_text_cols, old_text_lines,
   759                                    new_text_cols, new_text_lines,
   760                                    old_native_width, old_native_height,
   761                                    new_native_width, new_native_height,
   762                                    old_inner_width, old_inner_height,
   763                                    new_inner_width, new_inner_height,
   764                                    min_inner_width, min_inner_height,
   765                                    inhibit_horizontal, inhibit_vertical);
   766 
   767       if (inhibit == 0 || inhibit == 1)
   768         {
   769           f->new_width = new_native_width;
   770           f->new_height = new_native_height;
   771           /* Resetting f->new_size_p is controversial: It might cause
   772              do_pending_window_change drop a previous request and we are
   773              in troubles when the window manager does not honor the
   774              request we issue here.  */
   775           f->new_size_p = false;
   776         }
   777 
   778       if (FRAME_TERMINAL (f)->set_window_size_hook)
   779         FRAME_TERMINAL (f)->set_window_size_hook
   780           (f, 0, new_native_width, new_native_height);
   781       f->resized_p = true;
   782 
   783       return;
   784     }
   785 
   786   if (CONSP (frame_size_history))
   787     frame_size_history_adjust (f, inhibit, parameter,
   788                                old_text_width, old_text_height,
   789                                new_text_width, new_text_height,
   790                                old_text_cols, old_text_lines,
   791                                new_text_cols, new_text_lines,
   792                                old_native_width, old_native_height,
   793                                new_native_width, new_native_height,
   794                                old_inner_width, old_inner_height,
   795                                new_inner_width, new_inner_height,
   796                                min_inner_width, min_inner_height,
   797                                inhibit_horizontal, inhibit_vertical);
   798 
   799   if ((XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top
   800        == FRAME_TOP_MARGIN_HEIGHT (f))
   801       && new_text_width == old_text_width
   802       && new_text_height == old_text_height
   803       && new_inner_width == old_inner_width
   804       && new_inner_height == old_inner_height
   805       /* We might be able to drop these but some doubts remain.  */
   806       && new_native_width == old_native_width
   807       && new_native_height == old_native_height
   808       && new_text_cols == old_text_cols
   809       && new_text_lines == old_text_lines)
   810     /* No change.  */
   811     return;
   812 
   813   block_input ();
   814 
   815 #ifdef MSDOS
   816   /* We only can set screen dimensions to certain values supported by
   817      our video hardware.  Try to find the smallest size greater or
   818      equal to the requested dimensions, while accounting for the fact
   819      that the menu-bar lines are not counted in the frame height.  */
   820   int dos_new_text_lines = new_text_lines + FRAME_TOP_MARGIN (f);
   821 
   822   dos_set_window_size (&dos_new_text_lines, &new_text_cols);
   823   new_text_lines = dos_new_text_lines - FRAME_TOP_MARGIN (f);
   824 #endif
   825 
   826   if (new_inner_width != old_inner_width)
   827     {
   828       resize_frame_windows (f, new_inner_width, true);
   829 
   830       /* MSDOS frames cannot PRETEND, as they change frame size by
   831          manipulating video hardware.  */
   832       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
   833         FrameCols (FRAME_TTY (f)) = new_text_cols;
   834 
   835 #if defined (HAVE_WINDOW_SYSTEM)
   836       if (WINDOWP (f->tab_bar_window))
   837         {
   838           XWINDOW (f->tab_bar_window)->pixel_width = new_inner_width;
   839           XWINDOW (f->tab_bar_window)->total_cols
   840             = new_inner_width / unit_width;
   841         }
   842 #endif
   843 
   844 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
   845       if (WINDOWP (f->tool_bar_window))
   846         {
   847           XWINDOW (f->tool_bar_window)->pixel_width = new_inner_width;
   848           XWINDOW (f->tool_bar_window)->total_cols
   849             = new_inner_width / unit_width;
   850         }
   851 #endif
   852     }
   853   else if (new_text_cols != old_text_cols)
   854     call2 (Qwindow__pixel_to_total, frame, Qt);
   855 
   856   if (new_inner_height != old_inner_height
   857       /* When the top margin has changed we have to recalculate the top
   858          edges of all windows.  No such calculation is necessary for the
   859          left edges.  */
   860       || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
   861     {
   862       resize_frame_windows (f, new_inner_height, false);
   863 
   864       /* MSDOS frames cannot PRETEND, as they change frame size by
   865          manipulating video hardware.  */
   866       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
   867         FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f);
   868     }
   869   else if (new_text_lines != old_text_lines)
   870     call2 (Qwindow__pixel_to_total, frame, Qnil);
   871 
   872   /* Assign new sizes.  */
   873   FRAME_COLS (f) = new_text_cols;
   874   FRAME_LINES (f) = new_text_lines;
   875   FRAME_TEXT_WIDTH (f) = new_text_width;
   876   FRAME_TEXT_HEIGHT (f) = new_text_height;
   877   FRAME_PIXEL_WIDTH (f) = new_native_width;
   878   FRAME_PIXEL_HEIGHT (f) = new_native_height;
   879   FRAME_TOTAL_COLS (f) = FRAME_PIXEL_WIDTH (f) / FRAME_COLUMN_WIDTH (f);
   880   FRAME_TOTAL_LINES (f) = FRAME_PIXEL_HEIGHT (f) / FRAME_LINE_HEIGHT (f);
   881 
   882   {
   883     struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
   884     int text_area_x, text_area_y, text_area_width, text_area_height;
   885 
   886     window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
   887                 &text_area_height);
   888     if (w->cursor.x >= text_area_x + text_area_width)
   889       w->cursor.hpos = w->cursor.x = 0;
   890     if (w->cursor.y >= text_area_y + text_area_height)
   891       w->cursor.vpos = w->cursor.y = 0;
   892   }
   893 
   894   adjust_frame_glyphs (f);
   895   calculate_costs (f);
   896   SET_FRAME_GARBAGED (f);
   897   /* We now say here that F was resized instead of using the old
   898      condition below.  Some resizing must have taken place and if it was
   899      only shifting the root window's position (paranoia?).  */
   900   f->resized_p = true;
   901 
   902 /**   /\* A frame was "resized" if its native size changed, even if its X **/
   903 /**      window wasn't resized at all.  *\/ **/
   904 /**   f->resized_p = (new_native_width != old_native_width **/
   905 /**               || new_native_height != old_native_height); **/
   906 
   907   unblock_input ();
   908 
   909 #ifdef HAVE_WINDOW_SYSTEM
   910   {
   911     /* Adjust size of F's child frames.  */
   912     Lisp_Object frames, frame1;
   913 
   914     FOR_EACH_FRAME (frames, frame1)
   915       if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f)
   916         keep_ratio (XFRAME (frame1), f, old_native_width, old_native_height,
   917                     new_native_width, new_native_height);
   918   }
   919 #endif
   920 }
   921 
   922 /* Allocate basically initialized frame.  */
   923 
   924 static struct frame *
   925 allocate_frame (void)
   926 {
   927   return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, tool_bar_items,
   928                                        PVEC_FRAME);
   929 }
   930 
   931 struct frame *
   932 make_frame (bool mini_p)
   933 {
   934   Lisp_Object frame;
   935   struct frame *f;
   936   struct window *rw, *mw UNINIT;
   937   Lisp_Object root_window;
   938   Lisp_Object mini_window;
   939 
   940   f = allocate_frame ();
   941   XSETFRAME (frame, f);
   942 
   943 #ifdef USE_GTK
   944   /* Initialize Lisp data.  Note that allocate_frame initializes all
   945      Lisp data to nil, so do it only for slots which should not be nil.  */
   946   fset_tool_bar_position (f, Qtop);
   947 #endif
   948 
   949   /* Initialize non-Lisp data.  Note that allocate_frame zeroes out all
   950      non-Lisp data, so do it only for slots which should not be zero.
   951      To avoid subtle bugs and for the sake of readability, it's better to
   952      initialize enum members explicitly even if their values are zero.  */
   953   f->wants_modeline = true;
   954   f->redisplay = true;
   955   f->garbaged = true;
   956   f->can_set_window_size = false;
   957   f->after_make_frame = false;
   958   f->inhibit_horizontal_resize = false;
   959   f->inhibit_vertical_resize = false;
   960   f->tab_bar_redisplayed = false;
   961   f->tab_bar_resized = false;
   962   f->tool_bar_redisplayed = false;
   963   f->tool_bar_resized = false;
   964   f->column_width = 1;  /* !FRAME_WINDOW_P value.  */
   965   f->line_height = 1;  /* !FRAME_WINDOW_P value.  */
   966   f->new_width = -1;
   967   f->new_height = -1;
   968 #ifdef HAVE_WINDOW_SYSTEM
   969   f->vertical_scroll_bar_type = vertical_scroll_bar_none;
   970   f->horizontal_scroll_bars = false;
   971   f->want_fullscreen = FULLSCREEN_NONE;
   972   f->undecorated = false;
   973   f->no_special_glyphs = false;
   974 #ifndef HAVE_NTGUI
   975   f->override_redirect = false;
   976 #endif
   977   f->skip_taskbar = false;
   978   f->no_focus_on_map = false;
   979   f->no_accept_focus = false;
   980   f->z_group = z_group_none;
   981   f->tooltip = false;
   982   f->was_invisible = false;
   983   f->child_frame_border_width = -1;
   984   f->last_tab_bar_item = -1;
   985 #ifndef HAVE_EXT_TOOL_BAR
   986   f->last_tool_bar_item = -1;
   987 #endif
   988 #ifdef NS_IMPL_COCOA
   989   f->ns_appearance = ns_appearance_system_default;
   990   f->ns_transparent_titlebar = false;
   991 #endif
   992 #endif
   993   f->select_mini_window_flag = false;
   994   /* This one should never be zero.  */
   995   f->change_stamp = 1;
   996   root_window = make_window ();
   997   rw = XWINDOW (root_window);
   998   if (mini_p)
   999     {
  1000       mini_window = make_window ();
  1001       mw = XWINDOW (mini_window);
  1002       wset_next (rw, mini_window);
  1003       wset_prev (mw, root_window);
  1004       mw->mini = 1;
  1005       wset_frame (mw, frame);
  1006       fset_minibuffer_window (f, mini_window);
  1007       store_frame_param (f, Qminibuffer, Qt);
  1008     }
  1009   else
  1010     {
  1011       mini_window = Qnil;
  1012       wset_next (rw, Qnil);
  1013       fset_minibuffer_window (f, Qnil);
  1014     }
  1015 
  1016   wset_frame (rw, frame);
  1017 
  1018   /* 80/25 is arbitrary, just so that there is "something there."
  1019      Correct size will be set up later with adjust_frame_size.  */
  1020   FRAME_COLS (f) = FRAME_TOTAL_COLS (f) = rw->total_cols = 80;
  1021   FRAME_TEXT_WIDTH (f) = FRAME_PIXEL_WIDTH (f) = rw->pixel_width
  1022     = 80 * FRAME_COLUMN_WIDTH (f);
  1023   FRAME_LINES (f) = FRAME_TOTAL_LINES (f) = 25;
  1024   FRAME_TEXT_HEIGHT (f) = FRAME_PIXEL_HEIGHT (f) = 25 * FRAME_LINE_HEIGHT (f);
  1025 
  1026   rw->total_lines = FRAME_LINES (f) - (mini_p ? 1 : 0);
  1027   rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
  1028 
  1029   fset_face_hash_table
  1030     (f, make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE,
  1031                          DEFAULT_REHASH_THRESHOLD, Qnil, false));
  1032 
  1033   if (mini_p)
  1034     {
  1035       mw->top_line = rw->total_lines;
  1036       mw->pixel_top = rw->pixel_height;
  1037       mw->total_cols = rw->total_cols;
  1038       mw->pixel_width = rw->pixel_width;
  1039       mw->total_lines = 1;
  1040       mw->pixel_height = FRAME_LINE_HEIGHT (f);
  1041     }
  1042 
  1043   /* Choose a buffer for the frame's root window.  */
  1044   {
  1045     Lisp_Object buf = Fcurrent_buffer ();
  1046 
  1047     /* If current buffer is hidden, try to find another one.  */
  1048     if (BUFFER_HIDDEN_P (XBUFFER (buf)))
  1049       buf = other_buffer_safely (buf);
  1050 
  1051     /* Use set_window_buffer, not Fset_window_buffer, and don't let
  1052        hooks be run by it.  The reason is that the whole frame/window
  1053        arrangement is not yet fully initialized at this point.  Windows
  1054        don't have the right size, glyph matrices aren't initialized
  1055        etc.  Running Lisp functions at this point surely ends in a
  1056        SEGV.  */
  1057     set_window_buffer (root_window, buf, 0, 0);
  1058     fset_buffer_list (f, list1 (buf));
  1059   }
  1060 
  1061   if (mini_p)
  1062     set_window_buffer (mini_window,
  1063                        (NILP (Vminibuffer_list)
  1064                         ? get_minibuffer (0)
  1065                         : Fcar (Vminibuffer_list)),
  1066                        0, 0);
  1067 
  1068   fset_root_window (f, root_window);
  1069   fset_selected_window (f, root_window);
  1070   /* Make sure this window seems more recently used than
  1071      a newly-created, never-selected window.  */
  1072   XWINDOW (f->selected_window)->use_time = ++window_select_count;
  1073 
  1074   return f;
  1075 }
  1076 
  1077 #ifdef HAVE_WINDOW_SYSTEM
  1078 /* Make a frame using a separate minibuffer window on another frame.
  1079    MINI_WINDOW is the minibuffer window to use.  nil means use the
  1080    default (the global minibuffer).  */
  1081 
  1082 struct frame *
  1083 make_frame_without_minibuffer (Lisp_Object mini_window, KBOARD *kb,
  1084                                Lisp_Object display)
  1085 {
  1086   struct frame *f;
  1087 
  1088   if (!NILP (mini_window))
  1089     CHECK_LIVE_WINDOW (mini_window);
  1090 
  1091   if (!NILP (mini_window)
  1092       && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
  1093     error ("Frame and minibuffer must be on the same terminal");
  1094 
  1095   /* Make a frame containing just a root window.  */
  1096   f = make_frame (0);
  1097 
  1098   if (NILP (mini_window))
  1099     {
  1100       /* Use default-minibuffer-frame if possible.  */
  1101       if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
  1102           || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
  1103         {
  1104           Lisp_Object frame_dummy;
  1105 
  1106           XSETFRAME (frame_dummy, f);
  1107           /* If there's no minibuffer frame to use, create one.  */
  1108           kset_default_minibuffer_frame
  1109             (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
  1110         }
  1111 
  1112       mini_window
  1113         = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
  1114     }
  1115 
  1116   fset_minibuffer_window (f, mini_window);
  1117   store_frame_param (f, Qminibuffer, mini_window);
  1118 
  1119   /* Make the chosen minibuffer window display the proper minibuffer,
  1120      unless it is already showing a minibuffer.  */
  1121   if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
  1122     /* Use set_window_buffer instead of Fset_window_buffer (see
  1123        discussion of bug#11984, bug#12025, bug#12026).  */
  1124     set_window_buffer (mini_window,
  1125                        (NILP (Vminibuffer_list)
  1126                         ? get_minibuffer (0)
  1127                         : Fcar (Vminibuffer_list)), 0, 0);
  1128   return f;
  1129 }
  1130 
  1131 /* Make a frame containing only a minibuffer window.  */
  1132 
  1133 struct frame *
  1134 make_minibuffer_frame (void)
  1135 {
  1136   /* First make a frame containing just a root window, no minibuffer.  */
  1137 
  1138   register struct frame *f = make_frame (0);
  1139   register Lisp_Object mini_window;
  1140   register Lisp_Object frame;
  1141 
  1142   XSETFRAME (frame, f);
  1143 
  1144   f->auto_raise = 0;
  1145   f->auto_lower = 0;
  1146   f->no_split = 1;
  1147   f->wants_modeline = 0;
  1148 
  1149   /* Now label the root window as also being the minibuffer.
  1150      Avoid infinite looping on the window chain by marking next pointer
  1151      as nil. */
  1152 
  1153   mini_window = f->root_window;
  1154   fset_minibuffer_window (f, mini_window);
  1155   store_frame_param (f, Qminibuffer, Qonly);
  1156   XWINDOW (mini_window)->mini = 1;
  1157   wset_next (XWINDOW (mini_window), Qnil);
  1158   wset_prev (XWINDOW (mini_window), Qnil);
  1159   wset_frame (XWINDOW (mini_window), frame);
  1160 
  1161   /* Put the proper buffer in that window.  */
  1162 
  1163   /* Use set_window_buffer instead of Fset_window_buffer (see
  1164      discussion of bug#11984, bug#12025, bug#12026).  */
  1165   set_window_buffer (mini_window,
  1166                      (NILP (Vminibuffer_list)
  1167                       ? get_minibuffer (0)
  1168                       : Fcar (Vminibuffer_list)), 0, 0);
  1169   return f;
  1170 }
  1171 #endif /* HAVE_WINDOW_SYSTEM */
  1172 
  1173 /* Construct a frame that refers to a terminal.  */
  1174 
  1175 static intmax_t tty_frame_count;
  1176 
  1177 struct frame *
  1178 make_initial_frame (void)
  1179 {
  1180   struct frame *f;
  1181   struct terminal *terminal;
  1182   Lisp_Object frame;
  1183 
  1184   eassert (initial_kboard);
  1185   eassert (NILP (Vframe_list) || CONSP (Vframe_list));
  1186 
  1187   terminal = init_initial_terminal ();
  1188 
  1189   f = make_frame (true);
  1190   XSETFRAME (frame, f);
  1191 
  1192   Vframe_list = Fcons (frame, Vframe_list);
  1193 
  1194   tty_frame_count = 1;
  1195   fset_name (f, build_pure_c_string ("F1"));
  1196 
  1197   SET_FRAME_VISIBLE (f, 1);
  1198 
  1199   f->output_method = terminal->type;
  1200   f->terminal = terminal;
  1201   f->terminal->reference_count++;
  1202 
  1203   FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
  1204   FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
  1205 
  1206 #ifdef HAVE_WINDOW_SYSTEM
  1207   f->vertical_scroll_bar_type = vertical_scroll_bar_none;
  1208   f->horizontal_scroll_bars = false;
  1209 #endif
  1210 
  1211   /* The default value of menu-bar-mode is t.  */
  1212   set_menu_bar_lines (f, make_fixnum (1), Qnil);
  1213 
  1214   /* The default value of tab-bar-mode is nil.  */
  1215   set_tab_bar_lines (f, make_fixnum (0), Qnil);
  1216 
  1217   /* Allocate glyph matrices.  */
  1218   adjust_frame_glyphs (f);
  1219 
  1220   if (!noninteractive)
  1221     init_frame_faces (f);
  1222 
  1223   last_nonminibuf_frame = f;
  1224 
  1225   f->can_set_window_size = true;
  1226   f->after_make_frame = true;
  1227 
  1228   return f;
  1229 }
  1230 
  1231 
  1232 static struct frame *
  1233 make_terminal_frame (struct terminal *terminal)
  1234 {
  1235   register struct frame *f;
  1236   Lisp_Object frame;
  1237   char name[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)];
  1238 
  1239   if (!terminal->name)
  1240     error ("Terminal is not live, can't create new frames on it");
  1241 
  1242   f = make_frame (1);
  1243 
  1244   XSETFRAME (frame, f);
  1245   Vframe_list = Fcons (frame, Vframe_list);
  1246 
  1247   fset_name (f, make_formatted_string (name, "F%"PRIdMAX, ++tty_frame_count));
  1248 
  1249   SET_FRAME_VISIBLE (f, 1);
  1250 
  1251   f->terminal = terminal;
  1252   f->terminal->reference_count++;
  1253 #ifdef MSDOS
  1254   f->output_data.tty = &the_only_tty_output;
  1255   f->output_data.tty->display_info = &the_only_display_info;
  1256   if (!inhibit_window_system
  1257       && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
  1258           || XFRAME (selected_frame)->output_method == output_msdos_raw))
  1259     f->output_method = output_msdos_raw;
  1260   else
  1261     f->output_method = output_termcap;
  1262 #else /* not MSDOS */
  1263   f->output_method = output_termcap;
  1264   create_tty_output (f);
  1265   FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
  1266   FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
  1267 #endif /* not MSDOS */
  1268 
  1269 #ifdef HAVE_WINDOW_SYSTEM
  1270   f->vertical_scroll_bar_type = vertical_scroll_bar_none;
  1271   f->horizontal_scroll_bars = false;
  1272 #endif
  1273 
  1274   FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
  1275   FRAME_TAB_BAR_LINES (f) = NILP (Vtab_bar_mode) ? 0 : 1;
  1276   FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f)
  1277     - FRAME_TAB_BAR_LINES (f);
  1278   FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
  1279   FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
  1280   FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f)
  1281     - FRAME_TAB_BAR_HEIGHT (f);
  1282 
  1283   /* Set the top frame to the newly created frame.  */
  1284   if (FRAMEP (FRAME_TTY (f)->top_frame)
  1285       && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
  1286     SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
  1287 
  1288   FRAME_TTY (f)->top_frame = frame;
  1289 
  1290   if (!noninteractive)
  1291     init_frame_faces (f);
  1292 
  1293   return f;
  1294 }
  1295 
  1296 /* Get a suitable value for frame parameter PARAMETER for a newly
  1297    created frame, based on (1) the user-supplied frame parameter
  1298    alist SUPPLIED_PARMS, and (2) CURRENT_VALUE.  */
  1299 
  1300 static Lisp_Object
  1301 get_future_frame_param (Lisp_Object parameter,
  1302                         Lisp_Object supplied_parms,
  1303                         char *current_value)
  1304 {
  1305   Lisp_Object result;
  1306 
  1307   result = Fassq (parameter, supplied_parms);
  1308   if (NILP (result))
  1309     result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
  1310   if (NILP (result) && current_value != NULL)
  1311     result = build_string (current_value);
  1312   if (!NILP (result) && !STRINGP (result))
  1313     result = XCDR (result);
  1314   if (NILP (result) || !STRINGP (result))
  1315     result = Qnil;
  1316 
  1317   return result;
  1318 }
  1319 
  1320 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
  1321        1, 1, 0,
  1322        doc: /* Create an additional terminal frame, possibly on another terminal.
  1323 This function takes one argument, an alist specifying frame parameters.
  1324 
  1325 You can create multiple frames on a single text terminal, but only one
  1326 of them (the selected terminal frame) is actually displayed.
  1327 
  1328 In practice, generally you don't need to specify any parameters,
  1329 except when you want to create a new frame on another terminal.
  1330 In that case, the `tty' parameter specifies the device file to open,
  1331 and the `tty-type' parameter specifies the terminal type.  Example:
  1332 
  1333    (make-terminal-frame \\='((tty . "/dev/pts/5") (tty-type . "xterm")))
  1334 
  1335 Note that changing the size of one terminal frame automatically
  1336 affects all frames on the same terminal device.  */)
  1337   (Lisp_Object parms)
  1338 {
  1339   struct frame *f;
  1340   struct terminal *t = NULL;
  1341   Lisp_Object frame;
  1342   struct frame *sf = SELECTED_FRAME ();
  1343 
  1344 #ifdef MSDOS
  1345   if (sf->output_method != output_msdos_raw
  1346       && sf->output_method != output_termcap)
  1347     emacs_abort ();
  1348 #else /* not MSDOS */
  1349 
  1350 #ifdef WINDOWSNT                           /* This should work now! */
  1351   if (sf->output_method != output_termcap)
  1352     error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
  1353 #endif
  1354 #endif /* not MSDOS */
  1355 
  1356   {
  1357     Lisp_Object terminal;
  1358 
  1359     terminal = Fassq (Qterminal, parms);
  1360     if (CONSP (terminal))
  1361       {
  1362         terminal = XCDR (terminal);
  1363         t = decode_live_terminal (terminal);
  1364       }
  1365 #ifdef MSDOS
  1366     if (t && t != the_only_display_info.terminal)
  1367       /* msdos.c assumes a single tty_display_info object.  */
  1368       error ("Multiple terminals are not supported on this platform");
  1369     if (!t)
  1370       t = the_only_display_info.terminal;
  1371 #endif
  1372   }
  1373 
  1374   if (!t)
  1375     {
  1376       char *name = 0, *type = 0;
  1377       Lisp_Object tty, tty_type;
  1378       USE_SAFE_ALLOCA;
  1379 
  1380       tty = get_future_frame_param
  1381         (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
  1382                        ? FRAME_TTY (XFRAME (selected_frame))->name
  1383                        : NULL));
  1384       if (!NILP (tty))
  1385         SAFE_ALLOCA_STRING (name, tty);
  1386 
  1387       tty_type = get_future_frame_param
  1388         (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
  1389                             ? FRAME_TTY (XFRAME (selected_frame))->type
  1390                             : NULL));
  1391       if (!NILP (tty_type))
  1392         SAFE_ALLOCA_STRING (type, tty_type);
  1393 
  1394       t = init_tty (name, type, 0); /* Errors are not fatal.  */
  1395       SAFE_FREE ();
  1396     }
  1397 
  1398   f = make_terminal_frame (t);
  1399 
  1400   {
  1401     int width, height;
  1402     get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
  1403     /* With INHIBIT 5 pass correct text height to adjust_frame_size.  */
  1404     adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f),
  1405                        5, 0, Qterminal_frame);
  1406   }
  1407 
  1408   adjust_frame_glyphs (f);
  1409   calculate_costs (f);
  1410   XSETFRAME (frame, f);
  1411 
  1412   store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
  1413   store_in_alist (&parms, Qtty,
  1414                   (t->display_info.tty->name
  1415                    ? build_string (t->display_info.tty->name)
  1416                    : Qnil));
  1417 
  1418   /* Make the frame face hash be frame-specific, so that each
  1419      frame could change its face definitions independently.  */
  1420   fset_face_hash_table (f, Fcopy_hash_table (sf->face_hash_table));
  1421   /* Simple copy_hash_table isn't enough, because we need the contents of
  1422      the vectors which are the values in face_hash_table to
  1423      be copied as well.  */
  1424   ptrdiff_t idx = 0;
  1425   struct Lisp_Hash_Table *table = XHASH_TABLE (f->face_hash_table);
  1426   for (idx = 0; idx < table->count; ++idx)
  1427     set_hash_value_slot (table, idx, Fcopy_sequence (HASH_VALUE (table, idx)));
  1428 
  1429   /* On terminal frames the `minibuffer' frame parameter is always
  1430      virtually t.  Avoid that a different value in parms causes
  1431      complaints, see Bug#24758.  */
  1432   store_in_alist (&parms, Qminibuffer, Qt);
  1433   Fmodify_frame_parameters (frame, parms);
  1434 
  1435   f->can_set_window_size = true;
  1436   f->after_make_frame = true;
  1437 
  1438   return frame;
  1439 }
  1440 
  1441 
  1442 /* Perform the switch to frame FRAME.
  1443 
  1444    If FRAME is a switch-frame event `(switch-frame FRAME1)', use
  1445    FRAME1 as frame.
  1446 
  1447    If TRACK is non-zero and the frame that currently has the focus
  1448    redirects its focus to the selected frame, redirect that focused
  1449    frame's focus to FRAME instead.
  1450 
  1451    FOR_DELETION non-zero means that the selected frame is being
  1452    deleted, which includes the possibility that the frame's terminal
  1453    is dead.
  1454 
  1455    The value of NORECORD is passed as argument to Fselect_window.  */
  1456 
  1457 Lisp_Object
  1458 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
  1459 {
  1460   struct frame *sf = SELECTED_FRAME (), *f;
  1461 
  1462   /* If FRAME is a switch-frame event, extract the frame we should
  1463      switch to.  */
  1464   if (CONSP (frame)
  1465       && EQ (XCAR (frame), Qswitch_frame)
  1466       && CONSP (XCDR (frame)))
  1467     frame = XCAR (XCDR (frame));
  1468 
  1469   /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
  1470      a switch-frame event to arrive after a frame is no longer live,
  1471      especially when deleting the initial frame during startup.  */
  1472   CHECK_FRAME (frame);
  1473   f = XFRAME (frame);
  1474   /* Silently ignore dead and tooltip frames (Bug#47207).  */
  1475   if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f))
  1476     return Qnil;
  1477   else if (f == sf)
  1478     return frame;
  1479 
  1480   /* If the frame with GUI focus has had it's Emacs focus redirected
  1481      toward the currently selected frame, we should change the
  1482      redirection to point to the newly selected frame.  This means
  1483      that if the focus is redirected from a minibufferless frame to a
  1484      surrogate minibuffer frame, we can use `other-window' to switch
  1485      between all the frames using that minibuffer frame, and the focus
  1486      redirection will follow us around.  This code is necessary when
  1487      we have a minibufferless frame using the MB in another (normal)
  1488      frame (bug#64152) (ACM, 2023-06-20).  */
  1489 #ifdef HAVE_WINDOW_SYSTEM
  1490   if (track && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame)
  1491     {
  1492       Lisp_Object gfocus; /* The frame which still has focus on the
  1493                              current terminal, according to the GUI
  1494                              system. */
  1495       Lisp_Object focus;  /* The frame to which Emacs has redirected
  1496                              the focus from `gfocus'.  This might be a
  1497                              frame with a minibuffer when `gfocus'
  1498                              doesn't have a MB.  */
  1499 
  1500       gfocus = FRAME_TERMINAL (f)->get_focus_frame (f);
  1501       if (FRAMEP (gfocus))
  1502         {
  1503           focus = FRAME_FOCUS_FRAME (XFRAME (gfocus));
  1504           if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
  1505               /* Redirect frame focus also when FRAME has its minibuffer
  1506                  window on the selected frame (see Bug#24500).
  1507 
  1508                  Don't do that: It causes redirection problem with a
  1509                  separate minibuffer frame (Bug#24803) and problems
  1510                  when updating the cursor on such frames.
  1511               || (NILP (focus)
  1512                   && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))  */
  1513             Fredirect_frame_focus (gfocus, frame);
  1514         }
  1515     }
  1516 #endif /* HAVE_X_WINDOWS */
  1517 
  1518   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
  1519     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
  1520 
  1521   if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
  1522     {
  1523       struct tty_display_info *tty = FRAME_TTY (f);
  1524       Lisp_Object top_frame = tty->top_frame;
  1525 
  1526       /* Don't mark the frame garbaged and/or obscured if we are
  1527          switching to the frame that is already the top frame of that
  1528          TTY.  */
  1529       if (!EQ (frame, top_frame))
  1530         {
  1531           if (FRAMEP (top_frame))
  1532             /* Mark previously displayed frame as now obscured.  */
  1533             SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
  1534           SET_FRAME_VISIBLE (f, 1);
  1535           /* If the new TTY frame changed dimensions, we need to
  1536              resync term.c's idea of the frame size with the new
  1537              frame's data.  */
  1538           if (FRAME_COLS (f) != FrameCols (tty))
  1539             FrameCols (tty) = FRAME_COLS (f);
  1540           if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
  1541             FrameRows (tty) = FRAME_TOTAL_LINES (f);
  1542         }
  1543       tty->top_frame = frame;
  1544     }
  1545 
  1546   sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window));
  1547 
  1548   move_minibuffers_onto_frame (sf, frame, for_deletion);
  1549 
  1550   /* If the selected window in the target frame is its mini-window, we move
  1551      to a different window, the most recently used one, unless there is a
  1552      valid active minibuffer in the mini-window.  */
  1553   if (EQ (f->selected_window, f->minibuffer_window)
  1554       /* The following test might fail if the mini-window contains a
  1555          non-active minibuffer.  */
  1556       && NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt)))
  1557     {
  1558       Lisp_Object w = call1 (Qget_mru_window, frame);
  1559       if (WINDOW_LIVE_P (w)) /* W can be nil in minibuffer-only frames.  */
  1560         Fset_frame_selected_window (frame, w, Qnil);
  1561     }
  1562 
  1563   /* After setting `selected_frame`, we're temporarily in an inconsistent
  1564      state where (selected-window) != (frame-selected-window).  Until this
  1565      invariant is restored we should be very careful not to run ELisp code.
  1566      (bug#58343)  */
  1567   selected_frame = frame;
  1568 
  1569   if (f->select_mini_window_flag
  1570       && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt)))
  1571     f->selected_window = f->minibuffer_window;
  1572   f->select_mini_window_flag = false;
  1573 
  1574   if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
  1575     last_nonminibuf_frame = XFRAME (selected_frame);
  1576 
  1577   Fselect_window (f->selected_window, norecord);
  1578 
  1579   /* We want to make sure that the next event generates a frame-switch
  1580      event to the appropriate frame.  This seems kludgy to me, but
  1581      before you take it out, make sure that evaluating something like
  1582      (select-window (frame-root-window (make-frame))) doesn't end up
  1583      with your typing being interpreted in the new frame instead of
  1584      the one you're actually typing in.  */
  1585 #ifdef HAVE_WINDOW_SYSTEM
  1586   if (!frame_ancestor_p (f, sf))
  1587 #endif
  1588     internal_last_event_frame = Qnil;
  1589 
  1590   return frame;
  1591 }
  1592 
  1593 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
  1594        doc: /* Select FRAME.
  1595 Subsequent editing commands apply to its selected window.
  1596 Optional argument NORECORD means to neither change the order of
  1597 recently selected windows nor the buffer list.
  1598 
  1599 The selection of FRAME lasts until the next time the user does
  1600 something to select a different frame, or until the next time
  1601 this function is called.  If you are using a window system, the
  1602 previously selected frame may be restored as the selected frame
  1603 when returning to the command loop, because it still may have
  1604 the window system's input focus.  On a text terminal, the next
  1605 redisplay will display FRAME.
  1606 
  1607 This function returns FRAME, or nil if FRAME has been deleted.  */)
  1608   (Lisp_Object frame, Lisp_Object norecord)
  1609 {
  1610   struct frame *f;
  1611 
  1612   CHECK_LIVE_FRAME (frame);
  1613   f = XFRAME (frame);
  1614 
  1615   if (FRAME_TOOLTIP_P (f))
  1616     /* Do not select a tooltip frame (Bug#47207).  */
  1617     error ("Cannot select a tooltip frame");
  1618   else
  1619     return do_switch_frame (frame, 1, 0, norecord);
  1620 }
  1621 
  1622 DEFUN ("handle-switch-frame", Fhandle_switch_frame,
  1623        Shandle_switch_frame, 1, 1, "^e",
  1624        doc: /* Handle a switch-frame event EVENT.
  1625 Switch-frame events are usually bound to this function.
  1626 A switch-frame event is an event Emacs sends itself to
  1627 indicate that input is arriving in a new frame. It does not
  1628 necessarily represent user-visible input focus.  */)
  1629   (Lisp_Object event)
  1630 {
  1631   /* Preserve prefix arg that the command loop just cleared.  */
  1632   kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
  1633   run_hook (Qmouse_leave_buffer_hook);
  1634 
  1635   return do_switch_frame (event, 0, 0, Qnil);
  1636 }
  1637 
  1638 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
  1639        doc: /* Return the frame that is now selected.  */)
  1640   (void)
  1641 {
  1642   return selected_frame;
  1643 }
  1644 
  1645 DEFUN ("old-selected-frame", Fold_selected_frame,
  1646        Sold_selected_frame, 0, 0, 0,
  1647        doc: /* Return the old selected FRAME.
  1648 FRAME must be a live frame and defaults to the selected one.
  1649 
  1650 The return value is the frame selected the last time window change
  1651 functions were run.  */)
  1652   (void)
  1653 {
  1654   return old_selected_frame;
  1655 }
  1656 
  1657 DEFUN ("frame-list", Fframe_list, Sframe_list,
  1658        0, 0, 0,
  1659        doc: /* Return a list of all live frames.
  1660 The return value does not include any tooltip frame.  */)
  1661   (void)
  1662 {
  1663 #ifdef HAVE_WINDOW_SYSTEM
  1664   Lisp_Object list = Qnil, tail, frame;
  1665 
  1666   FOR_EACH_FRAME (tail, frame)
  1667     if (!FRAME_TOOLTIP_P (XFRAME (frame)))
  1668       list = Fcons (frame, list);
  1669   /* Reverse list for consistency with the !HAVE_WINDOW_SYSTEM case.  */
  1670   return Fnreverse (list);
  1671 #else /* !HAVE_WINDOW_SYSTEM */
  1672   return Fcopy_sequence (Vframe_list);
  1673 #endif /* HAVE_WINDOW_SYSTEM */
  1674 }
  1675 
  1676 DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
  1677        0, 1, 0,
  1678        doc: /* Return the parent frame of FRAME.
  1679 The parent frame of FRAME is the Emacs frame whose window-system window
  1680 is the parent window of FRAME's window-system window.  When such a frame
  1681 exists, FRAME is considered a child frame of that frame.
  1682 
  1683 Return nil if FRAME has no parent frame.  This means that FRAME's
  1684 window-system window is either a "top-level" window (a window whose
  1685 parent window is the window-system's root window) or an embedded window
  1686 \(a window whose parent window is owned by some other application).  */)
  1687      (Lisp_Object frame)
  1688 {
  1689   struct frame *f = decode_live_frame (frame);
  1690   struct frame *p = FRAME_PARENT_FRAME (f);
  1691   Lisp_Object parent;
  1692 
  1693   /* Can't return f->parent_frame directly since it might not be defined
  1694      for this platform.  */
  1695   if (p)
  1696     {
  1697       XSETFRAME (parent, p);
  1698 
  1699       return parent;
  1700     }
  1701   else
  1702     return Qnil;
  1703 }
  1704 
  1705 #ifdef HAVE_WINDOW_SYSTEM
  1706 bool
  1707 frame_ancestor_p (struct frame *af, struct frame *df)
  1708 {
  1709   struct frame *pf = FRAME_PARENT_FRAME (df);
  1710 
  1711   while (pf)
  1712     {
  1713       if (pf == af)
  1714         return true;
  1715       else
  1716         pf = FRAME_PARENT_FRAME (pf);
  1717     }
  1718 
  1719   return false;
  1720 }
  1721 #endif
  1722 
  1723 DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
  1724        2, 2, 0,
  1725        doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
  1726 ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
  1727 parent frame or it is an ancestor of DESCENDANT's parent frame.  Both,
  1728 ANCESTOR and DESCENDANT must be live frames and default to the selected
  1729 frame.  */)
  1730      (Lisp_Object ancestor, Lisp_Object descendant)
  1731 {
  1732 #ifdef HAVE_WINDOW_SYSTEM
  1733   struct frame *af = decode_live_frame (ancestor);
  1734   struct frame *df = decode_live_frame (descendant);
  1735 
  1736   return frame_ancestor_p (af, df) ? Qt : Qnil;
  1737 #else
  1738   return Qnil;
  1739 #endif
  1740   }
  1741 
  1742 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
  1743    same tty (for tty frames) or among frames which uses FRAME's keyboard.
  1744    If MINIBUF is nil, do not consider minibuffer-only candidate.
  1745    If MINIBUF is `visible', do not consider an invisible candidate.
  1746    If MINIBUF is a window, consider only its own frame and candidate now
  1747    using that window as the minibuffer.
  1748    If MINIBUF is 0, consider candidate if it is visible or iconified.
  1749    Otherwise consider any candidate and return nil if CANDIDATE is not
  1750    acceptable.  */
  1751 
  1752 static Lisp_Object
  1753 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
  1754 {
  1755   struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
  1756 
  1757   if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
  1758        && FRAME_KBOARD (c) == FRAME_KBOARD (f))
  1759       || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
  1760           && FRAME_TTY (c) == FRAME_TTY (f)))
  1761     {
  1762       if (!NILP (get_frame_param (c, Qno_other_frame)))
  1763         return Qnil;
  1764       else if (NILP (minibuf))
  1765         {
  1766           if (!FRAME_MINIBUF_ONLY_P (c))
  1767             return candidate;
  1768         }
  1769       else if (EQ (minibuf, Qvisible))
  1770         {
  1771           if (FRAME_VISIBLE_P (c))
  1772             return candidate;
  1773         }
  1774       else if (WINDOWP (minibuf))
  1775         {
  1776           if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
  1777               || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
  1778               || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
  1779                      FRAME_FOCUS_FRAME (c)))
  1780             return candidate;
  1781         }
  1782       else if (FIXNUMP (minibuf) && XFIXNUM (minibuf) == 0)
  1783         {
  1784           if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
  1785             return candidate;
  1786         }
  1787       else
  1788         return candidate;
  1789     }
  1790   return Qnil;
  1791 }
  1792 
  1793 /* Return the next frame in the frame list after FRAME.  */
  1794 
  1795 static Lisp_Object
  1796 next_frame (Lisp_Object frame, Lisp_Object minibuf)
  1797 {
  1798   Lisp_Object f, tail;
  1799   int passed = 0;
  1800 
  1801   eassume (CONSP (Vframe_list));
  1802 
  1803   while (passed < 2)
  1804     FOR_EACH_FRAME (tail, f)
  1805       {
  1806         if (passed)
  1807           {
  1808             f = candidate_frame (f, frame, minibuf);
  1809             if (!NILP (f))
  1810               return f;
  1811           }
  1812         if (EQ (frame, f))
  1813           passed++;
  1814       }
  1815   return frame;
  1816 }
  1817 
  1818 /* Return the previous frame in the frame list before FRAME.  */
  1819 
  1820 static Lisp_Object
  1821 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
  1822 {
  1823   Lisp_Object f, tail, prev = Qnil;
  1824 
  1825   eassume (CONSP (Vframe_list));
  1826 
  1827   FOR_EACH_FRAME (tail, f)
  1828     {
  1829       if (EQ (frame, f) && !NILP (prev))
  1830         return prev;
  1831       f = candidate_frame (f, frame, minibuf);
  1832       if (!NILP (f))
  1833         prev = f;
  1834     }
  1835 
  1836   /* We've scanned the entire list.  */
  1837   if (NILP (prev))
  1838     /* We went through the whole frame list without finding a single
  1839        acceptable frame.  Return the original frame.  */
  1840     return frame;
  1841   else
  1842     /* There were no acceptable frames in the list before FRAME; otherwise,
  1843        we would have returned directly from the loop.  Since PREV is the last
  1844        acceptable frame in the list, return it.  */
  1845     return prev;
  1846 }
  1847 
  1848 
  1849 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
  1850        doc: /* Return the next frame in the frame list after FRAME.
  1851 Only frames on the same terminal as FRAME are included in the list
  1852 of candidate frames.  If omitted, FRAME defaults to the selected frame.
  1853 
  1854 If MINIFRAME is nil (the default), include all frames except
  1855 minibuffer-only frames.
  1856 
  1857 If MINIFRAME is a window, include only its own frame and any frame now
  1858 using that window as the minibuffer.
  1859 
  1860 If MINIFRAME is `visible', include only visible frames.
  1861 
  1862 If MINIFRAME is 0, include only visible and iconified frames.
  1863 
  1864 If MINIFRAME is any other value, include all frames.  */)
  1865   (Lisp_Object frame, Lisp_Object miniframe)
  1866 {
  1867   if (NILP (frame))
  1868     frame = selected_frame;
  1869   CHECK_LIVE_FRAME (frame);
  1870   return next_frame (frame, miniframe);
  1871 }
  1872 
  1873 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
  1874        doc: /* Return the previous frame in the frame list before FRAME.
  1875 It considers only frames on the same terminal as FRAME.
  1876 By default, skip minibuffer-only frames.
  1877 If omitted, FRAME defaults to the selected frame.
  1878 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
  1879 If MINIFRAME is a window, include only its own frame
  1880 and any frame now using that window as the minibuffer.
  1881 If MINIFRAME is `visible', include all visible frames.
  1882 If MINIFRAME is 0, include all visible and iconified frames.
  1883 Otherwise, include all frames.  */)
  1884   (Lisp_Object frame, Lisp_Object miniframe)
  1885 {
  1886   if (NILP (frame))
  1887     frame = selected_frame;
  1888   CHECK_LIVE_FRAME (frame);
  1889   return prev_frame (frame, miniframe);
  1890 }
  1891 
  1892 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
  1893        Slast_nonminibuf_frame, 0, 0, 0,
  1894        doc: /* Return last non-minibuffer frame selected. */)
  1895   (void)
  1896 {
  1897   Lisp_Object frame = Qnil;
  1898 
  1899   if (last_nonminibuf_frame)
  1900     XSETFRAME (frame, last_nonminibuf_frame);
  1901 
  1902   return frame;
  1903 }
  1904 
  1905 /**
  1906  * other_frames:
  1907  *
  1908  * Return true if there exists at least one visible or iconified frame
  1909  * but F.  Tooltip frames do not qualify as candidates.  Return false
  1910  * if no such frame exists.
  1911  *
  1912  * INVISIBLE true means we are called from make_frame_invisible where
  1913  * such a frame must be visible or iconified.  INVISIBLE nil means we
  1914  * are called from delete_frame.  In that case FORCE true means that the
  1915  * visibility status of such a frame can be ignored.
  1916  *
  1917  * If F is the terminal frame and we are using X, return true if at
  1918  * least one X frame exists.
  1919  */
  1920 static bool
  1921 other_frames (struct frame *f, bool invisible, bool force)
  1922 {
  1923   Lisp_Object frames, frame, frame1;
  1924   Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
  1925 
  1926   XSETFRAME (frame, f);
  1927   if (WINDOWP (minibuffer_window)
  1928       && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
  1929     minibuffer_window = Qnil;
  1930 
  1931   FOR_EACH_FRAME (frames, frame1)
  1932     {
  1933       struct frame *f1 = XFRAME (frame1);
  1934 
  1935       if (f != f1)
  1936         {
  1937           /* Verify that we can still talk to the frame's X window, and
  1938              note any recent change in visibility.  */
  1939 #ifdef HAVE_X_WINDOWS
  1940           if (FRAME_WINDOW_P (f1))
  1941             x_sync (f1);
  1942 #endif
  1943           if (!FRAME_TOOLTIP_P (f1)
  1944               /* Tooltips and child frames count neither for
  1945                  invisibility nor for deletions.  */
  1946               && !FRAME_PARENT_FRAME (f1)
  1947               /* Frames with a non-nil `delete-before' parameter don't
  1948                  count for deletions.  */
  1949               && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
  1950               /* For invisibility and normal deletions, at least one
  1951                  visible or iconified frame must remain (Bug#26682).  */
  1952               && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
  1953                   || (!invisible
  1954                       && (force
  1955                           /* Allow deleting the terminal frame when at
  1956                              least one X frame exists.  */
  1957                           || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))))
  1958             return true;
  1959         }
  1960     }
  1961 
  1962   return false;
  1963 }
  1964 
  1965 /**
  1966  * delete_frame:
  1967  *
  1968  * Delete FRAME.  When FORCE equals Qnoelisp, delete FRAME
  1969  * unconditionally.  x_connection_closed and delete_terminal use this.
  1970  * Any other value of FORCE implements the semantics described for
  1971  * Fdelete_frame.  */
  1972 Lisp_Object
  1973 delete_frame (Lisp_Object frame, Lisp_Object force)
  1974 {
  1975   struct frame *f = decode_any_frame (frame);
  1976   struct frame *sf;
  1977   struct kboard *kb;
  1978   Lisp_Object frames, frame1;
  1979   int is_tooltip_frame;
  1980   bool nochild = !FRAME_PARENT_FRAME (f);
  1981   Lisp_Object minibuffer_child_frame = Qnil;
  1982 #ifdef HAVE_X_WINDOWS
  1983   specpdl_ref ref;
  1984 #endif
  1985 
  1986   if (!FRAME_LIVE_P (f))
  1987     return Qnil;
  1988   else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
  1989     {
  1990       if (NILP (force))
  1991         error ("Attempt to delete the sole visible or iconified frame");
  1992       else
  1993         error ("Attempt to delete the only frame");
  1994     }
  1995 #ifdef HAVE_X_WINDOWS
  1996   else if ((x_dnd_in_progress && f == x_dnd_frame)
  1997            || (x_dnd_waiting_for_finish && f == x_dnd_finish_frame))
  1998     error ("Attempt to delete the drop source frame");
  1999 #endif
  2000 #ifdef HAVE_HAIKU
  2001   else if (f == haiku_dnd_frame)
  2002     error ("Attempt to delete the drop source frame");
  2003 #endif
  2004 
  2005   XSETFRAME (frame, f);
  2006 
  2007   /* Softly delete all frames with this frame as their parent frame or
  2008      as their `delete-before' frame parameter value.  */
  2009   FOR_EACH_FRAME (frames, frame1)
  2010     {
  2011       struct frame *f1 = XFRAME (frame1);
  2012 
  2013       if (EQ (frame1, frame) || FRAME_TOOLTIP_P (f1))
  2014         continue;
  2015       else if (FRAME_PARENT_FRAME (f1) == f)
  2016         {
  2017           if (FRAME_HAS_MINIBUF_P (f1) && !FRAME_HAS_MINIBUF_P (f)
  2018               && EQ (FRAME_MINIBUF_WINDOW (f), FRAME_MINIBUF_WINDOW (f1)))
  2019             /* frame1 owns frame's minibuffer window so we must not
  2020                delete it here to avoid a surrogate minibuffer error.
  2021                Unparent frame1 and make it a top-level frame.  */
  2022             {
  2023               Fmodify_frame_parameters
  2024                 (frame1, Fcons (Fcons (Qparent_frame, Qnil), Qnil));
  2025               minibuffer_child_frame = frame1;
  2026             }
  2027           else
  2028             delete_frame (frame1, Qnil);
  2029         }
  2030       else if (nochild
  2031                && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame))
  2032         /* Process `delete-before' parameter iff FRAME is not a child
  2033            frame.  This avoids that we enter an infinite chain of mixed
  2034            dependencies.  */
  2035         delete_frame (frame1, Qnil);
  2036     }
  2037 
  2038   /* Does this frame have a minibuffer, and is it the surrogate
  2039      minibuffer for any other frame?  */
  2040   if (FRAME_HAS_MINIBUF_P (f))
  2041     {
  2042       FOR_EACH_FRAME (frames, frame1)
  2043         {
  2044           Lisp_Object fminiw;
  2045 
  2046           if (EQ (frame1, frame))
  2047             continue;
  2048 
  2049           fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
  2050 
  2051           if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
  2052             {
  2053               /* If we MUST delete this frame, delete the other first.
  2054                  But do this only if FORCE equals `noelisp'.  */
  2055               if (EQ (force, Qnoelisp))
  2056                 delete_frame (frame1, Qnoelisp);
  2057               else
  2058                 error ("Attempt to delete a surrogate minibuffer frame");
  2059             }
  2060         }
  2061     }
  2062 
  2063   is_tooltip_frame = FRAME_TOOLTIP_P (f);
  2064 
  2065   /* Run `delete-frame-functions' unless FORCE is `noelisp' or
  2066      frame is a tooltip.  FORCE is set to `noelisp' when handling
  2067      a disconnect from the terminal, so we don't dare call Lisp
  2068      code.  */
  2069   if (NILP (Vrun_hooks) || is_tooltip_frame)
  2070     ;
  2071   else if (EQ (force, Qnoelisp))
  2072     pending_funcalls
  2073       = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
  2074                pending_funcalls);
  2075   else
  2076     {
  2077 #ifdef HAVE_X_WINDOWS
  2078       /* Also, save clipboard to the clipboard manager.  */
  2079       x_clipboard_manager_save_frame (frame);
  2080 #endif
  2081 
  2082       safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
  2083     }
  2084 
  2085   /* delete_frame_functions may have deleted any frame, including this
  2086      one.  */
  2087   if (!FRAME_LIVE_P (f))
  2088     return Qnil;
  2089   else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
  2090     {
  2091       if (NILP (force))
  2092         error ("Attempt to delete the sole visible or iconified frame");
  2093       else
  2094         error ("Attempt to delete the only frame");
  2095     }
  2096 
  2097   /* At this point, we are committed to deleting the frame.
  2098      There is no more chance for errors to prevent it.  */
  2099   sf = SELECTED_FRAME ();
  2100   /* Don't let the frame remain selected.  */
  2101   if (f == sf)
  2102     {
  2103       Lisp_Object tail;
  2104       Lisp_Object frame1 UNINIT;  /* This line works around GCC bug 85563.  */
  2105       eassume (CONSP (Vframe_list));
  2106 
  2107       /* Look for another visible frame on the same terminal.
  2108          Do not call next_frame here because it may loop forever.
  2109          See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025.  */
  2110       FOR_EACH_FRAME (tail, frame1)
  2111         {
  2112           struct frame *f1 = XFRAME (frame1);
  2113 
  2114           if (!EQ (frame, frame1)
  2115               && !FRAME_TOOLTIP_P (f1)
  2116               && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1)
  2117               && FRAME_VISIBLE_P (f1))
  2118             break;
  2119         }
  2120 
  2121       /* If there is none, find *some* other frame.  */
  2122       if (NILP (frame1) || EQ (frame1, frame))
  2123         {
  2124           FOR_EACH_FRAME (tail, frame1)
  2125             {
  2126               struct frame *f1 = XFRAME (frame1);
  2127 
  2128               if (!EQ (frame, frame1)
  2129                   && FRAME_LIVE_P (f1)
  2130                   && !FRAME_TOOLTIP_P (f1))
  2131                 {
  2132                   if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
  2133                     {
  2134                       Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
  2135 
  2136                       if (!EQ (top_frame, frame))
  2137                         frame1 = top_frame;
  2138                     }
  2139                   break;
  2140                 }
  2141             }
  2142         }
  2143 #ifdef NS_IMPL_COCOA
  2144       else
  2145         /* Under NS, there is no system mechanism for choosing a new
  2146            window to get focus -- it is left to application code.
  2147            So the portion of THIS application interfacing with NS
  2148            needs to know about it.  We call Fraise_frame, but the
  2149            purpose is really to transfer focus.  */
  2150         Fraise_frame (frame1);
  2151 #endif
  2152 
  2153       do_switch_frame (frame1, 0, 1, Qnil);
  2154       sf = SELECTED_FRAME ();
  2155     }
  2156   else
  2157     /* Ensure any minibuffers on FRAME are moved onto the selected
  2158        frame.  */
  2159     move_minibuffers_onto_frame (f, selected_frame, true);
  2160 
  2161   /* Don't let echo_area_window to remain on a deleted frame.  */
  2162   if (EQ (f->minibuffer_window, echo_area_window))
  2163     echo_area_window = sf->minibuffer_window;
  2164 
  2165   /* Clear any X selections for this frame.  */
  2166 #ifdef HAVE_X_WINDOWS
  2167   if (FRAME_X_P (f))
  2168     {
  2169       /* Don't preserve selections when a display is going away, since
  2170          that sends stuff down the wire.  */
  2171 
  2172       ref = SPECPDL_INDEX ();
  2173 
  2174       if (EQ (force, Qnoelisp))
  2175         specbind (Qx_auto_preserve_selections, Qnil);
  2176 
  2177       x_clear_frame_selections (f);
  2178       unbind_to (ref, Qnil);
  2179     }
  2180 #endif
  2181 
  2182 #ifdef HAVE_PGTK
  2183   if (FRAME_PGTK_P (f))
  2184     {
  2185       /* Do special selection events now, in case the window gets
  2186          destroyed by this deletion.  Does this run Lisp code?  */
  2187       swallow_events (false);
  2188 
  2189       pgtk_clear_frame_selections (f);
  2190     }
  2191 #endif
  2192 
  2193   /* Free glyphs.
  2194      This function must be called before the window tree of the
  2195      frame is deleted because windows contain dynamically allocated
  2196      memory. */
  2197   free_glyphs (f);
  2198 
  2199 #ifdef HAVE_WINDOW_SYSTEM
  2200   /* Give chance to each font driver to free a frame specific data.  */
  2201   font_update_drivers (f, Qnil);
  2202 #endif
  2203 
  2204   /* Mark all the windows that used to be on FRAME as deleted, and then
  2205      remove the reference to them.  */
  2206   delete_all_child_windows (f->root_window);
  2207   fset_root_window (f, Qnil);
  2208 
  2209   Vframe_list = Fdelq (frame, Vframe_list);
  2210   SET_FRAME_VISIBLE (f, 0);
  2211 
  2212   /* Allow the vector of menu bar contents to be freed in the next
  2213      garbage collection.  The frame object itself may not be garbage
  2214      collected until much later, because recent_keys and other data
  2215      structures can still refer to it.  */
  2216   fset_menu_bar_vector (f, Qnil);
  2217 
  2218   /* If FRAME's buffer lists contains killed
  2219      buffers, this helps GC to reclaim them.  */
  2220   fset_buffer_list (f, Qnil);
  2221   fset_buried_buffer_list (f, Qnil);
  2222 
  2223   free_font_driver_list (f);
  2224 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
  2225   xfree (f->namebuf);
  2226 #endif
  2227   xfree (f->decode_mode_spec_buffer);
  2228   xfree (FRAME_INSERT_COST (f));
  2229   xfree (FRAME_DELETEN_COST (f));
  2230   xfree (FRAME_INSERTN_COST (f));
  2231   xfree (FRAME_DELETE_COST (f));
  2232 
  2233   /* Since some events are handled at the interrupt level, we may get
  2234      an event for f at any time; if we zero out the frame's terminal
  2235      now, then we may trip up the event-handling code.  Instead, we'll
  2236      promise that the terminal of the frame must be valid until we
  2237      have called the window-system-dependent frame destruction
  2238      routine.  */
  2239   {
  2240     struct terminal *terminal;
  2241     block_input ();
  2242     if (FRAME_TERMINAL (f)->delete_frame_hook)
  2243       (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
  2244     terminal = FRAME_TERMINAL (f);
  2245     f->terminal = 0;             /* Now the frame is dead.  */
  2246     unblock_input ();
  2247 
  2248     /* If needed, delete the terminal that this frame was on.
  2249        (This must be done after the frame is killed.)  */
  2250     terminal->reference_count--;
  2251 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
  2252     /* FIXME: Deleting the terminal crashes emacs because of a GTK
  2253        bug.
  2254        https://lists.gnu.org/r/emacs-devel/2011-10/msg00363.html */
  2255 
  2256     /* Since a similar behavior was observed on the Lucid and Motif
  2257        builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now
  2258        don't delete the terminal for these builds either.  */
  2259     if (terminal->reference_count == 0
  2260         && (terminal->type == output_x_window
  2261             || terminal->type == output_pgtk))
  2262       terminal->reference_count = 1;
  2263 #endif /* USE_X_TOOLKIT || USE_GTK */
  2264 
  2265     if (terminal->reference_count == 0)
  2266       {
  2267         Lisp_Object tmp;
  2268         XSETTERMINAL (tmp, terminal);
  2269 
  2270         kb = NULL;
  2271 
  2272         /* If force is noelisp, the terminal is going away inside
  2273            x_delete_terminal, and a recursive call to Fdelete_terminal
  2274            is unsafe!  */
  2275         if (!EQ (force, Qnoelisp))
  2276           Fdelete_terminal (tmp, NILP (force) ? Qt : force);
  2277       }
  2278     else
  2279       kb = terminal->kboard;
  2280   }
  2281 
  2282   /* If we've deleted the last_nonminibuf_frame, then try to find
  2283      another one.  */
  2284   if (f == last_nonminibuf_frame)
  2285     {
  2286       last_nonminibuf_frame = 0;
  2287 
  2288       FOR_EACH_FRAME (frames, frame1)
  2289         {
  2290           struct frame *f1 = XFRAME (frame1);
  2291 
  2292           if (!FRAME_MINIBUF_ONLY_P (f1))
  2293             {
  2294               last_nonminibuf_frame = f1;
  2295               break;
  2296             }
  2297         }
  2298     }
  2299 
  2300   /* If there's no other frame on the same kboard, get out of
  2301      single-kboard state if we're in it for this kboard.  */
  2302   if (kb != NULL)
  2303     {
  2304       /* Some frame we found on the same kboard, or nil if there are none.  */
  2305       Lisp_Object frame_on_same_kboard = Qnil;
  2306 
  2307       FOR_EACH_FRAME (frames, frame1)
  2308         if (kb == FRAME_KBOARD (XFRAME (frame1)))
  2309           frame_on_same_kboard = frame1;
  2310 
  2311       if (NILP (frame_on_same_kboard))
  2312         not_single_kboard_state (kb);
  2313     }
  2314 
  2315 
  2316   /* If we've deleted this keyboard's default_minibuffer_frame, try to
  2317      find another one.  Prefer minibuffer-only frames, but also notice
  2318      frames with other windows.  */
  2319   if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
  2320     {
  2321       /* The last frame we saw with a minibuffer, minibuffer-only or not.  */
  2322       Lisp_Object frame_with_minibuf = Qnil;
  2323       /* Some frame we found on the same kboard, or nil if there are none.  */
  2324       Lisp_Object frame_on_same_kboard = Qnil;
  2325 
  2326       FOR_EACH_FRAME (frames, frame1)
  2327         {
  2328           struct frame *f1 = XFRAME (frame1);
  2329 
  2330           /* Set frame_on_same_kboard to frame1 if it is on the same
  2331              keyboard.  Set frame_with_minibuf to frame1 if it also
  2332              has a minibuffer.  Leave the loop immediately if frame1
  2333              is also minibuffer-only.
  2334 
  2335              Emacs 26 does _not_ set frame_on_same_kboard here when it
  2336              finds a minibuffer-only frame and subsequently fails to
  2337              set default_minibuffer_frame below.  Not a great deal and
  2338              never noticed since make_frame_without_minibuffer creates
  2339              a new minibuffer frame in that case (which can be a minor
  2340              annoyance though).  To consider for Emacs 26.3.  */
  2341           if (kb == FRAME_KBOARD (f1))
  2342             {
  2343               frame_on_same_kboard = frame1;
  2344               if (FRAME_HAS_MINIBUF_P (f1))
  2345                 {
  2346                   frame_with_minibuf = frame1;
  2347                   if (FRAME_MINIBUF_ONLY_P (f1))
  2348                     break;
  2349                 }
  2350             }
  2351         }
  2352 
  2353       if (!NILP (frame_on_same_kboard))
  2354         {
  2355           /* We know that there must be some frame with a minibuffer out
  2356              there.  If this were not true, all of the frames present
  2357              would have to be minibufferless, which implies that at some
  2358              point their minibuffer frames must have been deleted, but
  2359              that is prohibited at the top; you can't delete surrogate
  2360              minibuffer frames.  */
  2361           if (NILP (frame_with_minibuf))
  2362             emacs_abort ();
  2363 
  2364           kset_default_minibuffer_frame (kb, frame_with_minibuf);
  2365         }
  2366       else
  2367         /* No frames left on this kboard--say no minibuffer either.  */
  2368         kset_default_minibuffer_frame (kb, Qnil);
  2369     }
  2370 
  2371   /* Cause frame titles to update--necessary if we now have just one
  2372      frame.  */
  2373   if (!is_tooltip_frame)
  2374     update_mode_lines = 15;
  2375 
  2376   /* Now run the post-deletion hooks.  */
  2377   if (NILP (Vrun_hooks) || is_tooltip_frame)
  2378     ;
  2379   else if (EQ (force, Qnoelisp))
  2380     pending_funcalls
  2381       = Fcons (list3 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame),
  2382                pending_funcalls);
  2383   else
  2384     safe_call2 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame);
  2385 
  2386   if (!NILP (minibuffer_child_frame))
  2387     /* If minibuffer_child_frame is non-nil, it was FRAME's minibuffer
  2388        child frame.  Delete it unless it's also the minibuffer frame
  2389        of another frame in which case we make sure it's visible.  */
  2390     {
  2391       struct frame *f1 = XFRAME (minibuffer_child_frame);
  2392 
  2393       if (FRAME_LIVE_P (f1))
  2394         {
  2395           Lisp_Object window1 = FRAME_ROOT_WINDOW (f1);
  2396           Lisp_Object frame2;
  2397 
  2398           FOR_EACH_FRAME (frames, frame2)
  2399             {
  2400               struct frame *f2 = XFRAME (frame2);
  2401 
  2402               if (EQ (frame2, minibuffer_child_frame) || FRAME_TOOLTIP_P (f2))
  2403                 continue;
  2404               else if (EQ (FRAME_MINIBUF_WINDOW (f2), window1))
  2405                 {
  2406                   /* minibuffer_child_frame serves as minibuffer frame
  2407                      for at least one other frame - so make it visible
  2408                      and quit.  */
  2409                   if (!FRAME_VISIBLE_P (f1) && !FRAME_ICONIFIED_P (f1))
  2410                     Fmake_frame_visible (minibuffer_child_frame);
  2411 
  2412                   return Qnil;
  2413                 }
  2414             }
  2415 
  2416           /* No other frame found that uses minibuffer_child_frame as
  2417              minibuffer frame.  If FORCE is Qnoelisp or there are
  2418              other visible frames left, delete minibuffer_child_frame
  2419              since it presumably was used by FRAME only.  */
  2420           if (EQ (force, Qnoelisp) || other_frames (f1, false, !NILP (force)))
  2421             delete_frame (minibuffer_child_frame, Qnoelisp);
  2422         }
  2423     }
  2424 
  2425   return Qnil;
  2426 }
  2427 
  2428 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
  2429        doc: /* Delete FRAME, eliminating it from use.
  2430 FRAME must be a live frame and defaults to the selected one.
  2431 
  2432 When `undelete-frame-mode' is enabled, the 16 most recently deleted
  2433 frames can be undeleted with `undelete-frame', which see.
  2434 
  2435 A frame may not be deleted if its minibuffer serves as surrogate
  2436 minibuffer for another frame.  Normally, you may not delete a frame if
  2437 all other frames are invisible, but if the second optional argument
  2438 FORCE is non-nil, you may do so.
  2439 
  2440 This function runs `delete-frame-functions' before actually
  2441 deleting the frame, unless the frame is a tooltip.
  2442 The functions are run with one argument, the frame to be deleted.  */)
  2443   (Lisp_Object frame, Lisp_Object force)
  2444 {
  2445   return delete_frame (frame, !NILP (force) ? Qt : Qnil);
  2446 }
  2447 
  2448 #ifdef HAVE_WINDOW_SYSTEM
  2449 /**
  2450  * frame_internal_border_part:
  2451  *
  2452  * Return part of internal border the coordinates X and Y relative to
  2453  * frame F are on.  Return nil if the coordinates are not on the
  2454  * internal border of F.
  2455  *
  2456  * Return one of INTERNAL_BORDER_LEFT_EDGE, INTERNAL_BORDER_TOP_EDGE,
  2457  * INTERNAL_BORDER_RIGHT_EDGE or INTERNAL_BORDER_BOTTOM_EDGE when the
  2458  * mouse cursor is on the corresponding border with an offset of at
  2459  * least one canonical character height from that border's edges.
  2460  *
  2461  * If no border part could be found this way, return one of
  2462  * INTERNAL_BORDER_TOP_LEFT_CORNER, INTERNAL_BORDER_TOP_RIGHT_CORNER,
  2463  * INTERNAL_BORDER_BOTTOM_LEFT_CORNER or
  2464  * INTERNAL_BORDER_BOTTOM_RIGHT_CORNER to indicate that the mouse is in
  2465  * one of the corresponding corners.  This means that for very small
  2466  * frames an `edge' return value is preferred.
  2467  */
  2468 enum internal_border_part
  2469 frame_internal_border_part (struct frame *f, int x, int y)
  2470 {
  2471   int border = FRAME_INTERNAL_BORDER_WIDTH (f);
  2472   int offset = FRAME_LINE_HEIGHT (f);
  2473   int width = FRAME_PIXEL_WIDTH (f);
  2474   int height = FRAME_PIXEL_HEIGHT (f);
  2475   enum internal_border_part part = INTERNAL_BORDER_NONE;
  2476 
  2477   if (offset < border)
  2478     /* For very wide borders make offset at least as large as
  2479        border.  */
  2480     offset = border;
  2481 
  2482   if (offset < x && x < width - offset)
  2483     /* Top or bottom border.  */
  2484     {
  2485       if (0 <= y && y <= border)
  2486         part = INTERNAL_BORDER_TOP_EDGE;
  2487       else if (height - border <= y && y <= height)
  2488         part = INTERNAL_BORDER_BOTTOM_EDGE;
  2489     }
  2490   else if (offset < y && y < height - offset)
  2491     /* Left or right border.  */
  2492     {
  2493       if (0 <= x && x <= border)
  2494         part = INTERNAL_BORDER_LEFT_EDGE;
  2495       else if (width - border <= x && x <= width)
  2496         part = INTERNAL_BORDER_RIGHT_EDGE;
  2497     }
  2498   else
  2499     {
  2500       /* An edge.  */
  2501       int half_width = width / 2;
  2502       int half_height = height / 2;
  2503 
  2504       if (0 <= x && x <= border)
  2505         {
  2506           /* A left edge.  */
  2507           if (0 <= y && y <= half_height)
  2508              part = INTERNAL_BORDER_TOP_LEFT_CORNER;
  2509           else if (half_height < y && y <= height)
  2510              part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
  2511         }
  2512       else if (width - border <= x && x <= width)
  2513         {
  2514           /* A right edge.  */
  2515           if (0 <= y && y <= half_height)
  2516              part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
  2517           else if (half_height < y && y <= height)
  2518              part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
  2519         }
  2520       else if (0 <= y && y <= border)
  2521         {
  2522           /* A top edge.  */
  2523           if (0 <= x && x <= half_width)
  2524              part = INTERNAL_BORDER_TOP_LEFT_CORNER;
  2525           else if (half_width < x && x <= width)
  2526             part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
  2527         }
  2528       else if (height - border <= y && y <= height)
  2529         {
  2530           /* A bottom edge.  */
  2531           if (0 <= x && x <= half_width)
  2532              part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
  2533           else if (half_width < x && x <= width)
  2534             part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
  2535         }
  2536     }
  2537 
  2538   return part;
  2539 }
  2540 #endif
  2541 
  2542 /* Return mouse position in character cell units.  */
  2543 
  2544 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
  2545        doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
  2546 The position is given in canonical character cells, where (0, 0) is the
  2547 upper-left corner of the frame, X is the horizontal offset, and Y is the
  2548 vertical offset, measured in units of the frame's default character size.
  2549 If Emacs is running on a mouseless terminal or hasn't been programmed
  2550 to read the mouse position, it returns the selected frame for FRAME
  2551 and nil for X and Y.
  2552 
  2553 FRAME might be nil if `track-mouse' is set to `drag-source'.  This
  2554 means there is no frame under the mouse.  If `mouse-position-function'
  2555 is non-nil, `mouse-position' calls it, passing the normal return value
  2556 to that function as an argument, and returns whatever that function
  2557 returns.  */)
  2558   (void)
  2559 {
  2560   return mouse_position (true);
  2561 }
  2562 
  2563 Lisp_Object
  2564 mouse_position (bool call_mouse_position_function)
  2565 {
  2566   struct frame *f;
  2567   Lisp_Object lispy_dummy;
  2568   Lisp_Object x, y, retval;
  2569 
  2570   f = SELECTED_FRAME ();
  2571   x = y = Qnil;
  2572 
  2573   /* It's okay for the hook to refrain from storing anything.  */
  2574   if (FRAME_TERMINAL (f)->mouse_position_hook)
  2575     {
  2576       enum scroll_bar_part party_dummy;
  2577       Time time_dummy;
  2578       (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
  2579                                                   &lispy_dummy, &party_dummy,
  2580                                                   &x, &y,
  2581                                                   &time_dummy);
  2582     }
  2583 
  2584   if (! NILP (x) && f)
  2585     {
  2586       int col = XFIXNUM (x);
  2587       int row = XFIXNUM (y);
  2588       pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
  2589       XSETINT (x, col);
  2590       XSETINT (y, row);
  2591     }
  2592   if (f)
  2593     XSETFRAME (lispy_dummy, f);
  2594   else
  2595     lispy_dummy = Qnil;
  2596   retval = Fcons (lispy_dummy, Fcons (x, y));
  2597   if (call_mouse_position_function && !NILP (Vmouse_position_function))
  2598     retval = call1 (Vmouse_position_function, retval);
  2599   return retval;
  2600 }
  2601 
  2602 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
  2603        Smouse_pixel_position, 0, 0, 0,
  2604        doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
  2605 The position is given in pixel units, where (0, 0) is the
  2606 upper-left corner of the frame, X is the horizontal offset, and Y is
  2607 the vertical offset.
  2608 FRAME might be nil if `track-mouse' is set to `drag-source'.  This
  2609 means there is no frame under the mouse.  If Emacs is running on a
  2610 mouseless terminal or hasn't been programmed to read the mouse
  2611 position, it returns the selected frame for FRAME and nil for X and
  2612 Y.  */)
  2613   (void)
  2614 {
  2615   struct frame *f;
  2616   Lisp_Object lispy_dummy;
  2617   Lisp_Object x, y, retval;
  2618 
  2619   f = SELECTED_FRAME ();
  2620   x = y = Qnil;
  2621 
  2622   /* It's okay for the hook to refrain from storing anything.  */
  2623   if (FRAME_TERMINAL (f)->mouse_position_hook)
  2624     {
  2625       enum scroll_bar_part party_dummy;
  2626       Time time_dummy;
  2627       (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
  2628                                                   &lispy_dummy, &party_dummy,
  2629                                                   &x, &y,
  2630                                                   &time_dummy);
  2631     }
  2632 
  2633   if (f)
  2634     XSETFRAME (lispy_dummy, f);
  2635   else
  2636     lispy_dummy = Qnil;
  2637 
  2638   retval = Fcons (lispy_dummy, Fcons (x, y));
  2639   if (!NILP (Vmouse_position_function))
  2640     retval = call1 (Vmouse_position_function, retval);
  2641   return retval;
  2642 }
  2643 
  2644 #ifdef HAVE_WINDOW_SYSTEM
  2645 
  2646 /* On frame F, convert character coordinates X and Y to pixel
  2647    coordinates *PIX_X and *PIX_Y.  */
  2648 
  2649 static void
  2650 frame_char_to_pixel_position (struct frame *f, int x, int y,
  2651                               int *pix_x, int *pix_y)
  2652 {
  2653   *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
  2654   *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
  2655 
  2656   if (*pix_x < 0)
  2657     *pix_x = 0;
  2658   if (*pix_x > FRAME_PIXEL_WIDTH (f))
  2659     *pix_x = FRAME_PIXEL_WIDTH (f);
  2660 
  2661   if (*pix_y < 0)
  2662     *pix_y = 0;
  2663   if (*pix_y > FRAME_PIXEL_HEIGHT (f))
  2664     *pix_y = FRAME_PIXEL_HEIGHT (f);
  2665 }
  2666 
  2667 /* On frame F, reposition mouse pointer to character coordinates X and Y.  */
  2668 
  2669 static void
  2670 frame_set_mouse_position (struct frame *f, int x, int y)
  2671 {
  2672   int pix_x, pix_y;
  2673 
  2674   frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
  2675   frame_set_mouse_pixel_position (f, pix_x, pix_y);
  2676 }
  2677 
  2678 #endif /* HAVE_WINDOW_SYSTEM */
  2679 
  2680 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
  2681        doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
  2682 Coordinates are relative to the frame, not a window,
  2683 so the coordinates of the top left character in the frame
  2684 may be nonzero due to left-hand scroll bars or the menu bar.
  2685 
  2686 The position is given in canonical character cells, where (0, 0) is
  2687 the upper-left corner of the frame, X is the horizontal offset, and
  2688 Y is the vertical offset, measured in units of the frame's default
  2689 character size.
  2690 
  2691 This function is a no-op for an X frame that is not visible.
  2692 If you have just created a frame, you must wait for it to become visible
  2693 before calling this function on it, like this.
  2694   (while (not (frame-visible-p frame)) (sleep-for .5))  */)
  2695   (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
  2696 {
  2697   CHECK_LIVE_FRAME (frame);
  2698   int xval = check_integer_range (x, INT_MIN, INT_MAX);
  2699   int yval = check_integer_range (y, INT_MIN, INT_MAX);
  2700 
  2701   /* I think this should be done with a hook.  */
  2702   if (FRAME_WINDOW_P (XFRAME (frame)))
  2703     {
  2704 #ifdef HAVE_WINDOW_SYSTEM
  2705       /* Warping the mouse will cause enternotify and focus events.  */
  2706       frame_set_mouse_position (XFRAME (frame), xval, yval);
  2707 #endif /* HAVE_WINDOW_SYSTEM */
  2708     }
  2709 #ifdef MSDOS
  2710   else if (FRAME_MSDOS_P (XFRAME (frame)))
  2711     {
  2712       Fselect_frame (frame, Qnil);
  2713       mouse_moveto (xval, yval);
  2714     }
  2715 #endif /* MSDOS */
  2716   else
  2717     {
  2718       Fselect_frame (frame, Qnil);
  2719 #ifdef HAVE_GPM
  2720       term_mouse_moveto (xval, yval);
  2721 #else
  2722       (void) xval;
  2723       (void) yval;
  2724 #endif /* HAVE_GPM */
  2725     }
  2726 
  2727   return Qnil;
  2728 }
  2729 
  2730 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
  2731        Sset_mouse_pixel_position, 3, 3, 0,
  2732        doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
  2733 The position is given in pixels, where (0, 0) is the upper-left corner
  2734 of the frame, X is the horizontal offset, and Y is the vertical offset.
  2735 
  2736 Note, this is a no-op for an X frame that is not visible.
  2737 If you have just created a frame, you must wait for it to become visible
  2738 before calling this function on it, like this.
  2739   (while (not (frame-visible-p frame)) (sleep-for .5))  */)
  2740   (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
  2741 {
  2742   CHECK_LIVE_FRAME (frame);
  2743   int xval = check_integer_range (x, INT_MIN, INT_MAX);
  2744   int yval = check_integer_range (y, INT_MIN, INT_MAX);
  2745 
  2746   /* I think this should be done with a hook.  */
  2747   if (FRAME_WINDOW_P (XFRAME (frame)))
  2748     {
  2749       /* Warping the mouse will cause enternotify and focus events.  */
  2750 #ifdef HAVE_WINDOW_SYSTEM
  2751       frame_set_mouse_pixel_position (XFRAME (frame), xval, yval);
  2752 #endif /* HAVE_WINDOW_SYSTEM */
  2753     }
  2754 #ifdef MSDOS
  2755   else if (FRAME_MSDOS_P (XFRAME (frame)))
  2756     {
  2757       Fselect_frame (frame, Qnil);
  2758       mouse_moveto (xval, yval);
  2759     }
  2760 #endif /* MSDOS */
  2761   else
  2762     {
  2763       Fselect_frame (frame, Qnil);
  2764 #ifdef HAVE_GPM
  2765       term_mouse_moveto (xval, yval);
  2766 #else
  2767       (void) xval;
  2768       (void) yval;
  2769 #endif /* HAVE_GPM */
  2770 
  2771     }
  2772 
  2773   return Qnil;
  2774 }
  2775 
  2776 static void make_frame_visible_1 (Lisp_Object);
  2777 
  2778 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
  2779        0, 1, "",
  2780        doc: /* Make the frame FRAME visible (assuming it is an X window).
  2781 If omitted, FRAME defaults to the currently selected frame.  */)
  2782   (Lisp_Object frame)
  2783 {
  2784   struct frame *f = decode_live_frame (frame);
  2785 
  2786   if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
  2787     FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, true);
  2788 
  2789   make_frame_visible_1 (f->root_window);
  2790 
  2791   /* Make menu bar update for the Buffers and Frames menus.  */
  2792   /* windows_or_buffers_changed = 15; FIXME: Why?  */
  2793 
  2794   XSETFRAME (frame, f);
  2795   return frame;
  2796 }
  2797 
  2798 /* Update the display_time slot of the buffers shown in WINDOW
  2799    and all its descendants.  */
  2800 
  2801 static void
  2802 make_frame_visible_1 (Lisp_Object window)
  2803 {
  2804   struct window *w;
  2805 
  2806   for (; !NILP (window); window = w->next)
  2807     {
  2808       w = XWINDOW (window);
  2809       if (WINDOWP (w->contents))
  2810         make_frame_visible_1 (w->contents);
  2811       else
  2812         bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
  2813     }
  2814 }
  2815 
  2816 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
  2817        0, 2, "",
  2818        doc: /* Make the frame FRAME invisible.
  2819 If omitted, FRAME defaults to the currently selected frame.
  2820 On graphical displays, invisible frames are not updated and are
  2821 usually not displayed at all, even in a window system's \"taskbar\".
  2822 
  2823 Normally you may not make FRAME invisible if all other frames are invisible,
  2824 but if the second optional argument FORCE is non-nil, you may do so.
  2825 
  2826 This function has no effect on text terminal frames.  Such frames are
  2827 always considered visible, whether or not they are currently being
  2828 displayed in the terminal.  */)
  2829   (Lisp_Object frame, Lisp_Object force)
  2830 {
  2831   struct frame *f = decode_live_frame (frame);
  2832 
  2833   if (NILP (force) && !other_frames (f, true, false))
  2834     error ("Attempt to make invisible the sole visible or iconified frame");
  2835 
  2836   if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook)
  2837     FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, false);
  2838 
  2839   /* Make menu bar update for the Buffers and Frames menus.  */
  2840   windows_or_buffers_changed = 16;
  2841 
  2842   return Qnil;
  2843 }
  2844 
  2845 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
  2846        0, 1, "",
  2847        doc: /* Make the frame FRAME into an icon.
  2848 If omitted, FRAME defaults to the currently selected frame.
  2849 
  2850 If FRAME is a child frame, consult the variable `iconify-child-frame'
  2851 for how to proceed.  */)
  2852   (Lisp_Object frame)
  2853 {
  2854   struct frame *f = decode_live_frame (frame);
  2855 #ifdef HAVE_WINDOW_SYSTEM
  2856   Lisp_Object parent = f->parent_frame;
  2857 
  2858   if (!NILP (parent))
  2859     {
  2860       if (NILP (iconify_child_frame))
  2861         /* Do nothing.  */
  2862         return Qnil;
  2863       else if (EQ (iconify_child_frame, Qiconify_top_level))
  2864         {
  2865           /* Iconify top level frame instead (the default).  */
  2866           Ficonify_frame (parent);
  2867           return Qnil;
  2868         }
  2869       else if (EQ (iconify_child_frame, Qmake_invisible))
  2870         {
  2871           /* Make frame invisible instead.  */
  2872           Fmake_frame_invisible (frame, Qnil);
  2873           return Qnil;
  2874         }
  2875     }
  2876 #endif  /* HAVE_WINDOW_SYSTEM */
  2877 
  2878   if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->iconify_frame_hook)
  2879     FRAME_TERMINAL (f)->iconify_frame_hook (f);
  2880 
  2881   return Qnil;
  2882 }
  2883 
  2884 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
  2885        1, 1, 0,
  2886        doc: /* Return t if FRAME is \"visible\" (actually in use for display).
  2887 Return the symbol `icon' if FRAME is iconified or \"minimized\".
  2888 Return nil if FRAME was made invisible, via `make-frame-invisible'.
  2889 On graphical displays, invisible frames are not updated and are
  2890 usually not displayed at all, even in a window system's \"taskbar\".
  2891 
  2892 If FRAME is a text terminal frame, this always returns t.
  2893 Such frames are always considered visible, whether or not they are
  2894 currently being displayed on the terminal.  */)
  2895   (Lisp_Object frame)
  2896 {
  2897   CHECK_LIVE_FRAME (frame);
  2898 
  2899   if (FRAME_VISIBLE_P (XFRAME (frame)))
  2900     return Qt;
  2901   if (FRAME_ICONIFIED_P (XFRAME (frame)))
  2902     return Qicon;
  2903   return Qnil;
  2904 }
  2905 
  2906 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
  2907        0, 0, 0,
  2908        doc: /* Return a list of all frames now \"visible\" (being updated).  */)
  2909   (void)
  2910 {
  2911   Lisp_Object tail, frame, value = Qnil;
  2912 
  2913   FOR_EACH_FRAME (tail, frame)
  2914     if (FRAME_VISIBLE_P (XFRAME (frame)))
  2915       value = Fcons (frame, value);
  2916 
  2917   return value;
  2918 }
  2919 
  2920 
  2921 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
  2922        doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
  2923 If FRAME is invisible or iconified, make it visible.
  2924 If you don't specify a frame, the selected frame is used.
  2925 If Emacs is displaying on an ordinary terminal or some other device which
  2926 doesn't support multiple overlapping frames, this function selects FRAME.  */)
  2927   (Lisp_Object frame)
  2928 {
  2929   struct frame *f = decode_live_frame (frame);
  2930 
  2931   XSETFRAME (frame, f);
  2932 
  2933   if (FRAME_TERMCAP_P (f))
  2934     /* On a text terminal select FRAME.  */
  2935     Fselect_frame (frame, Qnil);
  2936   else
  2937     /* Do like the documentation says. */
  2938     Fmake_frame_visible (frame);
  2939 
  2940   if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
  2941     (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, true);
  2942 
  2943   return Qnil;
  2944 }
  2945 
  2946 /* Should we have a corresponding function called Flower_Power?  */
  2947 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
  2948        doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
  2949 If you don't specify a frame, the selected frame is used.
  2950 If Emacs is displaying on an ordinary terminal or some other device which
  2951 doesn't support multiple overlapping frames, this function does nothing.  */)
  2952   (Lisp_Object frame)
  2953 {
  2954   struct frame *f = decode_live_frame (frame);
  2955 
  2956   if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
  2957     (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, false);
  2958 
  2959   return Qnil;
  2960 }
  2961 
  2962 
  2963 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
  2964        1, 2, 0,
  2965        doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
  2966 In other words, switch-frame events caused by events in FRAME will
  2967 request a switch to FOCUS-FRAME, and `last-event-frame' will be
  2968 FOCUS-FRAME after reading an event typed at FRAME.
  2969 
  2970 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
  2971 frame again receives its own keystrokes.
  2972 
  2973 Focus redirection is useful for temporarily redirecting keystrokes to
  2974 a surrogate minibuffer frame when a frame doesn't have its own
  2975 minibuffer window.
  2976 
  2977 A frame's focus redirection can be changed by `select-frame'.  If frame
  2978 FOO is selected, and then a different frame BAR is selected, any
  2979 frames redirecting their focus to FOO are shifted to redirect their
  2980 focus to BAR.  This allows focus redirection to work properly when the
  2981 user switches from one frame to another using `select-window'.
  2982 
  2983 This means that a frame whose focus is redirected to itself is treated
  2984 differently from a frame whose focus is redirected to nil; the former
  2985 is affected by `select-frame', while the latter is not.
  2986 
  2987 The redirection lasts until `redirect-frame-focus' is called to change it.  */)
  2988   (Lisp_Object frame, Lisp_Object focus_frame)
  2989 {
  2990   /* Note that we don't check for a live frame here.  It's reasonable
  2991      to redirect the focus of a frame you're about to delete, if you
  2992      know what other frame should receive those keystrokes.  */
  2993   struct frame *f = decode_any_frame (frame);
  2994 
  2995   if (! NILP (focus_frame))
  2996     CHECK_LIVE_FRAME (focus_frame);
  2997 
  2998   fset_focus_frame (f, focus_frame);
  2999 
  3000   if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
  3001     (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
  3002 
  3003   return Qnil;
  3004 }
  3005 
  3006 
  3007 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
  3008        doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
  3009 If FRAME is omitted or nil, the selected frame is used.
  3010 Return nil if FRAME's focus is not redirected.
  3011 See `redirect-frame-focus'.  */)
  3012   (Lisp_Object frame)
  3013 {
  3014   return FRAME_FOCUS_FRAME (decode_live_frame (frame));
  3015 }
  3016 
  3017 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 2, 0,
  3018        doc: /* Set the input focus to FRAME.
  3019 FRAME nil means use the selected frame.  Optional argument NOACTIVATE
  3020 means do not activate FRAME.
  3021 
  3022 If there is no window system support, this function does nothing.  */)
  3023      (Lisp_Object frame, Lisp_Object noactivate)
  3024 {
  3025 #ifdef HAVE_WINDOW_SYSTEM
  3026   struct frame *f = decode_window_system_frame (frame);
  3027   if (f && FRAME_TERMINAL (f)->focus_frame_hook)
  3028     FRAME_TERMINAL (f)->focus_frame_hook (f, !NILP (noactivate));
  3029 #endif
  3030   return Qnil;
  3031 }
  3032 
  3033 DEFUN ("frame-after-make-frame",
  3034        Fframe_after_make_frame,
  3035        Sframe_after_make_frame, 2, 2, 0,
  3036        doc: /* Mark FRAME as made.
  3037 FRAME nil means use the selected frame.  Second argument MADE non-nil
  3038 means functions on `window-configuration-change-hook' are called
  3039 whenever the window configuration of FRAME changes.  MADE nil means
  3040 these functions are not called.
  3041 
  3042 This function is currently called by `make-frame' only and should be
  3043 otherwise used with utter care to avoid that running functions on
  3044 `window-configuration-change-hook' is impeded forever.  */)
  3045   (Lisp_Object frame, Lisp_Object made)
  3046 {
  3047   struct frame *f = decode_live_frame (frame);
  3048   f->after_make_frame = !NILP (made);
  3049   f->inhibit_horizontal_resize = false;
  3050   f->inhibit_vertical_resize = false;
  3051   return made;
  3052 }
  3053 
  3054 
  3055 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame.  */
  3056 
  3057 void
  3058 frames_discard_buffer (Lisp_Object buffer)
  3059 {
  3060   Lisp_Object frame, tail;
  3061 
  3062   FOR_EACH_FRAME (tail, frame)
  3063     {
  3064       fset_buffer_list
  3065         (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
  3066       fset_buried_buffer_list
  3067         (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
  3068     }
  3069 }
  3070 
  3071 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
  3072    If the alist already has an element for PROP, we change it.  */
  3073 
  3074 void
  3075 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
  3076 {
  3077   Lisp_Object tem = Fassq (prop, *alistptr);
  3078   if (NILP (tem))
  3079     *alistptr = Fcons (Fcons (prop, val), *alistptr);
  3080   else
  3081     Fsetcdr (tem, val);
  3082 }
  3083 
  3084 static int
  3085 frame_name_fnn_p (char *str, ptrdiff_t len)
  3086 {
  3087   if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
  3088     {
  3089       char *p = str + 2;
  3090       while ('0' <= *p && *p <= '9')
  3091         p++;
  3092       if (p == str + len)
  3093         return 1;
  3094     }
  3095   return 0;
  3096 }
  3097 
  3098 /* Set the name of the terminal frame.  Also used by MSDOS frames.
  3099    Modeled after *_set_name which is used for WINDOW frames.  */
  3100 
  3101 static void
  3102 set_term_frame_name (struct frame *f, Lisp_Object name)
  3103 {
  3104   f->explicit_name = ! NILP (name);
  3105 
  3106   /* If NAME is nil, set the name to F<num>.  */
  3107   if (NILP (name))
  3108     {
  3109       char namebuf[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)];
  3110 
  3111       /* Check for no change needed in this very common case
  3112          before we do any consing.  */
  3113       if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
  3114         return;
  3115 
  3116       name = make_formatted_string (namebuf, "F%"PRIdMAX, ++tty_frame_count);
  3117     }
  3118   else
  3119     {
  3120       CHECK_STRING (name);
  3121 
  3122       /* Don't change the name if it's already NAME.  */
  3123       if (! NILP (Fstring_equal (name, f->name)))
  3124         return;
  3125 
  3126       /* Don't allow the user to set the frame name to F<num>, so it
  3127          doesn't clash with the names we generate for terminal frames.  */
  3128       if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
  3129         error ("Frame names of the form F<num> are usurped by Emacs");
  3130     }
  3131 
  3132   fset_name (f, name);
  3133   update_mode_lines = 16;
  3134 }
  3135 
  3136 void
  3137 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
  3138 {
  3139   register Lisp_Object old_alist_elt;
  3140 
  3141   if (EQ (prop, Qminibuffer))
  3142     {
  3143       if (WINDOWP (val))
  3144         {
  3145           if (!MINI_WINDOW_P (XWINDOW (val)))
  3146             error ("The `minibuffer' parameter does not specify a valid minibuffer window");
  3147           else if (FRAME_MINIBUF_ONLY_P (f))
  3148             {
  3149               if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
  3150                 val = Qonly;
  3151               else
  3152                 error ("Can't change the minibuffer window of a minibuffer-only frame");
  3153             }
  3154           else if (FRAME_HAS_MINIBUF_P (f))
  3155             {
  3156               if (EQ (val, FRAME_MINIBUF_WINDOW (f)))
  3157                 val = Qt;
  3158               else
  3159                 error ("Can't change the minibuffer window of a frame with its own minibuffer");
  3160             }
  3161           else
  3162             /* Store the chosen minibuffer window.  */
  3163             fset_minibuffer_window (f, val);
  3164         }
  3165       else
  3166         {
  3167           Lisp_Object old_val = Fcdr (Fassq (Qminibuffer, f->param_alist));
  3168 
  3169           if (!NILP (old_val))
  3170             {
  3171               if (WINDOWP (old_val) && NILP (val))
  3172                 /* Don't change the value for a minibuffer-less frame if
  3173                    only nil was specified as new value.  */
  3174                 val = old_val;
  3175               else if (!EQ (old_val, val))
  3176                 error ("Can't change the `minibuffer' parameter of this frame");
  3177             }
  3178         }
  3179     }
  3180 
  3181   /* Check each parent-frame and delete-before parameter for a
  3182      circular dependency.  Do not check between parameters, so you can
  3183      still create circular dependencies with different properties, for
  3184      example a chain of frames F1->F2->...Fn such that F1 is an ancestor
  3185      frame of Fn and thus cannot be deleted before Fn and a second chain
  3186      Fn->Fn-1->...F1 such that Fn cannot be deleted before F1.  */
  3187   else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
  3188     {
  3189       Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
  3190 
  3191       if (!EQ (oldval, val) && !NILP (val))
  3192         {
  3193           Lisp_Object frame;
  3194           Lisp_Object frame1 = val;
  3195 
  3196           if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
  3197             error ("Invalid `%s' frame parameter",
  3198                    SSDATA (SYMBOL_NAME (prop)));
  3199 
  3200           XSETFRAME (frame, f);
  3201 
  3202           while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
  3203             if (EQ (frame1, frame))
  3204               error ("Circular specification of `%s' frame parameter",
  3205                      SSDATA (SYMBOL_NAME (prop)));
  3206             else
  3207               frame1 = get_frame_param (XFRAME (frame1), prop);
  3208         }
  3209     }
  3210 
  3211   /* The buffer-list parameters are stored in a special place and not
  3212      in the alist.  All buffers must be live.  */
  3213   else if (EQ (prop, Qbuffer_list))
  3214     {
  3215       Lisp_Object list = Qnil;
  3216       for (; CONSP (val); val = XCDR (val))
  3217         if (!NILP (Fbuffer_live_p (XCAR (val))))
  3218           list = Fcons (XCAR (val), list);
  3219       fset_buffer_list (f, Fnreverse (list));
  3220       return;
  3221     }
  3222   else if (EQ (prop, Qburied_buffer_list))
  3223     {
  3224       Lisp_Object list = Qnil;
  3225       for (; CONSP (val); val = XCDR (val))
  3226         if (!NILP (Fbuffer_live_p (XCAR (val))))
  3227           list = Fcons (XCAR (val), list);
  3228       fset_buried_buffer_list (f, Fnreverse (list));
  3229       return;
  3230     }
  3231   else if ((EQ (prop, Qscroll_bar_width) || EQ (prop, Qscroll_bar_height))
  3232            && !NILP (val) && !RANGED_FIXNUMP (1, val, INT_MAX))
  3233     {
  3234       Lisp_Object old_val = Fcdr (Fassq (prop, f->param_alist));
  3235 
  3236       val = old_val;
  3237     }
  3238 
  3239   /* The tty color needed to be set before the frame's parameter
  3240      alist was updated with the new value.  This is not true any more,
  3241      but we still do this test early on.  */
  3242   if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
  3243       && f == FRAME_TTY (f)->previous_frame)
  3244     /* Force redisplay of this tty.  */
  3245     FRAME_TTY (f)->previous_frame = NULL;
  3246 
  3247   /* Update the frame parameter alist.  */
  3248   old_alist_elt = Fassq (prop, f->param_alist);
  3249   if (NILP (old_alist_elt))
  3250     fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
  3251   else
  3252     Fsetcdr (old_alist_elt, val);
  3253 
  3254   /* Update some other special parameters in their special places
  3255      in addition to the alist.  */
  3256 
  3257   if (EQ (prop, Qbuffer_predicate))
  3258     fset_buffer_predicate (f, val);
  3259 
  3260   if (! FRAME_WINDOW_P (f))
  3261     {
  3262       if (EQ (prop, Qmenu_bar_lines))
  3263         set_menu_bar_lines (f, val, make_fixnum (FRAME_MENU_BAR_LINES (f)));
  3264       else if (EQ (prop, Qtab_bar_lines))
  3265         set_tab_bar_lines (f, val, make_fixnum (FRAME_TAB_BAR_LINES (f)));
  3266       else if (EQ (prop, Qname))
  3267         set_term_frame_name (f, val);
  3268     }
  3269 }
  3270 
  3271 /* Return color matches UNSPEC on frame F or nil if UNSPEC
  3272    is not an unspecified foreground or background color.  */
  3273 
  3274 static Lisp_Object
  3275 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
  3276 {
  3277   return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
  3278           ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
  3279           : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
  3280              ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
  3281 }
  3282 
  3283 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
  3284        doc: /* Return the parameters-alist of frame FRAME.
  3285 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
  3286 The meaningful PARMs depend on the kind of frame.
  3287 If FRAME is omitted or nil, return information on the currently selected frame.  */)
  3288   (Lisp_Object frame)
  3289 {
  3290   Lisp_Object alist;
  3291   struct frame *f = decode_any_frame (frame);
  3292   int height, width;
  3293 
  3294   if (!FRAME_LIVE_P (f))
  3295     return Qnil;
  3296 
  3297   alist = Fcopy_alist (f->param_alist);
  3298 
  3299   if (!FRAME_WINDOW_P (f))
  3300     {
  3301       Lisp_Object elt;
  3302 
  3303       /* If the frame's parameter alist says the colors are
  3304          unspecified and reversed, take the frame's background pixel
  3305          for foreground and vice versa.  */
  3306       elt = Fassq (Qforeground_color, alist);
  3307       if (CONSP (elt) && STRINGP (XCDR (elt)))
  3308         {
  3309           elt = frame_unspecified_color (f, XCDR (elt));
  3310           if (!NILP (elt))
  3311             store_in_alist (&alist, Qforeground_color, elt);
  3312         }
  3313       else
  3314         store_in_alist (&alist, Qforeground_color,
  3315                         tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
  3316       elt = Fassq (Qbackground_color, alist);
  3317       if (CONSP (elt) && STRINGP (XCDR (elt)))
  3318         {
  3319           elt = frame_unspecified_color (f, XCDR (elt));
  3320           if (!NILP (elt))
  3321             store_in_alist (&alist, Qbackground_color, elt);
  3322         }
  3323       else
  3324         store_in_alist (&alist, Qbackground_color,
  3325                         tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
  3326       store_in_alist (&alist, Qfont,
  3327                       build_string (FRAME_MSDOS_P (f)
  3328                                     ? "ms-dos"
  3329                                     : FRAME_W32_P (f) ? "w32term"
  3330                                     :"tty"));
  3331     }
  3332 
  3333   store_in_alist (&alist, Qname, f->name);
  3334   /* It's questionable whether here we should report the value of
  3335      f->new_height (and f->new_width below) but we've done that in the
  3336      past, so let's keep it.  Note that a value of -1 for either of
  3337      these means that no new size was requested.
  3338 
  3339      But check f->new_size before to make sure that f->new_height and
  3340      f->new_width are not ones requested by adjust_frame_size.  */
  3341   height = ((f->new_size_p && f->new_height >= 0)
  3342             ? f->new_height / FRAME_LINE_HEIGHT (f)
  3343             : FRAME_LINES (f));
  3344   store_in_alist (&alist, Qheight, make_fixnum (height));
  3345   width = ((f->new_size_p && f->new_width >= 0)
  3346            ? f->new_width / FRAME_COLUMN_WIDTH (f)
  3347            : FRAME_COLS(f));
  3348   store_in_alist (&alist, Qwidth, make_fixnum (width));
  3349 
  3350   store_in_alist (&alist, Qmodeline, FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil);
  3351   store_in_alist (&alist, Qunsplittable, FRAME_NO_SPLIT_P (f) ? Qt : Qnil);
  3352   store_in_alist (&alist, Qbuffer_list, f->buffer_list);
  3353   store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
  3354 
  3355   /* I think this should be done with a hook.  */
  3356 #ifdef HAVE_WINDOW_SYSTEM
  3357   if (FRAME_WINDOW_P (f))
  3358     gui_report_frame_params (f, &alist);
  3359   else
  3360 #endif
  3361     {
  3362       /* This ought to be correct in f->param_alist for an X frame.  */
  3363       Lisp_Object lines;
  3364 
  3365       XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
  3366       store_in_alist (&alist, Qmenu_bar_lines, lines);
  3367       XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f));
  3368       store_in_alist (&alist, Qtab_bar_lines, lines);
  3369     }
  3370 
  3371   return alist;
  3372 }
  3373 
  3374 
  3375 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
  3376        doc: /* Return FRAME's value for parameter PARAMETER.
  3377 If FRAME is nil, describe the currently selected frame.  */)
  3378   (Lisp_Object frame, Lisp_Object parameter)
  3379 {
  3380   struct frame *f = decode_any_frame (frame);
  3381   Lisp_Object value = Qnil;
  3382 
  3383   CHECK_SYMBOL (parameter);
  3384 
  3385   XSETFRAME (frame, f);
  3386 
  3387   if (FRAME_LIVE_P (f))
  3388     {
  3389       /* Avoid consing in frequent cases.  */
  3390       if (EQ (parameter, Qname))
  3391         value = f->name;
  3392 #ifdef HAVE_WINDOW_SYSTEM
  3393       /* These are used by vertical motion commands.  */
  3394       else if (EQ (parameter, Qvertical_scroll_bars))
  3395         value = (f->vertical_scroll_bar_type == vertical_scroll_bar_none
  3396                  ? Qnil
  3397                  : (f->vertical_scroll_bar_type == vertical_scroll_bar_left
  3398                     ? Qleft : Qright));
  3399       else if (EQ (parameter, Qhorizontal_scroll_bars))
  3400         value = f->horizontal_scroll_bars ? Qt : Qnil;
  3401       else if (EQ (parameter, Qline_spacing) && f->extra_line_spacing == 0)
  3402         /* If this is non-zero, we can't determine whether the user specified
  3403            an integer or float value without looking through 'param_alist'.  */
  3404         value = make_fixnum (0);
  3405       else if (EQ (parameter, Qfont) && FRAME_X_P (f))
  3406         value = FRAME_FONT (f)->props[FONT_NAME_INDEX];
  3407 #endif /* HAVE_WINDOW_SYSTEM */
  3408 #ifdef HAVE_X_WINDOWS
  3409       else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
  3410         value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
  3411 #endif /* HAVE_X_WINDOWS */
  3412       else if (EQ (parameter, Qbackground_color)
  3413                || EQ (parameter, Qforeground_color))
  3414         {
  3415           value = Fassq (parameter, f->param_alist);
  3416           if (CONSP (value))
  3417             {
  3418               value = XCDR (value);
  3419               /* Fframe_parameters puts the actual fg/bg color names,
  3420                  even if f->param_alist says otherwise.  This is
  3421                  important when param_alist's notion of colors is
  3422                  "unspecified".  We need to do the same here.  */
  3423               if (STRINGP (value) && !FRAME_WINDOW_P (f))
  3424                 {
  3425                   Lisp_Object tem = frame_unspecified_color (f, value);
  3426 
  3427                   if (!NILP (tem))
  3428                     value = tem;
  3429                 }
  3430             }
  3431           else
  3432             value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
  3433         }
  3434       else if (EQ (parameter, Qdisplay_type)
  3435                || EQ (parameter, Qbackground_mode))
  3436         value = Fcdr (Fassq (parameter, f->param_alist));
  3437       else
  3438         /* FIXME: Avoid this code path at all (as well as code duplication)
  3439            by sharing more code with Fframe_parameters.  */
  3440         value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
  3441     }
  3442 
  3443   return value;
  3444 }
  3445 
  3446 
  3447 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
  3448        Smodify_frame_parameters, 2, 2, 0,
  3449        doc: /* Modify FRAME according to new values of its parameters in ALIST.
  3450 If FRAME is nil, it defaults to the selected frame.
  3451 ALIST is an alist of parameters to change and their new values.
  3452 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
  3453 Which PARMs are meaningful depends on the kind of frame.
  3454 The meaningful parameters are acted upon, i.e. the frame is changed
  3455 according to their new values, and are also stored in the frame's
  3456 parameter list so that `frame-parameters' will return them.
  3457 PARMs that are not meaningful are still stored in the frame's parameter
  3458 list, but are otherwise ignored.  */)
  3459   (Lisp_Object frame, Lisp_Object alist)
  3460 {
  3461   struct frame *f = decode_live_frame (frame);
  3462   Lisp_Object prop, val;
  3463 
  3464   /* I think this should be done with a hook.  */
  3465 #ifdef HAVE_WINDOW_SYSTEM
  3466   if (FRAME_WINDOW_P (f))
  3467     gui_set_frame_parameters (f, alist);
  3468   else
  3469 #endif
  3470 #ifdef MSDOS
  3471   if (FRAME_MSDOS_P (f))
  3472     IT_set_frame_parameters (f, alist);
  3473   else
  3474 #endif
  3475 
  3476     {
  3477       EMACS_INT length = list_length (alist);
  3478       ptrdiff_t i;
  3479       Lisp_Object *parms;
  3480       Lisp_Object *values;
  3481       USE_SAFE_ALLOCA;
  3482       SAFE_ALLOCA_LISP (parms, 2 * length);
  3483       values = parms + length;
  3484 
  3485       /* Extract parm names and values into those vectors.  */
  3486 
  3487       for (i = 0; CONSP (alist); alist = XCDR (alist))
  3488         {
  3489           Lisp_Object elt;
  3490 
  3491           elt = XCAR (alist);
  3492           parms[i] = Fcar (elt);
  3493           values[i] = Fcdr (elt);
  3494           i++;
  3495         }
  3496 
  3497       /* Now process them in reverse of specified order.  */
  3498       while (--i >= 0)
  3499         {
  3500           prop = parms[i];
  3501           val = values[i];
  3502           store_frame_param (f, prop, val);
  3503 
  3504           if (EQ (prop, Qforeground_color)
  3505               || EQ (prop, Qbackground_color))
  3506             update_face_from_frame_parameter (f, prop, val);
  3507         }
  3508 
  3509       SAFE_FREE ();
  3510     }
  3511   return Qnil;
  3512 }
  3513 
  3514 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
  3515        0, 1, 0,
  3516        doc: /* Height in pixels of a line in the font in frame FRAME.
  3517 If FRAME is omitted or nil, the selected frame is used.
  3518 For a terminal frame, the value is always 1.  */)
  3519   (Lisp_Object frame)
  3520 {
  3521 #ifdef HAVE_WINDOW_SYSTEM
  3522   struct frame *f = decode_any_frame (frame);
  3523 
  3524   if (FRAME_WINDOW_P (f))
  3525     return make_fixnum (FRAME_LINE_HEIGHT (f));
  3526   else
  3527 #endif
  3528     return make_fixnum (1);
  3529 }
  3530 
  3531 
  3532 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
  3533        0, 1, 0,
  3534        doc: /* Width in pixels of characters in the font in frame FRAME.
  3535 If FRAME is omitted or nil, the selected frame is used.
  3536 On a graphical screen, the width is the standard width of the default font.
  3537 For a terminal screen, the value is always 1.  */)
  3538   (Lisp_Object frame)
  3539 {
  3540 #ifdef HAVE_WINDOW_SYSTEM
  3541   struct frame *f = decode_any_frame (frame);
  3542 
  3543   if (FRAME_WINDOW_P (f))
  3544     return make_fixnum (FRAME_COLUMN_WIDTH (f));
  3545   else
  3546 #endif
  3547     return make_fixnum (1);
  3548 }
  3549 
  3550 DEFUN ("frame-native-width", Fframe_native_width,
  3551        Sframe_native_width, 0, 1, 0,
  3552        doc: /* Return FRAME's native width in pixels.
  3553 For a terminal frame, the result really gives the width in characters.
  3554 If FRAME is omitted or nil, the selected frame is used.
  3555 
  3556 If you're interested only in the width of the text portion of the
  3557 frame, see `frame-text-width' instead.  */)
  3558   (Lisp_Object frame)
  3559 {
  3560   struct frame *f = decode_any_frame (frame);
  3561 
  3562 #ifdef HAVE_WINDOW_SYSTEM
  3563   if (FRAME_WINDOW_P (f))
  3564     return make_fixnum (FRAME_PIXEL_WIDTH (f));
  3565   else
  3566 #endif
  3567     return make_fixnum (FRAME_TOTAL_COLS (f));
  3568 }
  3569 
  3570 DEFUN ("frame-native-height", Fframe_native_height,
  3571        Sframe_native_height, 0, 1, 0,
  3572        doc: /* Return FRAME's native height in pixels.
  3573 If FRAME is omitted or nil, the selected frame is used.  The exact value
  3574 of the result depends on the window-system and toolkit in use:
  3575 
  3576 In the Gtk+ and NS versions, it includes only any window (including the
  3577 minibuffer or echo area), mode line, and header line.  It does not
  3578 include the tool bar or menu bar.  With other graphical versions, it may
  3579 also include the tool bar and the menu bar.
  3580 
  3581 If you're interested only in the height of the text portion of the
  3582 frame, see `frame-text-height' instead.
  3583 
  3584 For a text terminal, it includes the menu bar.  In this case, the
  3585 result is really in characters rather than pixels (i.e., is identical
  3586 to `frame-height'). */)
  3587   (Lisp_Object frame)
  3588 {
  3589   struct frame *f = decode_any_frame (frame);
  3590 
  3591 #ifdef HAVE_WINDOW_SYSTEM
  3592   if (FRAME_WINDOW_P (f))
  3593     return make_fixnum (FRAME_PIXEL_HEIGHT (f));
  3594   else
  3595 #endif
  3596     return make_fixnum (FRAME_TOTAL_LINES (f));
  3597 }
  3598 
  3599 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
  3600        Stool_bar_pixel_width, 0, 1, 0,
  3601        doc: /* Return width in pixels of FRAME's tool bar.
  3602 The result is greater than zero only when the tool bar is on the left
  3603 or right side of FRAME.  If FRAME is omitted or nil, the selected frame
  3604 is used.  */)
  3605   (Lisp_Object frame)
  3606 {
  3607 #ifdef FRAME_TOOLBAR_WIDTH
  3608   struct frame *f = decode_any_frame (frame);
  3609 
  3610   if (FRAME_WINDOW_P (f))
  3611     return make_fixnum (FRAME_TOOLBAR_WIDTH (f));
  3612 #endif
  3613   return make_fixnum (0);
  3614 }
  3615 
  3616 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
  3617        doc: /* Return width in columns of FRAME's text area.  */)
  3618   (Lisp_Object frame)
  3619 {
  3620   return make_fixnum (FRAME_COLS (decode_any_frame (frame)));
  3621 }
  3622 
  3623 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
  3624        doc: /* Return height in lines of FRAME's text area.  */)
  3625   (Lisp_Object frame)
  3626 {
  3627   return make_fixnum (FRAME_LINES (decode_any_frame (frame)));
  3628 }
  3629 
  3630 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
  3631        doc: /* Return number of total columns of FRAME.  */)
  3632   (Lisp_Object frame)
  3633 {
  3634   return make_fixnum (FRAME_TOTAL_COLS (decode_any_frame (frame)));
  3635 }
  3636 
  3637 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
  3638        doc: /* Return number of total lines of FRAME.  */)
  3639   (Lisp_Object frame)
  3640 {
  3641   return make_fixnum (FRAME_TOTAL_LINES (decode_any_frame (frame)));
  3642 }
  3643 
  3644 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
  3645        doc: /* Return text area width of FRAME in pixels.  */)
  3646   (Lisp_Object frame)
  3647 {
  3648   return make_fixnum (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
  3649 }
  3650 
  3651 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
  3652        doc: /* Return text area height of FRAME in pixels.  */)
  3653   (Lisp_Object frame)
  3654 {
  3655   return make_fixnum (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
  3656 }
  3657 
  3658 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
  3659        doc: /* Return scroll bar width of FRAME in pixels.  */)
  3660   (Lisp_Object frame)
  3661 {
  3662   return make_fixnum (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
  3663 }
  3664 
  3665 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
  3666        doc: /* Return scroll bar height of FRAME in pixels.  */)
  3667   (Lisp_Object frame)
  3668 {
  3669   return make_fixnum (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
  3670 }
  3671 
  3672 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
  3673        doc: /* Return fringe width of FRAME in pixels.  */)
  3674   (Lisp_Object frame)
  3675 {
  3676   return make_fixnum (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
  3677 }
  3678 
  3679 DEFUN ("frame-child-frame-border-width", Fframe_child_frame_border_width, Sframe_child_frame_border_width, 0, 1, 0,
  3680        doc: /* Return width of FRAME's child-frame border in pixels.
  3681  If FRAME's `child-frame-border-width' parameter is nil, return FRAME's
  3682  internal border width instead.  */)
  3683   (Lisp_Object frame)
  3684 {
  3685   int width = FRAME_CHILD_FRAME_BORDER_WIDTH (decode_any_frame (frame));
  3686 
  3687   if (width < 0)
  3688     return make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
  3689   else
  3690     return make_fixnum (FRAME_CHILD_FRAME_BORDER_WIDTH (decode_any_frame (frame)));
  3691 }
  3692 
  3693 DEFUN ("frame-internal-border-width", Fframe_internal_border_width, Sframe_internal_border_width, 0, 1, 0,
  3694        doc: /* Return width of FRAME's internal border in pixels.  */)
  3695   (Lisp_Object frame)
  3696 {
  3697   return make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
  3698 }
  3699 
  3700 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
  3701        doc: /* Return width (in pixels) of vertical window dividers on FRAME.  */)
  3702   (Lisp_Object frame)
  3703 {
  3704   return make_fixnum (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
  3705 }
  3706 
  3707 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
  3708        doc: /* Return width (in pixels) of horizontal window dividers on FRAME.  */)
  3709   (Lisp_Object frame)
  3710 {
  3711   return make_fixnum (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
  3712 }
  3713 
  3714 static int
  3715 check_frame_pixels (Lisp_Object size, Lisp_Object pixelwise, int item_size)
  3716 {
  3717   intmax_t sz;
  3718   int pixel_size; /* size * item_size */
  3719 
  3720   CHECK_INTEGER (size);
  3721   if (!NILP (pixelwise))
  3722     item_size = 1;
  3723 
  3724   if (!integer_to_intmax (size, &sz)
  3725       || INT_MULTIPLY_WRAPV (sz, item_size, &pixel_size))
  3726     args_out_of_range_3 (size, make_int (INT_MIN / item_size),
  3727                          make_int (INT_MAX / item_size));
  3728 
  3729   return pixel_size;
  3730 }
  3731 
  3732 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4,
  3733        "(set-frame-property--interactive \"Frame height: \" (frame-height))",
  3734        doc: /* Set text height of frame FRAME to HEIGHT lines.
  3735 Optional third arg PRETEND non-nil means that redisplay should use
  3736 HEIGHT lines but that the idea of the actual height of the frame should
  3737 not be changed.
  3738 
  3739 Optional fourth argument PIXELWISE non-nil means that FRAME should be
  3740 HEIGHT pixels high.  Note: When `frame-resize-pixelwise' is nil, some
  3741 window managers may refuse to honor a HEIGHT that is not an integer
  3742 multiple of the default frame font height.
  3743 
  3744 When called interactively, HEIGHT is the numeric prefix and the
  3745 currently selected frame will be set to this height.
  3746 
  3747 If FRAME is nil, it defaults to the selected frame.  */)
  3748   (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
  3749 {
  3750   struct frame *f = decode_live_frame (frame);
  3751   int text_height
  3752     = check_frame_pixels (height, pixelwise, FRAME_LINE_HEIGHT (f));
  3753 
  3754   /* With INHIBIT 1 pass correct text width to adjust_frame_size.  */
  3755   adjust_frame_size
  3756     (f, FRAME_TEXT_WIDTH (f), text_height, 1, !NILP (pretend), Qheight);
  3757 
  3758   return Qnil;
  3759 }
  3760 
  3761 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4,
  3762        "(set-frame-property--interactive \"Frame width: \" (frame-width))",
  3763        doc: /* Set text width of frame FRAME to WIDTH columns.
  3764 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
  3765 columns but that the idea of the actual width of the frame should not
  3766 be changed.
  3767 
  3768 Optional fourth argument PIXELWISE non-nil means that FRAME should be
  3769 WIDTH pixels wide.  Note: When `frame-resize-pixelwise' is nil, some
  3770 window managers may refuse to honor a WIDTH that is not an integer
  3771 multiple of the default frame font width.
  3772 
  3773 When called interactively, WIDTH is the numeric prefix and the
  3774 currently selected frame will be set to this width.
  3775 
  3776 If FRAME is nil, it defaults to the selected frame.  */)
  3777   (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
  3778 {
  3779   struct frame *f = decode_live_frame (frame);
  3780   int text_width
  3781     = check_frame_pixels (width, pixelwise, FRAME_COLUMN_WIDTH (f));
  3782 
  3783   /* With INHIBIT 1 pass correct text height to adjust_frame_size.  */
  3784   adjust_frame_size
  3785     (f, text_width, FRAME_TEXT_HEIGHT (f), 1, !NILP (pretend), Qwidth);
  3786 
  3787   return Qnil;
  3788 }
  3789 
  3790 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
  3791        doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
  3792 Optional argument PIXELWISE non-nil means to measure in pixels.  Note:
  3793 When `frame-resize-pixelwise' is nil, some window managers may refuse to
  3794 honor a WIDTH that is not an integer multiple of the default frame font
  3795 width or a HEIGHT that is not an integer multiple of the default frame
  3796 font height.
  3797 
  3798 If FRAME is nil, it defaults to the selected frame.  */)
  3799   (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
  3800 {
  3801   struct frame *f = decode_live_frame (frame);
  3802   int text_width
  3803     = check_frame_pixels (width, pixelwise, FRAME_COLUMN_WIDTH (f));
  3804   int text_height
  3805     = check_frame_pixels (height, pixelwise, FRAME_LINE_HEIGHT (f));
  3806 
  3807   /* PRETEND is always false here.  */
  3808   adjust_frame_size (f, text_width, text_height, 1, false, Qsize);
  3809 
  3810   return Qnil;
  3811 }
  3812 
  3813 DEFUN ("frame-position", Fframe_position,
  3814        Sframe_position, 0, 1, 0,
  3815        doc: /* Return top left corner of FRAME in pixels.
  3816 FRAME must be a live frame and defaults to the selected one.  The return
  3817 value is a cons (x, y) of the coordinates of the top left corner of
  3818 FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
  3819 display.
  3820 
  3821 Note that the values returned are not guaranteed to be accurate: The
  3822 values depend on the underlying window system, and some systems add a
  3823 constant offset to the values.  */)
  3824      (Lisp_Object frame)
  3825 {
  3826   register struct frame *f = decode_live_frame (frame);
  3827 
  3828   return Fcons (make_fixnum (f->left_pos), make_fixnum (f->top_pos));
  3829 }
  3830 
  3831 DEFUN ("set-frame-position", Fset_frame_position,
  3832        Sset_frame_position, 3, 3, 0,
  3833        doc: /* Set position of FRAME to (X, Y).
  3834 FRAME must be a live frame and defaults to the selected one.  X and Y,
  3835 if positive, specify the coordinate of the left and top edge of FRAME's
  3836 outer frame in pixels relative to an origin (0, 0) of FRAME's display.
  3837 If any of X or Y is negative, it specifies the coordinates of the right
  3838 or bottom edge of the outer frame of FRAME relative to the right or
  3839 bottom edge of FRAME's display.  */)
  3840   (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
  3841 {
  3842   struct frame *f = decode_live_frame (frame);
  3843   int xval = check_integer_range (x, INT_MIN, INT_MAX);
  3844   int yval = check_integer_range (y, INT_MIN, INT_MAX);
  3845 
  3846   if (FRAME_WINDOW_P (f))
  3847     {
  3848 #ifdef HAVE_WINDOW_SYSTEM
  3849       if (FRAME_TERMINAL (f)->set_frame_offset_hook)
  3850         FRAME_TERMINAL (f)->set_frame_offset_hook (f, xval, yval, 1);
  3851 #else
  3852       (void) xval;
  3853       (void) yval;
  3854 #endif
  3855     }
  3856 
  3857   return Qt;
  3858 }
  3859 
  3860 DEFUN ("frame-window-state-change", Fframe_window_state_change,
  3861        Sframe_window_state_change, 0, 1, 0,
  3862        doc: /* Return t if FRAME's window state change flag is set, nil otherwise.
  3863 FRAME must be a live frame and defaults to the selected one.
  3864 
  3865 If FRAME's window state change flag is set, the default values of
  3866 `window-state-change-functions' and `window-state-change-hook' will be
  3867 run during next redisplay, regardless of whether a window state change
  3868 actually occurred on FRAME or not.  After that, the value of this flag
  3869 is reset.  */)
  3870      (Lisp_Object frame)
  3871 {
  3872   return FRAME_WINDOW_STATE_CHANGE (decode_live_frame (frame)) ? Qt : Qnil;
  3873 }
  3874 
  3875 DEFUN ("set-frame-window-state-change", Fset_frame_window_state_change,
  3876        Sset_frame_window_state_change, 0, 2, 0,
  3877        doc: /* Set FRAME's window state change flag according to ARG.
  3878 Set FRAME's window state change flag if ARG is non-nil, reset it
  3879 otherwise.
  3880 
  3881 If FRAME's window state change flag is set, the default values of
  3882 `window-state-change-functions' and `window-state-change-hook' will be
  3883 run during next redisplay, regardless of whether a window state change
  3884 actually occurred on FRAME or not.  After that, the value of FRAME's
  3885 window state change flag is reset.  */)
  3886      (Lisp_Object frame, Lisp_Object arg)
  3887 {
  3888   struct frame *f = decode_live_frame (frame);
  3889 
  3890   return (FRAME_WINDOW_STATE_CHANGE (f) = !NILP (arg)) ? Qt : Qnil;
  3891 }
  3892 
  3893 DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
  3894        0, 1, 0,
  3895        doc: /* Return FRAMEs scale factor.
  3896 If FRAME is omitted or nil, the selected frame is used.
  3897 The scale factor is the amount by which a logical pixel size must be
  3898 multiplied to find the real number of pixels.  */)
  3899      (Lisp_Object frame)
  3900 {
  3901   struct frame *f = decode_live_frame (frame);
  3902 
  3903   return (make_float (f ? FRAME_SCALE_FACTOR (f) : 1));
  3904 }
  3905 
  3906 /***********************************************************************
  3907                                 Frame Parameters
  3908  ***********************************************************************/
  3909 
  3910 /* Connect the frame-parameter names for frames to the ways of passing
  3911    the parameter values to the window system.
  3912 
  3913    The name of a parameter, as a Lisp symbol, has a
  3914    `frame-parameter-pos' property which is an integer in Lisp that is
  3915    an index in this table.  */
  3916 
  3917 struct frame_parm_table {
  3918   const char *name;
  3919   int sym;
  3920 };
  3921 
  3922 static const struct frame_parm_table frame_parms[] =
  3923 {
  3924   {"auto-raise",                SYMBOL_INDEX (Qauto_raise)},
  3925   {"auto-lower",                SYMBOL_INDEX (Qauto_lower)},
  3926   {"background-color",          -1},
  3927   {"border-color",              SYMBOL_INDEX (Qborder_color)},
  3928   {"border-width",              SYMBOL_INDEX (Qborder_width)},
  3929   {"cursor-color",              SYMBOL_INDEX (Qcursor_color)},
  3930   {"cursor-type",               SYMBOL_INDEX (Qcursor_type)},
  3931   {"font",                      -1},
  3932   {"foreground-color",          -1},
  3933   {"icon-name",                 SYMBOL_INDEX (Qicon_name)},
  3934   {"icon-type",                 SYMBOL_INDEX (Qicon_type)},
  3935   {"child-frame-border-width",  SYMBOL_INDEX (Qchild_frame_border_width)},
  3936   {"internal-border-width",     SYMBOL_INDEX (Qinternal_border_width)},
  3937   {"right-divider-width",       SYMBOL_INDEX (Qright_divider_width)},
  3938   {"bottom-divider-width",      SYMBOL_INDEX (Qbottom_divider_width)},
  3939   {"menu-bar-lines",            SYMBOL_INDEX (Qmenu_bar_lines)},
  3940   {"mouse-color",               SYMBOL_INDEX (Qmouse_color)},
  3941   {"name",                      SYMBOL_INDEX (Qname)},
  3942   {"scroll-bar-width",          SYMBOL_INDEX (Qscroll_bar_width)},
  3943   {"scroll-bar-height",         SYMBOL_INDEX (Qscroll_bar_height)},
  3944   {"title",                     SYMBOL_INDEX (Qtitle)},
  3945   {"unsplittable",              SYMBOL_INDEX (Qunsplittable)},
  3946   {"vertical-scroll-bars",      SYMBOL_INDEX (Qvertical_scroll_bars)},
  3947   {"horizontal-scroll-bars",    SYMBOL_INDEX (Qhorizontal_scroll_bars)},
  3948   {"visibility",                SYMBOL_INDEX (Qvisibility)},
  3949   {"tab-bar-lines",             SYMBOL_INDEX (Qtab_bar_lines)},
  3950   {"tool-bar-lines",            SYMBOL_INDEX (Qtool_bar_lines)},
  3951   {"scroll-bar-foreground",     SYMBOL_INDEX (Qscroll_bar_foreground)},
  3952   {"scroll-bar-background",     SYMBOL_INDEX (Qscroll_bar_background)},
  3953   {"screen-gamma",              SYMBOL_INDEX (Qscreen_gamma)},
  3954   {"line-spacing",              SYMBOL_INDEX (Qline_spacing)},
  3955   {"left-fringe",               SYMBOL_INDEX (Qleft_fringe)},
  3956   {"right-fringe",              SYMBOL_INDEX (Qright_fringe)},
  3957   {"wait-for-wm",               SYMBOL_INDEX (Qwait_for_wm)},
  3958   {"fullscreen",                SYMBOL_INDEX (Qfullscreen)},
  3959   {"font-backend",              SYMBOL_INDEX (Qfont_backend)},
  3960   {"alpha",                     SYMBOL_INDEX (Qalpha)},
  3961   {"sticky",                    SYMBOL_INDEX (Qsticky)},
  3962   {"tool-bar-position",         SYMBOL_INDEX (Qtool_bar_position)},
  3963   {"inhibit-double-buffering",  SYMBOL_INDEX (Qinhibit_double_buffering)},
  3964   {"undecorated",               SYMBOL_INDEX (Qundecorated)},
  3965   {"parent-frame",              SYMBOL_INDEX (Qparent_frame)},
  3966   {"skip-taskbar",              SYMBOL_INDEX (Qskip_taskbar)},
  3967   {"no-focus-on-map",           SYMBOL_INDEX (Qno_focus_on_map)},
  3968   {"no-accept-focus",           SYMBOL_INDEX (Qno_accept_focus)},
  3969   {"z-group",                   SYMBOL_INDEX (Qz_group)},
  3970   {"override-redirect",         SYMBOL_INDEX (Qoverride_redirect)},
  3971   {"no-special-glyphs",         SYMBOL_INDEX (Qno_special_glyphs)},
  3972   {"alpha-background",          SYMBOL_INDEX (Qalpha_background)},
  3973   {"use-frame-synchronization", SYMBOL_INDEX (Quse_frame_synchronization)},
  3974 #ifdef HAVE_X_WINDOWS
  3975   {"shaded",                    SYMBOL_INDEX (Qshaded)},
  3976 #endif
  3977 #ifdef NS_IMPL_COCOA
  3978   {"ns-appearance",             SYMBOL_INDEX (Qns_appearance)},
  3979   {"ns-transparent-titlebar",   SYMBOL_INDEX (Qns_transparent_titlebar)},
  3980 #endif
  3981 };
  3982 
  3983 #ifdef HAVE_WINDOW_SYSTEM
  3984 
  3985 /* Enumeration type for switch in frame_float.  */
  3986 enum frame_float_type
  3987 {
  3988  FRAME_FLOAT_WIDTH,
  3989  FRAME_FLOAT_HEIGHT,
  3990  FRAME_FLOAT_LEFT,
  3991  FRAME_FLOAT_TOP
  3992 };
  3993 
  3994 /**
  3995  * frame_float:
  3996  *
  3997  * Process the value VAL of the float type frame parameter 'width',
  3998  * 'height', 'left', or 'top' specified via a frame_float_type
  3999  * enumeration type WHAT for frame F.  Such parameters relate the outer
  4000  * size or position of F to the size of the F's display or parent frame
  4001  * which have to be both available in some way.
  4002  *
  4003  * The return value is a size or position value in pixels.  VAL must be
  4004  * in the range 0.0 to 1.0 where a width/height of 0.0 means to return 0
  4005  * and 1.0 means to return the full width/height of the display/parent.
  4006  * For positions, 0.0 means position in the left/top corner of the
  4007  * display/parent while 1.0 means to position at the right/bottom corner
  4008  * of the display/parent frame.
  4009  *
  4010  * Set PARENT_DONE and OUTER_DONE to avoid recalculation of the outer
  4011  * size or parent or display attributes when more float parameters are
  4012  * calculated in a row: -1 means not processed yet, 0 means processing
  4013  * failed, 1 means processing succeeded.
  4014  *
  4015  * Return DEFAULT_VALUE when processing fails for whatever reason with
  4016  * one exception: When calculating F's outer edges fails (probably
  4017  * because F has not been created yet) return the difference between F's
  4018  * native and text size.
  4019  */
  4020 static int
  4021 frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
  4022              int *parent_done, int *outer_done, int default_value)
  4023 {
  4024   double d_val = XFLOAT_DATA (val);
  4025 
  4026   if (d_val < 0.0 || d_val > 1.0)
  4027     /* Invalid VAL.  */
  4028     return default_value;
  4029   else
  4030     {
  4031       static unsigned parent_width, parent_height;
  4032       static int parent_left, parent_top;
  4033       static unsigned outer_minus_text_width, outer_minus_text_height;
  4034       struct frame *p = FRAME_PARENT_FRAME (f);
  4035 
  4036       if (*parent_done == 1)
  4037         ;
  4038       else if (p)
  4039         {
  4040           parent_width = FRAME_PIXEL_WIDTH (p);
  4041           parent_height = FRAME_PIXEL_HEIGHT (p);
  4042           *parent_done = 1;
  4043         }
  4044       else
  4045         {
  4046           if (*parent_done == 0)
  4047             /* No workarea available.  */
  4048             return default_value;
  4049           else if (*parent_done == -1)
  4050             {
  4051               Lisp_Object monitor_attributes;
  4052               Lisp_Object workarea;
  4053               Lisp_Object frame;
  4054 
  4055               XSETFRAME (frame, f);
  4056               monitor_attributes = call1 (Qframe_monitor_attributes, frame);
  4057               if (NILP (monitor_attributes))
  4058                 {
  4059                   /* No monitor attributes available.  */
  4060                   *parent_done = 0;
  4061 
  4062                   return default_value;
  4063                 }
  4064 
  4065               workarea = Fcdr (Fassq (Qworkarea, monitor_attributes));
  4066               if (NILP (workarea))
  4067                 {
  4068                   /* No workarea available.  */
  4069                   *parent_done = 0;
  4070 
  4071                   return default_value;
  4072                 }
  4073 
  4074               /* Workarea available.  */
  4075               parent_left = XFIXNUM (Fnth (make_fixnum (0), workarea));
  4076               parent_top = XFIXNUM (Fnth (make_fixnum (1), workarea));
  4077               parent_width = XFIXNUM (Fnth (make_fixnum (2), workarea));
  4078               parent_height = XFIXNUM (Fnth (make_fixnum (3), workarea));
  4079               *parent_done = 1;
  4080             }
  4081         }
  4082 
  4083       if (*outer_done == 1)
  4084         ;
  4085       else if (FRAME_UNDECORATED (f))
  4086         {
  4087           outer_minus_text_width
  4088             = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
  4089           outer_minus_text_height
  4090             = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
  4091           *outer_done = 1;
  4092         }
  4093       else if (*outer_done == 0)
  4094         /* No outer size available.  */
  4095         return default_value;
  4096       else if (*outer_done == -1)
  4097         {
  4098           Lisp_Object frame, outer_edges;
  4099 
  4100           XSETFRAME (frame, f);
  4101           outer_edges = call2 (Qframe_edges, frame, Qouter_edges);
  4102 
  4103           if (!NILP (outer_edges))
  4104             {
  4105               outer_minus_text_width
  4106                 = (XFIXNUM (Fnth (make_fixnum (2), outer_edges))
  4107                    - XFIXNUM (Fnth (make_fixnum (0), outer_edges))
  4108                    - FRAME_TEXT_WIDTH (f));
  4109               outer_minus_text_height
  4110                 = (XFIXNUM (Fnth (make_fixnum (3), outer_edges))
  4111                    - XFIXNUM (Fnth (make_fixnum (1), outer_edges))
  4112                    - FRAME_TEXT_HEIGHT (f));
  4113             }
  4114           else
  4115             {
  4116               /* If we can't get any outer edges, proceed as if the frame
  4117                  were undecorated.  */
  4118               outer_minus_text_width
  4119                 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
  4120               outer_minus_text_height
  4121                 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
  4122             }
  4123 
  4124           *outer_done = 1;
  4125         }
  4126 
  4127       switch (what)
  4128         {
  4129         case FRAME_FLOAT_WIDTH:
  4130           return parent_width * d_val - outer_minus_text_width;
  4131 
  4132         case FRAME_FLOAT_HEIGHT:
  4133           return parent_height * d_val - outer_minus_text_height;
  4134 
  4135         case FRAME_FLOAT_LEFT:
  4136           {
  4137             int rest_width = (parent_width
  4138                               - FRAME_TEXT_WIDTH (f)
  4139                               - outer_minus_text_width);
  4140 
  4141             if (p)
  4142               return (rest_width <= 0 ? 0 : d_val * rest_width);
  4143             else
  4144               return (rest_width <= 0
  4145                       ? parent_left
  4146                       : parent_left + d_val * rest_width);
  4147           }
  4148         case FRAME_FLOAT_TOP:
  4149           {
  4150             int rest_height = (parent_height
  4151                                - FRAME_TEXT_HEIGHT (f)
  4152                                - outer_minus_text_height);
  4153 
  4154             if (p)
  4155               return (rest_height <= 0 ? 0 : d_val * rest_height);
  4156             else
  4157               return (rest_height <= 0
  4158                       ? parent_top
  4159                       : parent_top + d_val * rest_height);
  4160           }
  4161         default:
  4162           emacs_abort ();
  4163         }
  4164     }
  4165 }
  4166 
  4167 /* Change the parameters of frame F as specified by ALIST.
  4168    If a parameter is not specially recognized, do nothing special;
  4169    otherwise call the `gui_set_...' function for that parameter.
  4170    Except for certain geometry properties, always call store_frame_param
  4171    to store the new value in the parameter alist.
  4172 
  4173    DEFAULT_PARAMETER should be set if the alist was not specified by
  4174    the user, or by the face code to set the `font' parameter.  In that
  4175    case, the `font-parameter' frame parameter should not be changed,
  4176    so dynamic-setting.el can restore the user's selected font
  4177    correctly.  */
  4178 
  4179 void
  4180 gui_set_frame_parameters_1 (struct frame *f, Lisp_Object alist,
  4181                             bool default_parameter)
  4182 {
  4183   Lisp_Object tail, frame;
  4184 
  4185   /* Neither of these values should be used.  */
  4186   int width = -1, height = -1;
  4187   bool width_change = false, height_change = false;
  4188 
  4189   /* Same here.  */
  4190   Lisp_Object left, top;
  4191 
  4192   /* Same with these.  */
  4193   Lisp_Object icon_left, icon_top;
  4194 
  4195   /* And with this.  */
  4196   Lisp_Object fullscreen UNINIT;
  4197   bool fullscreen_change = false;
  4198 
  4199   /* Record in these vectors all the parms specified.  */
  4200   Lisp_Object *parms;
  4201   Lisp_Object *values;
  4202   ptrdiff_t i, j, size;
  4203   bool left_no_change = 0, top_no_change = 0;
  4204 #ifdef HAVE_X_WINDOWS
  4205   bool icon_left_no_change = 0, icon_top_no_change = 0;
  4206 #endif
  4207   int parent_done = -1, outer_done = -1;
  4208 
  4209   XSETFRAME (frame, f);
  4210   for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
  4211     size++;
  4212   CHECK_LIST_END (tail, alist);
  4213 
  4214   USE_SAFE_ALLOCA;
  4215   SAFE_ALLOCA_LISP (parms, 2 * size);
  4216   values = parms + size;
  4217 
  4218   /* Extract parm names and values into those vectors.  */
  4219 
  4220   i = 0, j = size - 1;
  4221   for (tail = alist; CONSP (tail); tail = XCDR (tail))
  4222     {
  4223       Lisp_Object elt = XCAR (tail), prop = Fcar (elt), val = Fcdr (elt);
  4224 
  4225       /* Some properties are independent of other properties, but other
  4226          properties are dependent upon them.  These special properties
  4227          are foreground_color, background_color (affects cursor_color)
  4228          and font (affects fringe widths); they're recorded starting
  4229          from the end of PARMS and VALUES to process them first by using
  4230          reverse iteration.  */
  4231 
  4232       if (EQ (prop, Qforeground_color)
  4233           || EQ (prop, Qbackground_color)
  4234           || EQ (prop, Qfont))
  4235         {
  4236           parms[j] = prop;
  4237           values[j] = val;
  4238           j--;
  4239         }
  4240       else
  4241         {
  4242           parms[i] = prop;
  4243           values[i] = val;
  4244           i++;
  4245         }
  4246     }
  4247 
  4248   /* TAIL and ALIST are not used again below here.  */
  4249   alist = tail = Qnil;
  4250 
  4251   top = left = Qunbound;
  4252   icon_left = icon_top = Qunbound;
  4253 
  4254   /* Reverse order is used to make sure that special
  4255      properties noticed above are processed first.  */
  4256   for (i = size - 1; i >= 0; i--)
  4257     {
  4258       Lisp_Object prop, val;
  4259 
  4260       prop = parms[i];
  4261       val = values[i];
  4262 
  4263       if (EQ (prop, Qwidth))
  4264         {
  4265           width_change = true;
  4266 
  4267           if (RANGED_FIXNUMP (0, val, INT_MAX))
  4268             width = XFIXNAT (val) * FRAME_COLUMN_WIDTH (f) ;
  4269           else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
  4270                    && RANGED_FIXNUMP (0, XCDR (val), INT_MAX))
  4271             width = XFIXNAT (XCDR (val));
  4272           else if (FLOATP (val))
  4273             width = frame_float (f, val, FRAME_FLOAT_WIDTH, &parent_done,
  4274                                  &outer_done, -1);
  4275           else
  4276             width_change = false;
  4277         }
  4278       else if (EQ (prop, Qheight))
  4279         {
  4280           height_change = true;
  4281 
  4282           if (RANGED_FIXNUMP (0, val, INT_MAX))
  4283             height = XFIXNAT (val) * FRAME_LINE_HEIGHT (f);
  4284           else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
  4285                    && RANGED_FIXNUMP (0, XCDR (val), INT_MAX))
  4286             height = XFIXNAT (XCDR (val));
  4287           else if (FLOATP (val))
  4288             height = frame_float (f, val, FRAME_FLOAT_HEIGHT, &parent_done,
  4289                                  &outer_done, -1);
  4290           else
  4291             height_change = false;
  4292         }
  4293       else if (EQ (prop, Qtop))
  4294         top = val;
  4295       else if (EQ (prop, Qleft))
  4296         left = val;
  4297       else if (EQ (prop, Qicon_top))
  4298         icon_top = val;
  4299       else if (EQ (prop, Qicon_left))
  4300         icon_left = val;
  4301       else if (EQ (prop, Qfullscreen))
  4302         {
  4303           fullscreen = val;
  4304           fullscreen_change = true;
  4305         }
  4306       else
  4307         {
  4308           Lisp_Object param_index, old_value;
  4309 
  4310           old_value = get_frame_param (f, prop);
  4311 
  4312           store_frame_param (f, prop, val);
  4313 
  4314           param_index = Fget (prop, Qx_frame_parameter);
  4315           if (FIXNATP (param_index)
  4316               && XFIXNAT (param_index) < ARRAYELTS (frame_parms)
  4317               && FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])
  4318             (*(FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])) (f, val, old_value);
  4319 
  4320           if (!default_parameter && EQ (prop, Qfont))
  4321             /* The user manually specified the `font' frame parameter.
  4322                Save that parameter for future use by the
  4323                dynamic-setting code.  */
  4324             store_frame_param (f, Qfont_parameter, val);
  4325         }
  4326     }
  4327 
  4328   /* Don't die if just one of these was set.  */
  4329   if (BASE_EQ (left, Qunbound))
  4330     {
  4331       left_no_change = 1;
  4332       if (f->left_pos < 0)
  4333         left = list2 (Qplus, make_fixnum (f->left_pos));
  4334       else
  4335         XSETINT (left, f->left_pos);
  4336     }
  4337   if (BASE_EQ (top, Qunbound))
  4338     {
  4339       top_no_change = 1;
  4340       if (f->top_pos < 0)
  4341         top = list2 (Qplus, make_fixnum (f->top_pos));
  4342       else
  4343         XSETINT (top, f->top_pos);
  4344     }
  4345 
  4346   /* If one of the icon positions was not set, preserve or default it.  */
  4347   if (! TYPE_RANGED_FIXNUMP (int, icon_left))
  4348     {
  4349 #ifdef HAVE_X_WINDOWS
  4350       icon_left_no_change = 1;
  4351 #endif
  4352       icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
  4353       if (NILP (icon_left))
  4354         XSETINT (icon_left, 0);
  4355     }
  4356   if (! TYPE_RANGED_FIXNUMP (int, icon_top))
  4357     {
  4358 #ifdef HAVE_X_WINDOWS
  4359       icon_top_no_change = 1;
  4360 #endif
  4361       icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
  4362       if (NILP (icon_top))
  4363         XSETINT (icon_top, 0);
  4364     }
  4365 
  4366   if (width_change || height_change)
  4367     {
  4368       Lisp_Object parameter;
  4369 
  4370       if (width_change)
  4371         {
  4372           if (height_change)
  4373             parameter = Qsize;
  4374           else
  4375             {
  4376               height = FRAME_TEXT_HEIGHT (f);
  4377               parameter = Qwidth;
  4378             }
  4379         }
  4380       else
  4381         {
  4382           width = FRAME_TEXT_WIDTH (f);
  4383           parameter = Qheight;
  4384         }
  4385 
  4386       adjust_frame_size (f, width, height, 1, 0, parameter);
  4387     }
  4388 
  4389   if ((!NILP (left) || !NILP (top))
  4390       && ! (left_no_change && top_no_change)
  4391       && ! (FIXNUMP (left) && XFIXNUM (left) == f->left_pos
  4392             && FIXNUMP (top) && XFIXNUM (top) == f->top_pos))
  4393     {
  4394       int leftpos = 0;
  4395       int toppos = 0;
  4396 
  4397       /* Record the signs.  */
  4398       f->size_hint_flags &= ~ (XNegative | YNegative);
  4399       if (EQ (left, Qminus))
  4400         f->size_hint_flags |= XNegative;
  4401       else if (TYPE_RANGED_FIXNUMP (int, left))
  4402         {
  4403           leftpos = XFIXNUM (left);
  4404           if (leftpos < 0)
  4405             f->size_hint_flags |= XNegative;
  4406         }
  4407       else if (CONSP (left) && EQ (XCAR (left), Qminus)
  4408                && CONSP (XCDR (left))
  4409                && RANGED_FIXNUMP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
  4410         {
  4411           leftpos = - XFIXNUM (XCAR (XCDR (left)));
  4412           f->size_hint_flags |= XNegative;
  4413         }
  4414       else if (CONSP (left) && EQ (XCAR (left), Qplus)
  4415                && CONSP (XCDR (left))
  4416                && TYPE_RANGED_FIXNUMP (int, XCAR (XCDR (left))))
  4417         leftpos = XFIXNUM (XCAR (XCDR (left)));
  4418       else if (FLOATP (left))
  4419         leftpos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
  4420                                &outer_done, 0);
  4421 
  4422       if (EQ (top, Qminus))
  4423         f->size_hint_flags |= YNegative;
  4424       else if (TYPE_RANGED_FIXNUMP (int, top))
  4425         {
  4426           toppos = XFIXNUM (top);
  4427           if (toppos < 0)
  4428             f->size_hint_flags |= YNegative;
  4429         }
  4430       else if (CONSP (top) && EQ (XCAR (top), Qminus)
  4431                && CONSP (XCDR (top))
  4432                && RANGED_FIXNUMP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
  4433         {
  4434           toppos = - XFIXNUM (XCAR (XCDR (top)));
  4435           f->size_hint_flags |= YNegative;
  4436         }
  4437       else if (CONSP (top) && EQ (XCAR (top), Qplus)
  4438                && CONSP (XCDR (top))
  4439                && TYPE_RANGED_FIXNUMP (int, XCAR (XCDR (top))))
  4440         toppos = XFIXNUM (XCAR (XCDR (top)));
  4441       else if (FLOATP (top))
  4442         toppos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
  4443                               &outer_done, 0);
  4444 
  4445       /* Store the numeric value of the position.  */
  4446       f->top_pos = toppos;
  4447       f->left_pos = leftpos;
  4448 
  4449       f->win_gravity = NorthWestGravity;
  4450 
  4451       /* Actually set that position, and convert to absolute.  */
  4452       if (FRAME_TERMINAL (f)->set_frame_offset_hook)
  4453         FRAME_TERMINAL (f)->set_frame_offset_hook (f, leftpos, toppos, -1);
  4454     }
  4455 
  4456   if (fullscreen_change)
  4457     {
  4458       Lisp_Object old_value = get_frame_param (f, Qfullscreen);
  4459 
  4460       store_frame_param (f, Qfullscreen, fullscreen);
  4461       if (!EQ (fullscreen, old_value))
  4462         gui_set_fullscreen (f, fullscreen, old_value);
  4463     }
  4464 
  4465 
  4466 #ifdef HAVE_X_WINDOWS
  4467   if ((!NILP (icon_left) || !NILP (icon_top))
  4468       && ! (icon_left_no_change && icon_top_no_change))
  4469     x_wm_set_icon_position (f, XFIXNUM (icon_left), XFIXNUM (icon_top));
  4470 #endif /* HAVE_X_WINDOWS */
  4471 
  4472   SAFE_FREE ();
  4473 }
  4474 
  4475 void
  4476 gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
  4477 {
  4478   gui_set_frame_parameters_1 (f, alist, false);
  4479 }
  4480 
  4481 /* Insert a description of internally-recorded parameters of frame F
  4482    into the parameter alist *ALISTPTR that is to be given to the user.
  4483    Only parameters that are specific to the X window system
  4484    and whose values are not correctly recorded in the frame's
  4485    param_alist need to be considered here.  */
  4486 
  4487 void
  4488 gui_report_frame_params (struct frame *f, Lisp_Object *alistptr)
  4489 {
  4490   Lisp_Object tem;
  4491   uintmax_t w;
  4492   char buf[INT_BUFSIZE_BOUND (w)];
  4493 
  4494   /* Represent negative positions (off the top or left screen edge)
  4495      in a way that Fmodify_frame_parameters will understand correctly.  */
  4496   XSETINT (tem, f->left_pos);
  4497   if (f->left_pos >= 0)
  4498     store_in_alist (alistptr, Qleft, tem);
  4499   else
  4500     store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
  4501 
  4502   XSETINT (tem, f->top_pos);
  4503   if (f->top_pos >= 0)
  4504     store_in_alist (alistptr, Qtop, tem);
  4505   else
  4506     store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
  4507 
  4508   store_in_alist (alistptr, Qborder_width,
  4509                   make_fixnum (f->border_width));
  4510   store_in_alist (alistptr, Qchild_frame_border_width,
  4511                   FRAME_CHILD_FRAME_BORDER_WIDTH (f) >= 0
  4512                   ? make_fixnum (FRAME_CHILD_FRAME_BORDER_WIDTH (f))
  4513                   : Qnil);
  4514   store_in_alist (alistptr, Qinternal_border_width,
  4515                   make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f)));
  4516   store_in_alist (alistptr, Qright_divider_width,
  4517                   make_fixnum (FRAME_RIGHT_DIVIDER_WIDTH (f)));
  4518   store_in_alist (alistptr, Qbottom_divider_width,
  4519                   make_fixnum (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
  4520   store_in_alist (alistptr, Qleft_fringe,
  4521                   make_fixnum (FRAME_LEFT_FRINGE_WIDTH (f)));
  4522   store_in_alist (alistptr, Qright_fringe,
  4523                   make_fixnum (FRAME_RIGHT_FRINGE_WIDTH (f)));
  4524   store_in_alist (alistptr, Qscroll_bar_width,
  4525                   (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
  4526                    ? make_fixnum (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
  4527                    /* nil means "use default width"
  4528                       for non-toolkit scroll bar.
  4529                       ruler-mode.el depends on this.  */
  4530                    : Qnil));
  4531   store_in_alist (alistptr, Qscroll_bar_height,
  4532                   (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
  4533                    ? make_fixnum (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
  4534                    /* nil means "use default height"
  4535                       for non-toolkit scroll bar.  */
  4536                    : Qnil));
  4537   /* FRAME_NATIVE_WINDOW is not guaranteed to return an integer.
  4538      E.g., on MS-Windows it returns a value whose type is HANDLE,
  4539      which is actually a pointer.  Explicit casting avoids compiler
  4540      warnings.  */
  4541   w = (uintptr_t) FRAME_NATIVE_WINDOW (f);
  4542   store_in_alist (alistptr, Qwindow_id,
  4543                   make_formatted_string (buf, "%"PRIuMAX, w));
  4544 #ifdef HAVE_X_WINDOWS
  4545 #ifdef USE_X_TOOLKIT
  4546   /* Tooltip frame may not have this widget.  */
  4547   if (FRAME_X_OUTPUT (f)->widget)
  4548 #endif
  4549     w = (uintptr_t) FRAME_OUTER_WINDOW (f);
  4550   store_in_alist (alistptr, Qouter_window_id,
  4551                   make_formatted_string (buf, "%"PRIuMAX, w));
  4552 #endif
  4553   store_in_alist (alistptr, Qicon_name, f->icon_name);
  4554   store_in_alist (alistptr, Qvisibility,
  4555                   (FRAME_VISIBLE_P (f) ? Qt
  4556                    : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
  4557   store_in_alist (alistptr, Qdisplay,
  4558                   XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
  4559 
  4560   if (FRAME_OUTPUT_DATA (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
  4561     tem = Qnil;
  4562   else
  4563     tem = make_fixed_natnum ((uintptr_t) FRAME_OUTPUT_DATA (f)->parent_desc);
  4564   store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
  4565   store_in_alist (alistptr, Qparent_id, tem);
  4566   store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
  4567 }
  4568 
  4569 
  4570 /* Change the `fullscreen' frame parameter of frame F.  OLD_VALUE is
  4571    the previous value of that parameter, NEW_VALUE is the new value. */
  4572 
  4573 void
  4574 gui_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  4575 {
  4576   if (NILP (new_value))
  4577     f->want_fullscreen = FULLSCREEN_NONE;
  4578   else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
  4579     f->want_fullscreen = FULLSCREEN_BOTH;
  4580   else if (EQ (new_value, Qfullwidth))
  4581     f->want_fullscreen = FULLSCREEN_WIDTH;
  4582   else if (EQ (new_value, Qfullheight))
  4583     f->want_fullscreen = FULLSCREEN_HEIGHT;
  4584   else if (EQ (new_value, Qmaximized))
  4585     f->want_fullscreen = FULLSCREEN_MAXIMIZED;
  4586 
  4587   if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
  4588     FRAME_TERMINAL (f)->fullscreen_hook (f);
  4589 }
  4590 
  4591 
  4592 /* Change the `line-spacing' frame parameter of frame F.  OLD_VALUE is
  4593    the previous value of that parameter, NEW_VALUE is the new value.  */
  4594 
  4595 void
  4596 gui_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  4597 {
  4598   if (NILP (new_value))
  4599     f->extra_line_spacing = 0;
  4600   else if (RANGED_FIXNUMP (0, new_value, INT_MAX))
  4601     f->extra_line_spacing = XFIXNAT (new_value);
  4602   else if (FLOATP (new_value))
  4603     {
  4604       int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
  4605 
  4606       if (new_spacing >= 0)
  4607         f->extra_line_spacing = new_spacing;
  4608       else
  4609         signal_error ("Invalid line-spacing", new_value);
  4610     }
  4611   else
  4612     signal_error ("Invalid line-spacing", new_value);
  4613   if (FRAME_VISIBLE_P (f))
  4614     redraw_frame (f);
  4615 }
  4616 
  4617 
  4618 /* Change the `screen-gamma' frame parameter of frame F.  OLD_VALUE is
  4619    the previous value of that parameter, NEW_VALUE is the new value.  */
  4620 
  4621 void
  4622 gui_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  4623 {
  4624   Lisp_Object bgcolor;
  4625 
  4626   if (NILP (new_value))
  4627     f->gamma = 0;
  4628   else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
  4629     /* The value 0.4545 is the normal viewing gamma.  */
  4630     f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
  4631   else
  4632     signal_error ("Invalid screen-gamma", new_value);
  4633 
  4634   /* Apply the new gamma value to the frame background.  */
  4635   bgcolor = Fassq (Qbackground_color, f->param_alist);
  4636   if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
  4637     {
  4638       Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
  4639       if (FIXNATP (parm_index)
  4640           && XFIXNAT (parm_index) < ARRAYELTS (frame_parms)
  4641           && FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
  4642           (*FRAME_RIF (f)->frame_parm_handlers[XFIXNAT (parm_index)])
  4643             (f, bgcolor, Qnil);
  4644     }
  4645 
  4646   clear_face_cache (true);      /* FIXME: Why of all frames?  */
  4647   fset_redisplay (f);
  4648 }
  4649 
  4650 
  4651 void
  4652 gui_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4653 {
  4654   Lisp_Object font_object;
  4655   int fontset = -1;
  4656 
  4657   /* Set the frame parameter back to the old value because we may
  4658      fail to use ARG as the new parameter value.  */
  4659   store_frame_param (f, Qfont, oldval);
  4660 
  4661   /* ARG is a fontset name, a font name, a cons of fontset name and a
  4662      font object, or a font object.  In the last case, this function
  4663      never fail.  */
  4664   if (STRINGP (arg))
  4665     {
  4666       fontset = fs_query_fontset (arg, 0);
  4667       if (fontset < 0)
  4668         {
  4669           font_object = font_open_by_name (f, arg);
  4670           if (NILP (font_object))
  4671             error ("Font `%s' is not defined", SSDATA (arg));
  4672           arg = AREF (font_object, FONT_NAME_INDEX);
  4673         }
  4674       else if (fontset > 0)
  4675         {
  4676           font_object = font_open_by_name (f, fontset_ascii (fontset));
  4677           if (NILP (font_object))
  4678             error ("Font `%s' is not defined", SDATA (arg));
  4679           arg = AREF (font_object, FONT_NAME_INDEX);
  4680         }
  4681       else
  4682         error ("The default fontset can't be used for a frame font");
  4683     }
  4684   else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
  4685     {
  4686       /* This is the case that the ASCII font of F's fontset XCAR
  4687          (arg) is changed to the font XCDR (arg) by
  4688          `set-fontset-font'.  */
  4689       fontset = fs_query_fontset (XCAR (arg), 0);
  4690       if (fontset < 0)
  4691         error ("Unknown fontset: %s", SDATA (XCAR (arg)));
  4692       font_object = XCDR (arg);
  4693       arg = AREF (font_object, FONT_NAME_INDEX);
  4694     }
  4695   else if (FONT_OBJECT_P (arg))
  4696     {
  4697       font_object = arg;
  4698       /* This is to store the XLFD font name in the frame parameter for
  4699          backward compatibility.  We should store the font-object
  4700          itself in the future.  */
  4701       arg = AREF (font_object, FONT_NAME_INDEX);
  4702       fontset = FRAME_FONTSET (f);
  4703       /* Check if we can use the current fontset.  If not, set FONTSET
  4704          to -1 to generate a new fontset from FONT-OBJECT.  */
  4705       if (fontset >= 0)
  4706         {
  4707           Lisp_Object ascii_font = fontset_ascii (fontset);
  4708           Lisp_Object spec = font_spec_from_name (ascii_font);
  4709 
  4710           /* SPEC might be nil because ASCII_FONT's name doesn't parse
  4711              according to stupid XLFD rules, which, for example,
  4712              disallow font names that include a dash followed by a
  4713              number.  So in those cases we simply call
  4714              set_new_font_hook below to generate a new fontset.  */
  4715           if (NILP (spec) || ! font_match_p (spec, font_object))
  4716             fontset = -1;
  4717         }
  4718     }
  4719   else
  4720     signal_error ("Invalid font", arg);
  4721 
  4722   if (! NILP (Fequal (font_object, oldval)))
  4723     return;
  4724 
  4725   if (FRAME_TERMINAL (f)->set_new_font_hook)
  4726     FRAME_TERMINAL (f)->set_new_font_hook (f, font_object, fontset);
  4727   store_frame_param (f, Qfont, arg);
  4728 
  4729   /* Recalculate tabbar height.  */
  4730   f->n_tab_bar_rows = 0;
  4731   /* Recalculate toolbar height.  */
  4732   f->n_tool_bar_rows = 0;
  4733 
  4734   /* Ensure we redraw it.  */
  4735   clear_current_matrices (f);
  4736 
  4737   /* Attempt to hunt down bug#16028.  */
  4738   SET_FRAME_GARBAGED (f);
  4739 
  4740   /* This is important if we are called by some Lisp as part of
  4741      redisplaying the frame, see redisplay_internal.  */
  4742   f->fonts_changed = true;
  4743 
  4744   recompute_basic_faces (f);
  4745 
  4746   do_pending_window_change (0);
  4747 
  4748   /* We used to call face-set-after-frame-default here, but it leads to
  4749      recursive calls (since that function can set the `default' face's
  4750      font which in turns changes the frame's `font' parameter).
  4751      Also I don't know what this call is meant to do, but it seems the
  4752      wrong way to do it anyway (it does a lot more work than what seems
  4753      reasonable in response to a change to `font').  */
  4754 }
  4755 
  4756 
  4757 void
  4758 gui_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  4759 {
  4760   if (! NILP (new_value)
  4761       && !CONSP (new_value))
  4762     {
  4763       char *p0, *p1;
  4764 
  4765       CHECK_STRING (new_value);
  4766       p0 = p1 = SSDATA (new_value);
  4767       new_value = Qnil;
  4768       while (*p0)
  4769         {
  4770           while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
  4771           if (p0 < p1)
  4772             new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
  4773                                new_value);
  4774           if (*p1)
  4775             {
  4776               int c;
  4777 
  4778               while ((c = *++p1) && c_isspace (c));
  4779             }
  4780           p0 = p1;
  4781         }
  4782       new_value = Fnreverse (new_value);
  4783     }
  4784 
  4785   if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
  4786     return;
  4787 
  4788   if (FRAME_FONT (f))
  4789     {
  4790       Lisp_Object frame;
  4791       XSETFRAME (frame, f);
  4792       free_all_realized_faces (frame);
  4793     }
  4794 
  4795   new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
  4796   if (NILP (new_value))
  4797     {
  4798       if (NILP (old_value))
  4799         error ("No font backend available");
  4800       font_update_drivers (f, old_value);
  4801       error ("None of specified font backends are available");
  4802     }
  4803   store_frame_param (f, Qfont_backend, new_value);
  4804 
  4805   if (FRAME_FONT (f))
  4806     {
  4807       /* Reconsider default font after backend(s) change (Bug#23386).  */
  4808       FRAME_RIF (f)->default_font_parameter (f, Qnil);
  4809       face_change = true;
  4810       windows_or_buffers_changed = 18;
  4811     }
  4812 }
  4813 
  4814 void
  4815 gui_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  4816 {
  4817   int unit = FRAME_COLUMN_WIDTH (f);
  4818   int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
  4819   int new_width;
  4820 
  4821   new_width = (RANGED_FIXNUMP (-INT_MAX, new_value, INT_MAX)
  4822                ? eabs (XFIXNUM (new_value)) : 8);
  4823 
  4824   if (new_width != old_width)
  4825     {
  4826       f->left_fringe_width = new_width;
  4827       f->fringe_cols /* Round up.  */
  4828         = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
  4829 
  4830       if (FRAME_NATIVE_WINDOW (f) != 0)
  4831         adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
  4832 
  4833       SET_FRAME_GARBAGED (f);
  4834     }
  4835 }
  4836 
  4837 
  4838 void
  4839 gui_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  4840 {
  4841   int unit = FRAME_COLUMN_WIDTH (f);
  4842   int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
  4843   int new_width;
  4844 
  4845   new_width = (RANGED_FIXNUMP (-INT_MAX, new_value, INT_MAX)
  4846                ? eabs (XFIXNUM (new_value)) : 8);
  4847 
  4848   if (new_width != old_width)
  4849     {
  4850       f->right_fringe_width = new_width;
  4851       f->fringe_cols /* Round up.  */
  4852         = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
  4853 
  4854       if (FRAME_NATIVE_WINDOW (f) != 0)
  4855         adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
  4856 
  4857       SET_FRAME_GARBAGED (f);
  4858     }
  4859 }
  4860 
  4861 
  4862 void
  4863 gui_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4864 {
  4865   int border_width = check_integer_range (arg, INT_MIN, INT_MAX);
  4866 
  4867   if (border_width == f->border_width)
  4868     return;
  4869 
  4870   if (FRAME_NATIVE_WINDOW (f) != 0)
  4871     error ("Cannot change the border width of a frame");
  4872 
  4873   f->border_width = border_width;
  4874 }
  4875 
  4876 void
  4877 gui_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4878 {
  4879   int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
  4880   int new = check_int_nonnegative (arg);
  4881   if (new != old)
  4882     {
  4883       f->right_divider_width = new;
  4884       adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
  4885       adjust_frame_glyphs (f);
  4886       SET_FRAME_GARBAGED (f);
  4887     }
  4888 }
  4889 
  4890 void
  4891 gui_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4892 {
  4893   int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
  4894   int new = check_int_nonnegative (arg);
  4895   if (new != old)
  4896     {
  4897       f->bottom_divider_width = new;
  4898       adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
  4899       adjust_frame_glyphs (f);
  4900       SET_FRAME_GARBAGED (f);
  4901     }
  4902 }
  4903 
  4904 void
  4905 gui_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
  4906 {
  4907   Lisp_Object frame;
  4908   XSETFRAME (frame, f);
  4909 
  4910   if (NILP (value))
  4911     Fmake_frame_invisible (frame, Qt);
  4912   else if (EQ (value, Qicon))
  4913     Ficonify_frame (frame);
  4914   else
  4915     Fmake_frame_visible (frame);
  4916 }
  4917 
  4918 void
  4919 gui_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4920 {
  4921   f->auto_raise = !NILP (arg);
  4922 }
  4923 
  4924 void
  4925 gui_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4926 {
  4927   f->auto_lower = !NILP (arg);
  4928 }
  4929 
  4930 void
  4931 gui_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4932 {
  4933   f->no_split = !NILP (arg);
  4934 }
  4935 
  4936 void
  4937 gui_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4938 {
  4939   if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
  4940       || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
  4941       || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
  4942       || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
  4943     {
  4944       FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
  4945         = (NILP (arg)
  4946            ? vertical_scroll_bar_none
  4947            : EQ (Qleft, arg)
  4948            ? vertical_scroll_bar_left
  4949            : EQ (Qright, arg)
  4950            ? vertical_scroll_bar_right
  4951            : EQ (Qleft, Vdefault_frame_scroll_bars)
  4952            ? vertical_scroll_bar_left
  4953            : EQ (Qright, Vdefault_frame_scroll_bars)
  4954            ? vertical_scroll_bar_right
  4955            : vertical_scroll_bar_none);
  4956 
  4957       /* We set this parameter before creating the native window for
  4958          the frame, so we can get the geometry right from the start.
  4959          However, if the window hasn't been created yet, we shouldn't
  4960          call set_window_size_hook.  */
  4961       if (FRAME_NATIVE_WINDOW (f))
  4962         adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
  4963 
  4964       SET_FRAME_GARBAGED (f);
  4965     }
  4966 }
  4967 
  4968 void
  4969 gui_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4970 {
  4971 #if USE_HORIZONTAL_SCROLL_BARS
  4972   if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
  4973       || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
  4974     {
  4975       f->horizontal_scroll_bars = NILP (arg) ? false : true;
  4976 
  4977       /* We set this parameter before creating the native window for
  4978          the frame, so we can get the geometry right from the start.
  4979          However, if the window hasn't been created yet, we shouldn't
  4980          call set_window_size_hook.  */
  4981       if (FRAME_NATIVE_WINDOW (f))
  4982         adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
  4983 
  4984       SET_FRAME_GARBAGED (f);
  4985     }
  4986 #endif
  4987 }
  4988 
  4989 void
  4990 gui_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  4991 {
  4992   int unit = FRAME_COLUMN_WIDTH (f);
  4993 
  4994   if (RANGED_FIXNUMP (1, arg, INT_MAX)
  4995       && XFIXNAT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
  4996     {
  4997       FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFIXNAT (arg);
  4998       FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFIXNAT (arg) + unit - 1) / unit;
  4999       if (FRAME_NATIVE_WINDOW (f))
  5000         adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
  5001 
  5002       SET_FRAME_GARBAGED (f);
  5003     }
  5004   else
  5005     {
  5006       if (FRAME_TERMINAL (f)->set_scroll_bar_default_width_hook)
  5007         FRAME_TERMINAL (f)->set_scroll_bar_default_width_hook (f);
  5008 
  5009       if (FRAME_NATIVE_WINDOW (f))
  5010         adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
  5011 
  5012       SET_FRAME_GARBAGED (f);
  5013     }
  5014 
  5015   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
  5016   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
  5017 }
  5018 
  5019 void
  5020 gui_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  5021 {
  5022 #if USE_HORIZONTAL_SCROLL_BARS
  5023   int unit = FRAME_LINE_HEIGHT (f);
  5024 
  5025   if (RANGED_FIXNUMP (1, arg, INT_MAX)
  5026       && XFIXNAT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
  5027     {
  5028       FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFIXNAT (arg);
  5029       FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFIXNAT (arg) + unit - 1) / unit;
  5030       if (FRAME_NATIVE_WINDOW (f))
  5031         adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
  5032 
  5033       SET_FRAME_GARBAGED (f);
  5034     }
  5035   else
  5036     {
  5037       if (FRAME_TERMINAL (f)->set_scroll_bar_default_height_hook)
  5038         FRAME_TERMINAL (f)->set_scroll_bar_default_height_hook (f);
  5039 
  5040       if (FRAME_NATIVE_WINDOW (f))
  5041         adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
  5042 
  5043       SET_FRAME_GARBAGED (f);
  5044     }
  5045 
  5046   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
  5047   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
  5048 #endif
  5049 }
  5050 
  5051 void
  5052 gui_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  5053 {
  5054   double alpha = 1.0;
  5055   double newval[2];
  5056   int i;
  5057   Lisp_Object item;
  5058 
  5059   for (i = 0; i < 2; i++)
  5060     {
  5061       newval[i] = 1.0;
  5062       if (CONSP (arg))
  5063         {
  5064           item = CAR (arg);
  5065           arg  = CDR (arg);
  5066         }
  5067       else
  5068         item = arg;
  5069 
  5070       if (NILP (item))
  5071         alpha = - 1.0;
  5072       else if (FLOATP (item))
  5073         {
  5074           alpha = XFLOAT_DATA (item);
  5075           if (! (0 <= alpha && alpha <= 1.0))
  5076             args_out_of_range (make_float (0.0), make_float (1.0));
  5077         }
  5078       else if (FIXNUMP (item))
  5079         {
  5080           EMACS_INT ialpha = XFIXNUM (item);
  5081           if (! (0 <= ialpha && ialpha <= 100))
  5082             args_out_of_range (make_fixnum (0), make_fixnum (100));
  5083           alpha = ialpha / 100.0;
  5084         }
  5085       else
  5086         wrong_type_argument (Qnumberp, item);
  5087       newval[i] = alpha;
  5088     }
  5089 
  5090   for (i = 0; i < 2; i++)
  5091     f->alpha[i] = newval[i];
  5092 
  5093   if (FRAME_TERMINAL (f)->set_frame_alpha_hook)
  5094     {
  5095       block_input ();
  5096       FRAME_TERMINAL (f)->set_frame_alpha_hook (f);
  5097       unblock_input ();
  5098     }
  5099 }
  5100 
  5101 void
  5102 gui_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  5103 {
  5104   double alpha = 1.0;
  5105 
  5106   if (NILP (arg))
  5107     alpha = 1.0;
  5108   else if (FLOATP (arg))
  5109     {
  5110       alpha = XFLOAT_DATA (arg);
  5111       if (! (0 <= alpha && alpha <= 1.0))
  5112         args_out_of_range (make_float (0.0), make_float (1.0));
  5113     }
  5114   else if (FIXNUMP (arg))
  5115     {
  5116       EMACS_INT ialpha = XFIXNUM (arg);
  5117       if (! (0 <= ialpha && ialpha <= 100))
  5118         args_out_of_range (make_fixnum (0), make_fixnum (100));
  5119       alpha = ialpha / 100.0;
  5120     }
  5121   else
  5122     wrong_type_argument (Qnumberp, arg);
  5123 
  5124   f->alpha_background = alpha;
  5125 
  5126   recompute_basic_faces (f);
  5127   SET_FRAME_GARBAGED (f);
  5128 }
  5129 
  5130 /**
  5131  * gui_set_no_special_glyphs:
  5132  *
  5133  * Set frame F's `no-special-glyphs' parameter which, if non-nil,
  5134  * suppresses the display of truncation and continuation glyphs
  5135  * outside fringes.
  5136  */
  5137 void
  5138 gui_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  5139 {
  5140   if (!EQ (new_value, old_value))
  5141     FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (new_value);
  5142 }
  5143 
  5144 
  5145 /* Non-zero if mouse is grabbed on DPYINFO
  5146    and we know the frame where it is.  */
  5147 
  5148 bool
  5149 gui_mouse_grabbed (Display_Info *dpyinfo)
  5150 {
  5151   return ((dpyinfo->grabbed
  5152            || (dpyinfo->terminal->any_grab_hook
  5153                && dpyinfo->terminal->any_grab_hook (dpyinfo)))
  5154           && dpyinfo->last_mouse_frame
  5155           && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
  5156 }
  5157 
  5158 /* Re-highlight something with mouse-face properties
  5159    on DPYINFO using saved frame and mouse position.  */
  5160 
  5161 void
  5162 gui_redo_mouse_highlight (Display_Info *dpyinfo)
  5163 {
  5164   if (dpyinfo->last_mouse_motion_frame
  5165       && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
  5166     note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
  5167                           dpyinfo->last_mouse_motion_x,
  5168                           dpyinfo->last_mouse_motion_y);
  5169 }
  5170 
  5171 /* Subroutines of creating an X frame.  */
  5172 
  5173 /* Make sure that Vx_resource_name is set to a reasonable value.
  5174    Fix it up, or set it to `emacs' if it is too hopeless.  */
  5175 
  5176 void
  5177 validate_x_resource_name (void)
  5178 {
  5179   ptrdiff_t len = 0;
  5180   /* Number of valid characters in the resource name.  */
  5181   ptrdiff_t good_count = 0;
  5182   /* Number of invalid characters in the resource name.  */
  5183   ptrdiff_t bad_count = 0;
  5184   Lisp_Object new;
  5185   ptrdiff_t i;
  5186 
  5187   if (!STRINGP (Vx_resource_class))
  5188     Vx_resource_class = build_string (EMACS_CLASS);
  5189 
  5190   if (STRINGP (Vx_resource_name))
  5191     {
  5192       unsigned char *p = SDATA (Vx_resource_name);
  5193 
  5194       len = SBYTES (Vx_resource_name);
  5195 
  5196       /* Only letters, digits, - and _ are valid in resource names.
  5197          Count the valid characters and count the invalid ones.  */
  5198       for (i = 0; i < len; i++)
  5199         {
  5200           int c = p[i];
  5201           if (! ((c >= 'a' && c <= 'z')
  5202                  || (c >= 'A' && c <= 'Z')
  5203                  || (c >= '0' && c <= '9')
  5204                  || c == '-' || c == '_'))
  5205             bad_count++;
  5206           else
  5207             good_count++;
  5208         }
  5209     }
  5210   else
  5211     /* Not a string => completely invalid.  */
  5212     bad_count = 5, good_count = 0;
  5213 
  5214   /* If name is valid already, return.  */
  5215   if (bad_count == 0)
  5216     return;
  5217 
  5218   /* If name is entirely invalid, or nearly so, or is so implausibly
  5219      large that alloca might not work, use `emacs'.  */
  5220   if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
  5221     {
  5222       Vx_resource_name = build_string ("emacs");
  5223       return;
  5224     }
  5225 
  5226   /* Name is partly valid.  Copy it and replace the invalid characters
  5227      with underscores.  */
  5228 
  5229   Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
  5230 
  5231   for (i = 0; i < len; i++)
  5232     {
  5233       int c = SREF (new, i);
  5234       if (! ((c >= 'a' && c <= 'z')
  5235              || (c >= 'A' && c <= 'Z')
  5236              || (c >= '0' && c <= '9')
  5237              || c == '-' || c == '_'))
  5238         SSET (new, i, '_');
  5239     }
  5240 }
  5241 
  5242 /* Get a GUI resource, like Fx_get_resource, but for display DPYINFO.
  5243    See Fx_get_resource below for other parameters.  */
  5244 
  5245 Lisp_Object
  5246 gui_display_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
  5247                           Lisp_Object class, Lisp_Object component,
  5248                           Lisp_Object subclass)
  5249 {
  5250   CHECK_STRING (attribute);
  5251   CHECK_STRING (class);
  5252 
  5253   if (!NILP (component))
  5254     CHECK_STRING (component);
  5255   if (!NILP (subclass))
  5256     CHECK_STRING (subclass);
  5257   if (NILP (component) != NILP (subclass))
  5258     error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
  5259 
  5260   validate_x_resource_name ();
  5261 
  5262   /* Allocate space for the components, the dots which separate them,
  5263      and the final '\0'.  Make them big enough for the worst case.  */
  5264   ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
  5265                             + (STRINGP (component)
  5266                                ? SBYTES (component) : 0)
  5267                             + SBYTES (attribute)
  5268                             + 3);
  5269 
  5270   ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
  5271                              + SBYTES (class)
  5272                              + (STRINGP (subclass)
  5273                                 ? SBYTES (subclass) : 0)
  5274                              + 3);
  5275   USE_SAFE_ALLOCA;
  5276   char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
  5277   char *class_key = name_key + name_keysize;
  5278 
  5279   /* Start with emacs.FRAMENAME for the name (the specific one)
  5280      and with `Emacs' for the class key (the general one).  */
  5281   char *nz = lispstpcpy (name_key, Vx_resource_name);
  5282   char *cz = lispstpcpy (class_key, Vx_resource_class);
  5283 
  5284   *cz++ = '.';
  5285   cz = lispstpcpy (cz, class);
  5286 
  5287   if (!NILP (component))
  5288     {
  5289       *cz++ = '.';
  5290       lispstpcpy (cz, subclass);
  5291 
  5292       *nz++ = '.';
  5293       nz = lispstpcpy (nz, component);
  5294     }
  5295 
  5296   *nz++ = '.';
  5297   lispstpcpy (nz, attribute);
  5298 
  5299   const char *value =
  5300     dpyinfo->terminal->get_string_resource_hook (&dpyinfo->rdb,
  5301                                                  name_key,
  5302                                                  class_key);
  5303   SAFE_FREE();
  5304 
  5305   if (value && *value)
  5306     return build_string (value);
  5307   else
  5308     return Qnil;
  5309 }
  5310 
  5311 
  5312 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
  5313        doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
  5314 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
  5315 class, where INSTANCE is the name under which Emacs was invoked, or
  5316 the name specified by the `-name' or `-rn' command-line arguments.
  5317 
  5318 The optional arguments COMPONENT and SUBCLASS add to the key and the
  5319 class, respectively.  You must specify both of them or neither.
  5320 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
  5321 and the class is `Emacs.CLASS.SUBCLASS'.  */)
  5322   (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
  5323    Lisp_Object subclass)
  5324 {
  5325   check_window_system (NULL);
  5326 
  5327   return gui_display_get_resource (check_x_display_info (Qnil),
  5328                                    attribute, class, component, subclass);
  5329 }
  5330 
  5331 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
  5332 /* Used when C code wants a resource value.  */
  5333 /* Called from oldXMenu/Create.c.  */
  5334 const char *
  5335 x_get_resource_string (const char *attribute, const char *class)
  5336 {
  5337   const char *result;
  5338   struct frame *sf = SELECTED_FRAME ();
  5339   ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
  5340   USE_SAFE_ALLOCA;
  5341 
  5342   /* Allocate space for the components, the dots which separate them,
  5343      and the final '\0'.  */
  5344   ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
  5345   ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
  5346   char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
  5347   char *class_key = name_key + name_keysize;
  5348   esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
  5349   sprintf (class_key, "%s.%s", EMACS_CLASS, class);
  5350 
  5351   result = x_get_string_resource (&FRAME_DISPLAY_INFO (sf)->rdb,
  5352                                   name_key, class_key);
  5353   SAFE_FREE ();
  5354   return result;
  5355 }
  5356 #endif
  5357 
  5358 /* Return the value of parameter PARAM.
  5359 
  5360    First search ALIST, then Vdefault_frame_alist, then the GUI
  5361    resource database, using ATTRIBUTE as the attribute name and CLASS
  5362    as its class.
  5363 
  5364    Convert the resource to the type specified by desired_type.
  5365 
  5366    If no default is specified, return Qunbound.  If you call
  5367    gui_display_get_arg, make sure you deal with Qunbound in a
  5368    reasonable way, and don't let it get stored in any Lisp-visible
  5369    variables!  */
  5370 
  5371 Lisp_Object
  5372 gui_display_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
  5373                      const char *attribute, const char *class,
  5374                      enum resource_types type)
  5375 {
  5376   Lisp_Object tem;
  5377 
  5378   tem = Fassq (param, alist);
  5379 
  5380   if (!NILP (tem))
  5381     {
  5382       /* If we find this parm in ALIST, clear it out
  5383          so that it won't be "left over" at the end.  */
  5384       Lisp_Object tail;
  5385       XSETCAR (tem, Qnil);
  5386       /* In case the parameter appears more than once in the alist,
  5387          clear it out.  */
  5388       for (tail = alist; CONSP (tail); tail = XCDR (tail))
  5389         if (CONSP (XCAR (tail))
  5390             && EQ (XCAR (XCAR (tail)), param))
  5391           XSETCAR (XCAR (tail), Qnil);
  5392     }
  5393   else
  5394     tem = Fassq (param, Vdefault_frame_alist);
  5395 
  5396   /* If it wasn't specified in ALIST or the Lisp-level defaults,
  5397      look in the X resources.  */
  5398   if (NILP (tem))
  5399     {
  5400       if (attribute && dpyinfo)
  5401         {
  5402           AUTO_STRING (at, attribute);
  5403           AUTO_STRING (cl, class);
  5404           tem = gui_display_get_resource (dpyinfo, at, cl, Qnil, Qnil);
  5405 
  5406           if (NILP (tem))
  5407             return Qunbound;
  5408 
  5409           switch (type)
  5410             {
  5411             case RES_TYPE_NUMBER:
  5412               return make_fixnum (atoi (SSDATA (tem)));
  5413 
  5414             case RES_TYPE_BOOLEAN_NUMBER:
  5415               if (!strcmp (SSDATA (tem), "on")
  5416                   || !strcmp (SSDATA (tem), "true"))
  5417                 return make_fixnum (1);
  5418               return make_fixnum (atoi (SSDATA (tem)));
  5419               break;
  5420 
  5421             case RES_TYPE_FLOAT:
  5422               return make_float (atof (SSDATA (tem)));
  5423 
  5424             case RES_TYPE_BOOLEAN:
  5425               tem = Fdowncase (tem);
  5426               if (!strcmp (SSDATA (tem), "on")
  5427 #ifdef HAVE_NS
  5428                   || !strcmp (SSDATA (tem), "yes")
  5429 #endif
  5430                   || !strcmp (SSDATA (tem), "true"))
  5431                 return Qt;
  5432               else
  5433                 return Qnil;
  5434 
  5435             case RES_TYPE_STRING:
  5436               return tem;
  5437 
  5438             case RES_TYPE_SYMBOL:
  5439               /* As a special case, we map the values `true' and `on'
  5440                  to Qt, and `false' and `off' to Qnil.  */
  5441               {
  5442                 Lisp_Object lower;
  5443                 lower = Fdowncase (tem);
  5444                 if (!strcmp (SSDATA (lower), "on")
  5445 #ifdef HAVE_NS
  5446                     || !strcmp (SSDATA (lower), "yes")
  5447 #endif
  5448                     || !strcmp (SSDATA (lower), "true"))
  5449                   return Qt;
  5450                 else if (!strcmp (SSDATA (lower), "off")
  5451 #ifdef HAVE_NS
  5452                       || !strcmp (SSDATA (lower), "no")
  5453 #endif
  5454                       || !strcmp (SSDATA (lower), "false"))
  5455                   return Qnil;
  5456                 else
  5457                   return Fintern (tem, Qnil);
  5458               }
  5459 
  5460             default:
  5461               emacs_abort ();
  5462             }
  5463         }
  5464       else
  5465         return Qunbound;
  5466     }
  5467   return Fcdr (tem);
  5468 }
  5469 
  5470 static Lisp_Object
  5471 gui_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
  5472                    const char *attribute, const char *class,
  5473                    enum resource_types type)
  5474 {
  5475   return gui_display_get_arg (FRAME_DISPLAY_INFO (f),
  5476                               alist, param, attribute, class, type);
  5477 }
  5478 
  5479 /* Like gui_frame_get_arg, but also record the value in f->param_alist.  */
  5480 
  5481 Lisp_Object
  5482 gui_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
  5483                               Lisp_Object param,
  5484                               const char *attribute, const char *class,
  5485                               enum resource_types type)
  5486 {
  5487   Lisp_Object value;
  5488 
  5489   value = gui_display_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
  5490                                attribute, class, type);
  5491   if (! NILP (value) && ! BASE_EQ (value, Qunbound))
  5492     store_frame_param (f, param, value);
  5493 
  5494   return value;
  5495 }
  5496 
  5497 
  5498 /* Record in frame F the specified or default value according to ALIST
  5499    of the parameter named PROP (a Lisp symbol).
  5500    If no value is specified for PROP, look for an X default for XPROP
  5501    on the frame named NAME.
  5502    If that is not found either, use the value DEFLT.  */
  5503 
  5504 Lisp_Object
  5505 gui_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
  5506                        Lisp_Object deflt, const char *xprop, const char *xclass,
  5507                        enum resource_types type)
  5508 {
  5509   Lisp_Object tem;
  5510   bool was_unbound;
  5511 
  5512   tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type);
  5513 
  5514   if (BASE_EQ (tem, Qunbound))
  5515     {
  5516       tem = deflt;
  5517       was_unbound = true;
  5518     }
  5519   else
  5520     was_unbound = false;
  5521 
  5522   AUTO_FRAME_ARG (arg, prop, tem);
  5523   gui_set_frame_parameters_1 (f, arg, was_unbound);
  5524   return tem;
  5525 }
  5526 
  5527 
  5528 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
  5529 
  5530 /*
  5531  *    XParseGeometry parses strings of the form
  5532  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
  5533  *   width, height, xoffset, and yoffset are unsigned integers.
  5534  *   Example:  "=80x24+300-49"
  5535  *   The equal sign is optional.
  5536  *   It returns a bitmask that indicates which of the four values
  5537  *   were actually found in the string.  For each value found,
  5538  *   the corresponding argument is updated;  for each value
  5539  *   not found, the corresponding argument is left unchanged.
  5540  */
  5541 
  5542 static int
  5543 XParseGeometry (char *string,
  5544                 int *x, int *y,
  5545                 unsigned int *width, unsigned int *height)
  5546 {
  5547   int mask = NoValue;
  5548   char *strind;
  5549   unsigned long tempWidth UNINIT, tempHeight UNINIT;
  5550   long int tempX UNINIT, tempY UNINIT;
  5551   char *nextCharacter;
  5552 
  5553   if (string == NULL || *string == '\0')
  5554     return mask;
  5555   if (*string == '=')
  5556     string++;  /* ignore possible '=' at beg of geometry spec */
  5557 
  5558   strind = string;
  5559   if (*strind != '+' && *strind != '-' && *strind != 'x')
  5560     {
  5561       tempWidth = strtoul (strind, &nextCharacter, 10);
  5562       if (strind == nextCharacter)
  5563         return 0;
  5564       strind = nextCharacter;
  5565       mask |= WidthValue;
  5566     }
  5567 
  5568   if (*strind == 'x' || *strind == 'X')
  5569     {
  5570       strind++;
  5571       tempHeight = strtoul (strind, &nextCharacter, 10);
  5572       if (strind == nextCharacter)
  5573         return 0;
  5574       strind = nextCharacter;
  5575       mask |= HeightValue;
  5576     }
  5577 
  5578   if (*strind == '+' || *strind == '-')
  5579     {
  5580       if (*strind == '-')
  5581         mask |= XNegative;
  5582       tempX = strtol (strind, &nextCharacter, 10);
  5583       if (strind == nextCharacter)
  5584         return 0;
  5585       strind = nextCharacter;
  5586       mask |= XValue;
  5587       if (*strind == '+' || *strind == '-')
  5588         {
  5589           if (*strind == '-')
  5590             mask |= YNegative;
  5591           tempY = strtol (strind, &nextCharacter, 10);
  5592           if (strind == nextCharacter)
  5593             return 0;
  5594           strind = nextCharacter;
  5595           mask |= YValue;
  5596         }
  5597     }
  5598 
  5599   /* If strind isn't at the end of the string then it's an invalid
  5600      geometry specification. */
  5601 
  5602   if (*strind != '\0')
  5603     return 0;
  5604 
  5605   if (mask & XValue)
  5606     *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
  5607   if (mask & YValue)
  5608     *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
  5609   if (mask & WidthValue)
  5610     *width = min (tempWidth, UINT_MAX);
  5611   if (mask & HeightValue)
  5612     *height = min (tempHeight, UINT_MAX);
  5613   return mask;
  5614 }
  5615 
  5616 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
  5617 
  5618 
  5619 /* NS used to define x-parse-geometry in ns-win.el, but that confused
  5620    make-docfile: the documentation string in ns-win.el was used for
  5621    x-parse-geometry even in non-NS builds.
  5622 
  5623    With two definitions of x-parse-geometry in this file, various
  5624    things still get confused (eg M-x apropos documentation), so that
  5625    it is best if the two definitions just share the same doc-string.
  5626 */
  5627 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
  5628        doc: /* Parse a display geometry string STRING.
  5629 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
  5630 The properties returned may include `top', `left', `height', and `width'.
  5631 For X, the value of `left' or `top' may be an integer,
  5632 or a list (+ N) meaning N pixels relative to top/left corner,
  5633 or a list (- N) meaning -N pixels relative to bottom/right corner.
  5634 On Nextstep, this just calls `ns-parse-geometry'.  */)
  5635   (Lisp_Object string)
  5636 {
  5637   /* x and y don't need initialization, as they are not accessed
  5638      unless XParseGeometry sets them, in which case it always returns
  5639      a non-zero value.  */
  5640   int x UNINIT, y UNINIT;
  5641   unsigned int width, height;
  5642 
  5643   CHECK_STRING (string);
  5644 
  5645 #ifdef HAVE_NS
  5646   if (strchr (SSDATA (string), ' ') != NULL)
  5647     return call1 (Qns_parse_geometry, string);
  5648 #endif
  5649   int geometry = XParseGeometry (SSDATA (string),
  5650                                  &x, &y, &width, &height);
  5651   Lisp_Object result = Qnil;
  5652   if (geometry & XValue)
  5653     {
  5654       Lisp_Object element;
  5655 
  5656       if (x >= 0 && (geometry & XNegative))
  5657         element = list3 (Qleft, Qminus, make_fixnum (-x));
  5658       else if (x < 0 && ! (geometry & XNegative))
  5659         element = list3 (Qleft, Qplus, make_fixnum (x));
  5660       else
  5661         element = Fcons (Qleft, make_fixnum (x));
  5662       result = Fcons (element, result);
  5663     }
  5664 
  5665   if (geometry & YValue)
  5666     {
  5667       Lisp_Object element;
  5668 
  5669       if (y >= 0 && (geometry & YNegative))
  5670         element = list3 (Qtop, Qminus, make_fixnum (-y));
  5671       else if (y < 0 && ! (geometry & YNegative))
  5672         element = list3 (Qtop, Qplus, make_fixnum (y));
  5673       else
  5674         element = Fcons (Qtop, make_fixnum (y));
  5675       result = Fcons (element, result);
  5676     }
  5677 
  5678   if (geometry & WidthValue)
  5679     result = Fcons (Fcons (Qwidth, make_fixnum (width)), result);
  5680   if (geometry & HeightValue)
  5681     result = Fcons (Fcons (Qheight, make_fixnum (height)), result);
  5682 
  5683   return result;
  5684 }
  5685 
  5686 
  5687 /* Calculate the desired size and position of frame F.
  5688    Return the flags saying which aspects were specified.
  5689 
  5690    Also set the win_gravity and size_hint_flags of F.
  5691 
  5692    Adjust height for toolbar if TOOLBAR_P is 1.
  5693 
  5694    This function does not make the coordinates positive.  */
  5695 
  5696 long
  5697 gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
  5698                         bool toolbar_p)
  5699 {
  5700   Lisp_Object height, width, user_size, top, left, user_position;
  5701   long window_prompting = 0;
  5702   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
  5703   int parent_done = -1, outer_done = -1;
  5704   int text_width = 80 * FRAME_COLUMN_WIDTH (f);
  5705   int text_height = 36 * FRAME_LINE_HEIGHT (f);
  5706 
  5707   /* Window managers expect that if program-specified
  5708      positions are not (0,0), they're intentional, not defaults.  */
  5709   f->top_pos = 0;
  5710   f->left_pos = 0;
  5711 
  5712   /* Calculate a tab bar height so that the user gets a text display
  5713      area of the size he specified with -g or via .Xdefaults.  Later
  5714      changes of the tab bar height don't change the frame size.  This
  5715      is done so that users can create tall Emacs frames without having
  5716      to guess how tall the tab bar will get.  */
  5717   if (tabbar_p && FRAME_TAB_BAR_LINES (f))
  5718     {
  5719       if (frame_default_tab_bar_height)
  5720         /* A default tab bar height was already set by the display code
  5721            for some other frame, use that.  */
  5722         FRAME_TAB_BAR_HEIGHT (f) = frame_default_tab_bar_height;
  5723       else
  5724         /* Calculate the height from various other settings.  For some
  5725            reason, these are usually off by 2 hence of no use.  */
  5726         {
  5727           int margin, relief;
  5728 
  5729           relief = (tab_bar_button_relief < 0
  5730                     ? DEFAULT_TAB_BAR_BUTTON_RELIEF
  5731                     : min (tab_bar_button_relief, 1000000));
  5732 
  5733           if (RANGED_FIXNUMP (1, Vtab_bar_button_margin, INT_MAX))
  5734             margin = XFIXNAT (Vtab_bar_button_margin);
  5735           else if (CONSP (Vtab_bar_button_margin)
  5736                    && RANGED_FIXNUMP (1, XCDR (Vtab_bar_button_margin), INT_MAX))
  5737             margin = XFIXNAT (XCDR (Vtab_bar_button_margin));
  5738           else
  5739             margin = 0;
  5740 
  5741           FRAME_TAB_BAR_HEIGHT (f)
  5742             = DEFAULT_TAB_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
  5743         }
  5744     }
  5745 
  5746   /* Calculate a tool bar height so that the user gets a text display
  5747      area of the size he specified with -g or via .Xdefaults.  Later
  5748      changes of the tool bar height don't change the frame size.  This
  5749      is done so that users can create tall Emacs frames without having
  5750      to guess how tall the tool bar will get.  */
  5751   if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
  5752     {
  5753       if (frame_default_tool_bar_height)
  5754         FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
  5755       else
  5756         {
  5757           int margin, relief;
  5758 
  5759           relief = (tool_bar_button_relief < 0
  5760                     ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
  5761                     : min (tool_bar_button_relief, 1000000));
  5762 
  5763           if (RANGED_FIXNUMP (1, Vtool_bar_button_margin, INT_MAX))
  5764             margin = XFIXNAT (Vtool_bar_button_margin);
  5765           else if (CONSP (Vtool_bar_button_margin)
  5766                    && RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
  5767             margin = XFIXNAT (XCDR (Vtool_bar_button_margin));
  5768           else
  5769             margin = 0;
  5770 
  5771           FRAME_TOOL_BAR_HEIGHT (f)
  5772             = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
  5773         }
  5774     }
  5775 
  5776   /* Ensure that earlier new_width and new_height settings won't
  5777      override what we specify below.  */
  5778   f->new_width = f->new_height = -1;
  5779 
  5780   height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
  5781   width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
  5782   if (!BASE_EQ (width, Qunbound) || !BASE_EQ (height, Qunbound))
  5783     {
  5784       if (!BASE_EQ (width, Qunbound))
  5785         {
  5786           if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
  5787             {
  5788               CHECK_FIXNUM (XCDR (width));
  5789               if ((XFIXNUM (XCDR (width)) < 0 || XFIXNUM (XCDR (width)) > INT_MAX))
  5790                 xsignal1 (Qargs_out_of_range, XCDR (width));
  5791 
  5792               text_width = XFIXNUM (XCDR (width));
  5793               f->inhibit_horizontal_resize = true;
  5794             }
  5795           else if (FLOATP (width))
  5796             {
  5797               double d_width = XFLOAT_DATA (width);
  5798 
  5799               if (d_width < 0.0 || d_width > 1.0)
  5800                 xsignal1 (Qargs_out_of_range, width);
  5801               else
  5802                 {
  5803                   int new_width = frame_float (f, width, FRAME_FLOAT_WIDTH,
  5804                                                &parent_done, &outer_done, -1);
  5805 
  5806                   if (new_width > -1)
  5807                     text_width = new_width;
  5808                 }
  5809             }
  5810           else
  5811             {
  5812               CHECK_FIXNUM (width);
  5813               if ((XFIXNUM (width) < 0 || XFIXNUM (width) > INT_MAX))
  5814                 xsignal1 (Qargs_out_of_range, width);
  5815 
  5816               text_width = XFIXNUM (width) * FRAME_COLUMN_WIDTH (f);
  5817             }
  5818         }
  5819 
  5820       if (!BASE_EQ (height, Qunbound))
  5821         {
  5822           if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
  5823             {
  5824               CHECK_FIXNUM (XCDR (height));
  5825               if ((XFIXNUM (XCDR (height)) < 0 || XFIXNUM (XCDR (height)) > INT_MAX))
  5826                 xsignal1 (Qargs_out_of_range, XCDR (height));
  5827 
  5828               text_height = XFIXNUM (XCDR (height));
  5829               f->inhibit_vertical_resize = true;
  5830             }
  5831           else if (FLOATP (height))
  5832             {
  5833               double d_height = XFLOAT_DATA (height);
  5834 
  5835               if (d_height < 0.0 || d_height > 1.0)
  5836                 xsignal1 (Qargs_out_of_range, height);
  5837               else
  5838                 {
  5839                   int new_height = frame_float (f, height, FRAME_FLOAT_HEIGHT,
  5840                                                 &parent_done, &outer_done, -1);
  5841 
  5842                   if (new_height > -1)
  5843                     text_height = new_height;
  5844                 }
  5845             }
  5846           else
  5847             {
  5848               CHECK_FIXNUM (height);
  5849               if ((XFIXNUM (height) < 0) || (XFIXNUM (height) > INT_MAX))
  5850                 xsignal1 (Qargs_out_of_range, height);
  5851 
  5852               text_height = XFIXNUM (height) * FRAME_LINE_HEIGHT (f);
  5853             }
  5854         }
  5855 
  5856       user_size = gui_display_get_arg (dpyinfo, parms, Quser_size, 0, 0,
  5857                                        RES_TYPE_NUMBER);
  5858       if (!NILP (user_size) && !BASE_EQ (user_size, Qunbound))
  5859         window_prompting |= USSize;
  5860       else
  5861         window_prompting |= PSize;
  5862     }
  5863 
  5864   adjust_frame_size (f, text_width, text_height, 5, false,
  5865                      Qgui_figure_window_size);
  5866 
  5867   top = gui_display_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
  5868   left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
  5869   user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0,
  5870                                        RES_TYPE_NUMBER);
  5871   if (! BASE_EQ (top, Qunbound) || ! BASE_EQ (left, Qunbound))
  5872     {
  5873       if (EQ (top, Qminus))
  5874         {
  5875           f->top_pos = 0;
  5876           window_prompting |= YNegative;
  5877         }
  5878       else if (CONSP (top) && EQ (XCAR (top), Qminus)
  5879                && CONSP (XCDR (top))
  5880                && RANGED_FIXNUMP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
  5881         {
  5882           f->top_pos = - XFIXNUM (XCAR (XCDR (top)));
  5883           window_prompting |= YNegative;
  5884         }
  5885       else if (CONSP (top) && EQ (XCAR (top), Qplus)
  5886                && CONSP (XCDR (top))
  5887                && TYPE_RANGED_FIXNUMP (int, XCAR (XCDR (top))))
  5888         {
  5889           f->top_pos = XFIXNUM (XCAR (XCDR (top)));
  5890         }
  5891       else if (FLOATP (top))
  5892         f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
  5893                                   &outer_done, 0);
  5894       else if (BASE_EQ (top, Qunbound))
  5895         f->top_pos = 0;
  5896       else
  5897         {
  5898           f->top_pos = check_integer_range (top, INT_MIN, INT_MAX);
  5899           if (f->top_pos < 0)
  5900             window_prompting |= YNegative;
  5901         }
  5902 
  5903       if (EQ (left, Qminus))
  5904         {
  5905           f->left_pos = 0;
  5906           window_prompting |= XNegative;
  5907         }
  5908       else if (CONSP (left) && EQ (XCAR (left), Qminus)
  5909                && CONSP (XCDR (left))
  5910                && RANGED_FIXNUMP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
  5911         {
  5912           f->left_pos = - XFIXNUM (XCAR (XCDR (left)));
  5913           window_prompting |= XNegative;
  5914         }
  5915       else if (CONSP (left) && EQ (XCAR (left), Qplus)
  5916                && CONSP (XCDR (left))
  5917                && TYPE_RANGED_FIXNUMP (int, XCAR (XCDR (left))))
  5918         {
  5919           f->left_pos = XFIXNUM (XCAR (XCDR (left)));
  5920         }
  5921       else if (FLOATP (left))
  5922         f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
  5923                                    &outer_done, 0);
  5924       else if (BASE_EQ (left, Qunbound))
  5925         f->left_pos = 0;
  5926       else
  5927         {
  5928           f->left_pos = check_integer_range (left, INT_MIN, INT_MAX);
  5929           if (f->left_pos < 0)
  5930             window_prompting |= XNegative;
  5931         }
  5932 
  5933       if (!NILP (user_position) && ! BASE_EQ (user_position, Qunbound))
  5934         window_prompting |= USPosition;
  5935       else
  5936         window_prompting |= PPosition;
  5937     }
  5938 
  5939   if (window_prompting & XNegative)
  5940     {
  5941       if (window_prompting & YNegative)
  5942         f->win_gravity = SouthEastGravity;
  5943       else
  5944         f->win_gravity = NorthEastGravity;
  5945     }
  5946   else
  5947     {
  5948       if (window_prompting & YNegative)
  5949         f->win_gravity = SouthWestGravity;
  5950       else
  5951         f->win_gravity = NorthWestGravity;
  5952     }
  5953 
  5954   f->size_hint_flags = window_prompting;
  5955 
  5956   return window_prompting;
  5957 }
  5958 
  5959 
  5960 
  5961 #endif /* HAVE_WINDOW_SYSTEM */
  5962 
  5963 void
  5964 frame_make_pointer_invisible (struct frame *f)
  5965 {
  5966   if (! NILP (Vmake_pointer_invisible))
  5967     {
  5968       if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
  5969           && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
  5970         {
  5971           f->mouse_moved = 0;
  5972           FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
  5973           f->pointer_invisible = 1;
  5974         }
  5975     }
  5976 }
  5977 
  5978 void
  5979 frame_make_pointer_visible (struct frame *f)
  5980 {
  5981   /* We don't check Vmake_pointer_invisible here in case the
  5982      pointer was invisible when Vmake_pointer_invisible was set to nil.  */
  5983   if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
  5984       && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
  5985     {
  5986       FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
  5987       f->pointer_invisible = 0;
  5988     }
  5989 }
  5990 
  5991 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
  5992        Sframe_pointer_visible_p, 0, 1, 0,
  5993        doc: /* Return t if the mouse pointer displayed on FRAME is visible.
  5994 Otherwise it returns nil.  FRAME omitted or nil means the
  5995 selected frame.  This is useful when `make-pointer-invisible' is set.  */)
  5996   (Lisp_Object frame)
  5997 {
  5998   return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
  5999 }
  6000 
  6001 DEFUN ("frame--set-was-invisible", Fframe__set_was_invisible,
  6002        Sframe__set_was_invisible, 2, 2, 0,
  6003        doc: /* Set FRAME's was-invisible flag if WAS-INVISIBLE is non-nil.
  6004 This function is for internal use only.  */)
  6005   (Lisp_Object frame, Lisp_Object was_invisible)
  6006 {
  6007   struct frame *f = decode_live_frame (frame);
  6008 
  6009   f->was_invisible = !NILP (was_invisible);
  6010 
  6011   return f->was_invisible ? Qt : Qnil;
  6012 }
  6013 
  6014 #ifdef HAVE_WINDOW_SYSTEM
  6015 
  6016 DEFUN ("reconsider-frame-fonts", Freconsider_frame_fonts,
  6017        Sreconsider_frame_fonts, 1, 1, 0,
  6018        doc: /* Recreate FRAME's default font using updated font parameters.
  6019 Signal an error if FRAME is not a window system frame.  This should be
  6020 called after a `config-changed' event is received, signaling that the
  6021 parameters (such as pixel density) used by the system to open fonts
  6022 have changed.  */)
  6023   (Lisp_Object frame)
  6024 {
  6025   struct frame *f;
  6026   Lisp_Object params, font_parameter;
  6027 
  6028   f = decode_window_system_frame (frame);
  6029 
  6030   /* Kludge: if a `font' parameter was already specified,
  6031      create an alist containing just that parameter.  (bug#59371)
  6032 
  6033      This sounds so simple, right?  Well, read on below: */
  6034   params = Qnil;
  6035 
  6036   /* The difference between Qfont and Qfont_parameter is that the
  6037      latter is not set automatically by the likes of x_new_font, and
  6038      implicitly as the default face is realized.  It is only set when
  6039      the user specifically specifies a `font' frame parameter, and is
  6040      cleared the moment the frame's font becomes defined by a face
  6041      attribute, instead of through the `font' frame parameter.  */
  6042   font_parameter = get_frame_param (f, Qfont_parameter);
  6043 
  6044   if (!NILP (font_parameter))
  6045     params = list1 (Fcons (Qfont, font_parameter));
  6046 
  6047   /* First, call this to reinitialize any font backend specific
  6048      stuff.  */
  6049 
  6050   if (FRAME_RIF (f)->default_font_parameter)
  6051     FRAME_RIF (f)->default_font_parameter (f, params);
  6052 
  6053   /* For a mysterious reason, x_default_font_parameter sets Qfont to
  6054      nil in the alist!  */
  6055 
  6056   if (!NILP (font_parameter))
  6057     params = list1 (Fcons (Qfont, font_parameter));
  6058 
  6059   /* Now call this to apply the existing value(s) of the `default'
  6060      face.  */
  6061   call2 (Qface_set_after_frame_default, frame, params);
  6062 
  6063   /* Restore the value of the `font-parameter' parameter, as
  6064      `face-set-after-frame-default' will have changed it through its
  6065      calls to `set-face-attribute'.  */
  6066   if (!NILP (font_parameter))
  6067     store_frame_param (f, Qfont_parameter, font_parameter);
  6068 
  6069   return Qnil;
  6070 }
  6071 
  6072 #endif
  6073 
  6074 
  6075 /***********************************************************************
  6076                         Multimonitor data
  6077  ***********************************************************************/
  6078 
  6079 #ifdef HAVE_WINDOW_SYSTEM
  6080 
  6081 # if (defined USE_GTK || defined HAVE_PGTK || defined HAVE_NS || defined HAVE_XINERAMA \
  6082       || defined HAVE_XRANDR)
  6083 void
  6084 free_monitors (struct MonitorInfo *monitors, int n_monitors)
  6085 {
  6086   int i;
  6087   for (i = 0; i < n_monitors; ++i)
  6088     xfree (monitors[i].name);
  6089   xfree (monitors);
  6090 }
  6091 # endif
  6092 
  6093 Lisp_Object
  6094 make_monitor_attribute_list (struct MonitorInfo *monitors,
  6095                              int n_monitors,
  6096                              int primary_monitor,
  6097                              Lisp_Object monitor_frames,
  6098                              const char *source)
  6099 {
  6100   Lisp_Object attributes_list = Qnil;
  6101   Lisp_Object primary_monitor_attributes = Qnil;
  6102   int i;
  6103 
  6104   for (i = 0; i < n_monitors; ++i)
  6105     {
  6106       Lisp_Object geometry, workarea, attributes = Qnil;
  6107       struct MonitorInfo *mi = &monitors[i];
  6108 
  6109       if (mi->geom.width == 0) continue;
  6110 
  6111       workarea = list4i (mi->work.x, mi->work.y,
  6112                          mi->work.width, mi->work.height);
  6113       geometry = list4i (mi->geom.x, mi->geom.y,
  6114                          mi->geom.width, mi->geom.height);
  6115       attributes = Fcons (Fcons (Qsource, build_string (source)),
  6116                           attributes);
  6117       attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
  6118                           attributes);
  6119 #ifdef HAVE_PGTK
  6120       attributes = Fcons (Fcons (Qscale_factor, make_float (mi->scale_factor)),
  6121                           attributes);
  6122 #endif
  6123       attributes = Fcons (Fcons (Qmm_size,
  6124                                  list2i (mi->mm_width, mi->mm_height)),
  6125                           attributes);
  6126       attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
  6127       attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
  6128       if (mi->name)
  6129         attributes = Fcons (Fcons (Qname, make_string (mi->name,
  6130                                                        strlen (mi->name))),
  6131                             attributes);
  6132 
  6133       if (i == primary_monitor)
  6134         primary_monitor_attributes = attributes;
  6135       else
  6136         attributes_list = Fcons (attributes, attributes_list);
  6137     }
  6138 
  6139   if (!NILP (primary_monitor_attributes))
  6140     attributes_list = Fcons (primary_monitor_attributes, attributes_list);
  6141   return attributes_list;
  6142 }
  6143 
  6144 #endif /* HAVE_WINDOW_SYSTEM */
  6145 
  6146 
  6147 /***********************************************************************
  6148                                 Initialization
  6149  ***********************************************************************/
  6150 
  6151 static void init_frame_once_for_pdumper (void);
  6152 
  6153 void
  6154 init_frame_once (void)
  6155 {
  6156   staticpro (&Vframe_list);
  6157   staticpro (&selected_frame);
  6158   PDUMPER_IGNORE (last_nonminibuf_frame);
  6159   Vframe_list = Qnil;
  6160   selected_frame = Qnil;
  6161   pdumper_do_now_and_after_load (init_frame_once_for_pdumper);
  6162 }
  6163 
  6164 static void
  6165 init_frame_once_for_pdumper (void)
  6166 {
  6167   PDUMPER_RESET_LV (Vframe_list, Qnil);
  6168   PDUMPER_RESET_LV (selected_frame, Qnil);
  6169 }
  6170 
  6171 void
  6172 syms_of_frame (void)
  6173 {
  6174   DEFSYM (Qframep, "framep");
  6175   DEFSYM (Qframe_live_p, "frame-live-p");
  6176   DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
  6177   DEFSYM (Qframe_monitor_attributes, "frame-monitor-attributes");
  6178   DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
  6179   DEFSYM (Qexplicit_name, "explicit-name");
  6180   DEFSYM (Qheight, "height");
  6181   DEFSYM (Qicon, "icon");
  6182   DEFSYM (Qminibuffer, "minibuffer");
  6183   DEFSYM (Qundecorated, "undecorated");
  6184   DEFSYM (Qno_special_glyphs, "no-special-glyphs");
  6185   DEFSYM (Qparent_frame, "parent-frame");
  6186   DEFSYM (Qskip_taskbar, "skip-taskbar");
  6187   DEFSYM (Qno_focus_on_map, "no-focus-on-map");
  6188   DEFSYM (Qno_accept_focus, "no-accept-focus");
  6189   DEFSYM (Qz_group, "z-group");
  6190   DEFSYM (Qoverride_redirect, "override-redirect");
  6191   DEFSYM (Qdelete_before, "delete-before");
  6192   DEFSYM (Qmodeline, "modeline");
  6193   DEFSYM (Qonly, "only");
  6194   DEFSYM (Qnone, "none");
  6195   DEFSYM (Qwidth, "width");
  6196   DEFSYM (Qtext_pixels, "text-pixels");
  6197   DEFSYM (Qgeometry, "geometry");
  6198   DEFSYM (Qicon_left, "icon-left");
  6199   DEFSYM (Qicon_top, "icon-top");
  6200   DEFSYM (Qtooltip, "tooltip");
  6201   DEFSYM (Quser_position, "user-position");
  6202   DEFSYM (Quser_size, "user-size");
  6203   DEFSYM (Qwindow_id, "window-id");
  6204 #ifdef HAVE_X_WINDOWS
  6205   DEFSYM (Qouter_window_id, "outer-window-id");
  6206 #endif
  6207   DEFSYM (Qparent_id, "parent-id");
  6208   DEFSYM (Qx, "x");
  6209   DEFSYM (Qw32, "w32");
  6210   DEFSYM (Qpc, "pc");
  6211   DEFSYM (Qns, "ns");
  6212   DEFSYM (Qpgtk, "pgtk");
  6213   DEFSYM (Qhaiku, "haiku");
  6214   DEFSYM (Qvisible, "visible");
  6215   DEFSYM (Qbuffer_predicate, "buffer-predicate");
  6216   DEFSYM (Qbuffer_list, "buffer-list");
  6217   DEFSYM (Qburied_buffer_list, "buried-buffer-list");
  6218   DEFSYM (Qdisplay_type, "display-type");
  6219   DEFSYM (Qbackground_mode, "background-mode");
  6220   DEFSYM (Qnoelisp, "noelisp");
  6221   DEFSYM (Qtty_color_mode, "tty-color-mode");
  6222   DEFSYM (Qtty, "tty");
  6223   DEFSYM (Qtty_type, "tty-type");
  6224 
  6225   DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
  6226 
  6227   DEFSYM (Qfullwidth, "fullwidth");
  6228   DEFSYM (Qfullheight, "fullheight");
  6229   DEFSYM (Qfullboth, "fullboth");
  6230   DEFSYM (Qmaximized, "maximized");
  6231   DEFSYM (Qshaded, "shaded");
  6232   DEFSYM (Qx_resource_name, "x-resource-name");
  6233   DEFSYM (Qx_frame_parameter, "x-frame-parameter");
  6234 
  6235   DEFSYM (Qworkarea, "workarea");
  6236   DEFSYM (Qmm_size, "mm-size");
  6237 #ifdef HAVE_PGTK
  6238   DEFSYM (Qscale_factor, "scale-factor");
  6239 #endif
  6240   DEFSYM (Qframes, "frames");
  6241   DEFSYM (Qsource, "source");
  6242 
  6243   DEFSYM (Qframe_edges, "frame-edges");
  6244   DEFSYM (Qouter_edges, "outer-edges");
  6245   DEFSYM (Qouter_position, "outer-position");
  6246   DEFSYM (Qouter_size, "outer-size");
  6247   DEFSYM (Qnative_edges, "native-edges");
  6248   DEFSYM (Qinner_edges, "inner-edges");
  6249   DEFSYM (Qexternal_border_size, "external-border-size");
  6250   DEFSYM (Qtitle_bar_size, "title-bar-size");
  6251   DEFSYM (Qmenu_bar_external, "menu-bar-external");
  6252   DEFSYM (Qmenu_bar_size, "menu-bar-size");
  6253   DEFSYM (Qtab_bar_size, "tab-bar-size");
  6254   DEFSYM (Qtool_bar_external, "tool-bar-external");
  6255   DEFSYM (Qtool_bar_size, "tool-bar-size");
  6256   /* The following are passed to adjust_frame_size.  */
  6257   DEFSYM (Qx_set_menu_bar_lines, "x_set_menu_bar_lines");
  6258   DEFSYM (Qchange_frame_size, "change_frame_size");
  6259   DEFSYM (Qxg_frame_set_char_size, "xg_frame_set_char_size");
  6260   DEFSYM (Qx_set_window_size_1, "x_set_window_size_1");
  6261   DEFSYM (Qset_window_configuration, "set_window_configuration");
  6262   DEFSYM (Qx_create_frame_1, "x_create_frame_1");
  6263   DEFSYM (Qx_create_frame_2, "x_create_frame_2");
  6264   DEFSYM (Qgui_figure_window_size, "gui_figure_window_size");
  6265   DEFSYM (Qtip_frame, "tip_frame");
  6266   DEFSYM (Qterminal_frame, "terminal_frame");
  6267 
  6268 #ifdef HAVE_NS
  6269   DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
  6270 #endif
  6271 #ifdef NS_IMPL_COCOA
  6272   DEFSYM (Qns_appearance, "ns-appearance");
  6273   DEFSYM (Qns_transparent_titlebar, "ns-transparent-titlebar");
  6274 #endif
  6275 
  6276   DEFSYM (Qalpha, "alpha");
  6277   DEFSYM (Qalpha_background, "alpha-background");
  6278   DEFSYM (Qauto_lower, "auto-lower");
  6279   DEFSYM (Qauto_raise, "auto-raise");
  6280   DEFSYM (Qborder_color, "border-color");
  6281   DEFSYM (Qborder_width, "border-width");
  6282   DEFSYM (Qouter_border_width, "outer-border-width");
  6283   DEFSYM (Qbottom_divider_width, "bottom-divider-width");
  6284   DEFSYM (Qcursor_color, "cursor-color");
  6285   DEFSYM (Qcursor_type, "cursor-type");
  6286   DEFSYM (Qfont_backend, "font-backend");
  6287   DEFSYM (Qfullscreen, "fullscreen");
  6288   DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
  6289   DEFSYM (Qicon_name, "icon-name");
  6290   DEFSYM (Qicon_type, "icon-type");
  6291   DEFSYM (Qchild_frame_border_width, "child-frame-border-width");
  6292   DEFSYM (Qinternal_border_width, "internal-border-width");
  6293   DEFSYM (Qleft_fringe, "left-fringe");
  6294   DEFSYM (Qline_spacing, "line-spacing");
  6295   DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
  6296   DEFSYM (Qtab_bar_lines, "tab-bar-lines");
  6297   DEFSYM (Qmouse_color, "mouse-color");
  6298   DEFSYM (Qname, "name");
  6299   DEFSYM (Qright_divider_width, "right-divider-width");
  6300   DEFSYM (Qright_fringe, "right-fringe");
  6301   DEFSYM (Qscreen_gamma, "screen-gamma");
  6302   DEFSYM (Qscroll_bar_background, "scroll-bar-background");
  6303   DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
  6304   DEFSYM (Qscroll_bar_height, "scroll-bar-height");
  6305   DEFSYM (Qscroll_bar_width, "scroll-bar-width");
  6306   DEFSYM (Qsticky, "sticky");
  6307   DEFSYM (Qtitle, "title");
  6308   DEFSYM (Qtool_bar_lines, "tool-bar-lines");
  6309   DEFSYM (Qtool_bar_position, "tool-bar-position");
  6310   DEFSYM (Qunsplittable, "unsplittable");
  6311   DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
  6312   DEFSYM (Qvisibility, "visibility");
  6313   DEFSYM (Qwait_for_wm, "wait-for-wm");
  6314   DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
  6315   DEFSYM (Qno_other_frame, "no-other-frame");
  6316   DEFSYM (Qbelow, "below");
  6317   DEFSYM (Qabove_suspended, "above-suspended");
  6318   DEFSYM (Qmin_width, "min-width");
  6319   DEFSYM (Qmin_height, "min-height");
  6320   DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
  6321   DEFSYM (Qkeep_ratio, "keep-ratio");
  6322   DEFSYM (Qwidth_only, "width-only");
  6323   DEFSYM (Qheight_only, "height-only");
  6324   DEFSYM (Qleft_only, "left-only");
  6325   DEFSYM (Qtop_only, "top-only");
  6326   DEFSYM (Qiconify_top_level, "iconify-top-level");
  6327   DEFSYM (Qmake_invisible, "make-invisible");
  6328   DEFSYM (Quse_frame_synchronization, "use-frame-synchronization");
  6329   DEFSYM (Qfont_parameter, "font-parameter");
  6330 
  6331   {
  6332     int i;
  6333 
  6334     for (i = 0; i < ARRAYELTS (frame_parms); i++)
  6335       {
  6336         Lisp_Object v = (frame_parms[i].sym < 0
  6337                          ? intern_c_string (frame_parms[i].name)
  6338                          : builtin_lisp_symbol (frame_parms[i].sym));
  6339         Fput (v, Qx_frame_parameter, make_fixnum (i));
  6340       }
  6341   }
  6342 
  6343 #ifdef HAVE_WINDOW_SYSTEM
  6344   DEFVAR_LISP ("x-resource-name", Vx_resource_name,
  6345     doc: /* The name Emacs uses to look up X resources.
  6346 `x-get-resource' uses this as the first component of the instance name
  6347 when requesting resource values.
  6348 Emacs initially sets `x-resource-name' to the name under which Emacs
  6349 was invoked, or to the value specified with the `-name' or `-rn'
  6350 switches, if present.
  6351 
  6352 It may be useful to bind this variable locally around a call
  6353 to `x-get-resource'.  See also the variable `x-resource-class'.  */);
  6354   Vx_resource_name = Qnil;
  6355 
  6356   DEFVAR_LISP ("x-resource-class", Vx_resource_class,
  6357     doc: /* The class Emacs uses to look up X resources.
  6358 `x-get-resource' uses this as the first component of the instance class
  6359 when requesting resource values.
  6360 
  6361 Emacs initially sets `x-resource-class' to "Emacs".
  6362 
  6363 Setting this variable permanently is not a reasonable thing to do,
  6364 but binding this variable locally around a call to `x-get-resource'
  6365 is a reasonable practice.  See also the variable `x-resource-name'.  */);
  6366   Vx_resource_class = build_string (EMACS_CLASS);
  6367 
  6368   DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
  6369     doc: /* The lower limit of the frame opacity (alpha transparency).
  6370 The value should range from 0 (invisible) to 100 (completely opaque).
  6371 You can also use a floating number between 0.0 and 1.0.  */);
  6372   Vframe_alpha_lower_limit = make_fixnum (20);
  6373 #endif
  6374 
  6375   DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
  6376     doc: /* Alist of default values of frame parameters for frame creation.
  6377 These may be set in your init file, like this:
  6378   (setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
  6379 
  6380 These override values given in window system configuration data,
  6381 including X Windows' defaults database.
  6382 
  6383 Note that many display-related modes (like `scroll-bar-mode' or
  6384 `menu-bar-mode') alter `default-frame-alist', so if you set this
  6385 variable directly, you may be overriding other settings
  6386 unintentionally.  Instead it's often better to use
  6387 `modify-all-frames-parameters' or push new elements to the front of
  6388 this alist.
  6389 
  6390 For values specific to the first Emacs frame, see `initial-frame-alist'.
  6391 
  6392 For window-system specific values, see `window-system-default-frame-alist'.
  6393 
  6394 For values specific to the separate minibuffer frame, see
  6395 `minibuffer-frame-alist'.
  6396 
  6397 Setting this variable does not affect existing frames, only new ones.  */);
  6398   Vdefault_frame_alist = Qnil;
  6399 
  6400   DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
  6401                doc: /* Default position of vertical scroll bars on this window-system.  */);
  6402 #ifdef HAVE_WINDOW_SYSTEM
  6403 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
  6404   /* MS-Windows, macOS, and GTK have scroll bars on the right by
  6405      default.  */
  6406   Vdefault_frame_scroll_bars = Qright;
  6407 #else
  6408   Vdefault_frame_scroll_bars = Qleft;
  6409 #endif
  6410 #else
  6411   Vdefault_frame_scroll_bars = Qnil;
  6412 #endif
  6413 
  6414   DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
  6415                scroll_bar_adjust_thumb_portion_p,
  6416                doc: /* Adjust scroll bars for overscrolling for Gtk+, Motif and Haiku.
  6417 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
  6418 even if the end of the buffer is shown (i.e. overscrolling).
  6419 Set to nil if you want the thumb to be at the bottom when the end of the buffer
  6420 is shown.  Also, the thumb fills the whole scroll bar when the entire buffer
  6421 is visible.  In this case you can not overscroll.  */);
  6422   scroll_bar_adjust_thumb_portion_p = 1;
  6423 
  6424   DEFVAR_LISP ("terminal-frame", Vterminal_frame,
  6425                doc: /* The initial frame-object, which represents Emacs's stdout.  */);
  6426 
  6427   DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
  6428                doc: /* If non-nil, function to transform normal value of `mouse-position'.
  6429 `mouse-position' and `mouse-pixel-position' call this function, passing their
  6430 usual return value as argument, and return whatever this function returns.
  6431 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
  6432 which need to do mouse handling at the Lisp level.  */);
  6433   Vmouse_position_function = Qnil;
  6434 
  6435   DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
  6436                doc: /* If non-nil, clickable text is highlighted when mouse is over it.
  6437 If the value is an integer, highlighting is shown only after moving the
  6438 mouse, while keyboard input turns off the highlight even when the mouse
  6439 is over the clickable text.  However, the mouse shape still indicates
  6440 when the mouse is over clickable text.  */);
  6441   Vmouse_highlight = Qt;
  6442 
  6443   DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
  6444                doc: /* If non-nil, make mouse pointer invisible while typing.
  6445 The pointer becomes visible again when the mouse is moved.
  6446 
  6447 When using this, you might also want to disable highlighting of
  6448 clickable text.  See `mouse-highlight'.  */);
  6449   Vmake_pointer_invisible = Qt;
  6450 
  6451   DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
  6452                doc: /* Functions run after a frame was moved.
  6453 The functions are run with one arg, the frame that moved.  */);
  6454   Vmove_frame_functions = Qnil;
  6455 
  6456   DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
  6457                doc: /* Functions run before deleting a frame.
  6458 The functions are run with one arg, the frame to be deleted.
  6459 See `delete-frame'.
  6460 
  6461 Note that functions in this list may be called just before the frame is
  6462 actually deleted, or some time later (or even both when an earlier function
  6463 in `delete-frame-functions' (indirectly) calls `delete-frame'
  6464 recursively).  */);
  6465   Vdelete_frame_functions = Qnil;
  6466   DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
  6467 
  6468   DEFVAR_LISP ("after-delete-frame-functions",
  6469                Vafter_delete_frame_functions,
  6470                doc: /* Functions run after deleting a frame.
  6471 The functions are run with one arg, the frame that was deleted and
  6472 which is now dead.  */);
  6473   Vafter_delete_frame_functions = Qnil;
  6474   DEFSYM (Qafter_delete_frame_functions, "after-delete-frame-functions");
  6475 
  6476   DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
  6477                doc: /* Non-nil if Menu-Bar mode is enabled.
  6478 See the command `menu-bar-mode' for a description of this minor mode.
  6479 Setting this variable directly does not take effect;
  6480 either customize it (see the info node `Easy Customization')
  6481 or call the function `menu-bar-mode'.  */);
  6482   Vmenu_bar_mode = Qt;
  6483 
  6484   DEFVAR_LISP ("tab-bar-mode", Vtab_bar_mode,
  6485                doc: /* Non-nil if Tab-Bar mode is enabled.
  6486 See the command `tab-bar-mode' for a description of this minor mode.
  6487 Setting this variable directly does not take effect;
  6488 either customize it (see the info node `Easy Customization')
  6489 or call the function `tab-bar-mode'.  */);
  6490   Vtab_bar_mode = Qnil;
  6491 
  6492   DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
  6493                doc: /* Non-nil if Tool-Bar mode is enabled.
  6494 See the command `tool-bar-mode' for a description of this minor mode.
  6495 Setting this variable directly does not take effect;
  6496 either customize it (see the info node `Easy Customization')
  6497 or call the function `tool-bar-mode'.  */);
  6498 #ifdef HAVE_WINDOW_SYSTEM
  6499   Vtool_bar_mode = Qt;
  6500 #else
  6501   Vtool_bar_mode = Qnil;
  6502 #endif
  6503 
  6504   DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
  6505                  doc: /* Minibuffer-less frames by default use this frame's minibuffer.
  6506 Emacs consults this variable only when creating a minibuffer-less frame
  6507 and no explicit minibuffer window has been specified for that frame via
  6508 the `minibuffer' frame parameter.  Once such a frame has been created,
  6509 setting this variable does not change that frame's previous association.
  6510 
  6511 This variable is local to the current terminal and cannot be buffer-local.  */);
  6512 
  6513   DEFVAR_LISP ("resize-mini-frames", resize_mini_frames,
  6514     doc: /* Non-nil means resize minibuffer-only frames automatically.
  6515 If this is nil, do not resize minibuffer-only frames automatically.
  6516 
  6517 If this is a function, call that function with the minibuffer-only
  6518 frame that shall be resized as sole argument.  The buffer of the root
  6519 window of that frame is the buffer whose text will be eventually shown
  6520 in the minibuffer window.
  6521 
  6522 Any other non-nil value means to resize minibuffer-only frames by
  6523 calling `fit-mini-frame-to-buffer'.  */);
  6524   resize_mini_frames = Qnil;
  6525 
  6526   DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
  6527                doc: /* Non-nil if window system changes focus when you move the mouse.
  6528 You should set this variable to tell Emacs how your window manager
  6529 handles focus, since there is no way in general for Emacs to find out
  6530 automatically.
  6531 
  6532 There are three meaningful values:
  6533 
  6534 - The default nil should be used when your window manager follows a
  6535   "click-to-focus" policy where you have to click the mouse inside of a
  6536   frame in order for that frame to get focus.
  6537 
  6538 - The value t should be used when your window manager has the focus
  6539   automatically follow the position of the mouse pointer but a window
  6540   that gains focus is not raised automatically.
  6541 
  6542 - The value `auto-raise' should be used when your window manager has the
  6543   focus automatically follow the position of the mouse pointer and a
  6544   window that gains focus is raised automatically.
  6545 
  6546 If this option is non-nil, Emacs moves the mouse pointer to the frame
  6547 selected by `select-frame-set-input-focus'.  This function is used by a
  6548 number of commands like, for example, `other-frame' and `pop-to-buffer'.
  6549 If this option is nil and your focus follows mouse window manager does
  6550 not autonomously move the mouse pointer to the newly selected frame, the
  6551 previously selected window manager window might get reselected instead
  6552 immediately.
  6553 
  6554 The distinction between the values t and `auto-raise' is not needed for
  6555 "normal" frames because the window manager takes care of raising them.
  6556 Setting this to `auto-raise' will, however, override the standard
  6557 behavior of a window manager that does not automatically raise the frame
  6558 that gets focus.  Setting this to `auto-raise' is also necessary to
  6559 automatically raise child frames which are usually left alone by the
  6560 window manager.
  6561 
  6562 Note that this option does not distinguish "sloppy" focus (where the
  6563 frame that previously had focus retains focus as long as the mouse
  6564 pointer does not move into another window manager window) from "strict"
  6565 focus (where a frame immediately loses focus when it's left by the mouse
  6566 pointer).
  6567 
  6568 In order to extend a "focus follows mouse" policy to individual Emacs
  6569 windows, customize the variable `mouse-autoselect-window'.  */);
  6570   focus_follows_mouse = Qnil;
  6571 
  6572   DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
  6573                doc: /* Non-nil means resize frames pixelwise.
  6574 If this option is nil, resizing a frame rounds its sizes to the frame's
  6575 current values of `frame-char-height' and `frame-char-width'.  If this
  6576 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
  6577 by one pixel.
  6578 
  6579 With some window managers you may have to set this to non-nil in order
  6580 to set the size of a frame in pixels, to maximize frames or to make them
  6581 fullscreen.  To resize your initial frame pixelwise, set this option to
  6582 a non-nil value in your init file.  */);
  6583   frame_resize_pixelwise = 0;
  6584 
  6585   DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
  6586                doc: /* Whether frames should be resized implicitly.
  6587 If this option is nil, setting font, menu bar, tool bar, tab bar, internal
  6588 borders, fringes or scroll bars of a specific frame may resize the frame
  6589 in order to preserve the number of columns or lines it displays.  If
  6590 this option is t, no such resizing is done.  Note that the size of
  6591 fullscreen and maximized frames, the height of fullheight frames and the
  6592 width of fullwidth frames never change implicitly.
  6593 
  6594 The value of this option can be also a list of frame parameters.  In
  6595 this case, resizing is inhibited when changing a parameter that
  6596 appears in that list.  The parameters currently handled by this option
  6597 include `font', `font-backend', `internal-border-width',
  6598 `menu-bar-lines', `tool-bar-lines' and `tab-bar-lines'.
  6599 
  6600 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
  6601 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
  6602 `right-fringe' is handled as if the frame contained just one live
  6603 window.  This means, for example, that removing vertical scroll bars on
  6604 a frame containing several side by side windows will shrink the frame
  6605 width by the width of one scroll bar provided this option is nil and
  6606 keep it unchanged if this option is either t or a list containing
  6607 `vertical-scroll-bars'.
  6608 
  6609 In GTK+ and NS that use the external tool bar, the default value is
  6610 \\='(tab-bar-lines) which means that adding/removing a tab bar does
  6611 not change the frame height.  On all other types of GUI frames, the
  6612 default value is \\='(tab-bar-lines tool-bar-lines) which means that
  6613 adding/removing a tool bar or tab bar does not change the frame
  6614 height.  Otherwise it's t which means the frame size never changes
  6615 implicitly when there's no window system support.
  6616 
  6617 Note that when a frame is not large enough to accommodate a change of
  6618 any of the parameters listed above, Emacs may try to enlarge the frame
  6619 even if this option is non-nil.  */);
  6620 #if defined (HAVE_WINDOW_SYSTEM)
  6621 #if defined (USE_GTK) || defined (HAVE_NS)
  6622   frame_inhibit_implied_resize = list1 (Qtab_bar_lines);
  6623 #else
  6624   frame_inhibit_implied_resize = list2 (Qtab_bar_lines, Qtool_bar_lines);
  6625 #endif
  6626 #else
  6627   frame_inhibit_implied_resize = Qt;
  6628 #endif
  6629 
  6630   DEFVAR_LISP ("frame-size-history", frame_size_history,
  6631                doc: /* History of frame size adjustments.
  6632 If non-nil, list recording frame size adjustment.  Adjustments are
  6633 recorded only if the first element of this list is a positive number.
  6634 Adding an adjustment decrements that number by one.
  6635 
  6636 The remaining elements are the adjustments.  Each adjustment is a list
  6637 of four elements `frame', `function', `sizes' and `more'.  `frame' is
  6638 the affected frame and `function' the invoking function.  `sizes' is
  6639 usually a list of four elements `old-width', `old-height', `new-width'
  6640 and `new-height' representing the old and new sizes recorded/requested
  6641 by `function'.  `more' is a list with additional information.
  6642 
  6643 The function `frame--size-history' displays the value of this variable
  6644 in a more readable form.  */);
  6645     frame_size_history = Qnil;
  6646 
  6647   DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame,
  6648                doc: /* Non-nil means reuse hidden tooltip frames.
  6649 When this is nil, delete a tooltip frame when hiding the associated
  6650 tooltip.  When this is non-nil, make the tooltip frame invisible only,
  6651 so it can be reused when the next tooltip is shown.
  6652 
  6653 Setting this to non-nil may drastically reduce the consing overhead
  6654 incurred by creating new tooltip frames.  However, a value of non-nil
  6655 means also that intermittent changes of faces or `default-frame-alist'
  6656 are not applied when showing a tooltip in a reused frame.
  6657 
  6658 This variable is effective only with the X toolkit (and there only when
  6659 Gtk+ tooltips are not used) and on Windows.  */);
  6660   tooltip_reuse_hidden_frame = false;
  6661 
  6662   DEFVAR_BOOL ("use-system-tooltips", use_system_tooltips,
  6663                doc: /* Use the toolkit to display tooltips.
  6664 This option is only meaningful when Emacs is built with GTK+ or Haiku
  6665 windowing support, and results in tooltips that look like those
  6666 displayed by other GTK+ or Haiku programs, but will not be able to
  6667 display text properties inside tooltip text.  */);
  6668   use_system_tooltips = true;
  6669 
  6670   DEFVAR_LISP ("iconify-child-frame", iconify_child_frame,
  6671                doc: /* How to handle iconification of child frames.
  6672 This variable tells Emacs how to proceed when it is asked to iconify a
  6673 child frame.  If it is nil, `iconify-frame' will do nothing when invoked
  6674 on a child frame.  If it is `iconify-top-level', Emacs will try to
  6675 iconify the top level frame associated with this child frame instead.
  6676 If it is `make-invisible', Emacs will try to make this child frame
  6677 invisible instead.
  6678 
  6679 Any other value means to try iconifying the child frame.  Since such an
  6680 attempt is not honored by all window managers and may even lead to
  6681 making the child frame unresponsive to user actions, the default is to
  6682 iconify the top level frame instead.  */);
  6683   iconify_child_frame = Qiconify_top_level;
  6684 
  6685   DEFVAR_LISP ("frame-internal-parameters", frame_internal_parameters,
  6686                doc: /* Frame parameters specific to every frame.  */);
  6687 #ifdef HAVE_X_WINDOWS
  6688   frame_internal_parameters = list4 (Qname, Qparent_id, Qwindow_id, Qouter_window_id);
  6689 #else
  6690   frame_internal_parameters = list3 (Qname, Qparent_id, Qwindow_id);
  6691 #endif
  6692 
  6693   defsubr (&Sframep);
  6694   defsubr (&Sframe_live_p);
  6695   defsubr (&Swindow_system);
  6696   defsubr (&Sframe_windows_min_size);
  6697   defsubr (&Smake_terminal_frame);
  6698   defsubr (&Sselect_frame);
  6699   defsubr (&Shandle_switch_frame);
  6700   defsubr (&Sselected_frame);
  6701   defsubr (&Sold_selected_frame);
  6702   defsubr (&Sframe_list);
  6703   defsubr (&Sframe_parent);
  6704   defsubr (&Sframe_ancestor_p);
  6705   defsubr (&Snext_frame);
  6706   defsubr (&Sprevious_frame);
  6707   defsubr (&Slast_nonminibuf_frame);
  6708   defsubr (&Sdelete_frame);
  6709   defsubr (&Smouse_position);
  6710   defsubr (&Smouse_pixel_position);
  6711   defsubr (&Sset_mouse_position);
  6712   defsubr (&Sset_mouse_pixel_position);
  6713 #if 0
  6714   defsubr (&Sframe_configuration);
  6715   defsubr (&Srestore_frame_configuration);
  6716 #endif
  6717   defsubr (&Smake_frame_visible);
  6718   defsubr (&Smake_frame_invisible);
  6719   defsubr (&Siconify_frame);
  6720   defsubr (&Sframe_visible_p);
  6721   defsubr (&Svisible_frame_list);
  6722   defsubr (&Sraise_frame);
  6723   defsubr (&Slower_frame);
  6724   defsubr (&Sx_focus_frame);
  6725   defsubr (&Sframe_after_make_frame);
  6726   defsubr (&Sredirect_frame_focus);
  6727   defsubr (&Sframe_focus);
  6728   defsubr (&Sframe_parameters);
  6729   defsubr (&Sframe_parameter);
  6730   defsubr (&Smodify_frame_parameters);
  6731   defsubr (&Sframe_char_height);
  6732   defsubr (&Sframe_char_width);
  6733   defsubr (&Sframe_native_height);
  6734   defsubr (&Sframe_native_width);
  6735   defsubr (&Sframe_text_cols);
  6736   defsubr (&Sframe_text_lines);
  6737   defsubr (&Sframe_total_cols);
  6738   defsubr (&Sframe_total_lines);
  6739   defsubr (&Sframe_text_width);
  6740   defsubr (&Sframe_text_height);
  6741   defsubr (&Sscroll_bar_width);
  6742   defsubr (&Sscroll_bar_height);
  6743   defsubr (&Sfringe_width);
  6744   defsubr (&Sframe_child_frame_border_width);
  6745   defsubr (&Sframe_internal_border_width);
  6746   defsubr (&Sright_divider_width);
  6747   defsubr (&Sbottom_divider_width);
  6748   defsubr (&Stool_bar_pixel_width);
  6749   defsubr (&Sset_frame_height);
  6750   defsubr (&Sset_frame_width);
  6751   defsubr (&Sset_frame_size);
  6752   defsubr (&Sframe_position);
  6753   defsubr (&Sset_frame_position);
  6754   defsubr (&Sframe_pointer_visible_p);
  6755   defsubr (&Sframe__set_was_invisible);
  6756   defsubr (&Sframe_window_state_change);
  6757   defsubr (&Sset_frame_window_state_change);
  6758   defsubr (&Sframe_scale_factor);
  6759 
  6760 #ifdef HAVE_WINDOW_SYSTEM
  6761   defsubr (&Sx_get_resource);
  6762   defsubr (&Sx_parse_geometry);
  6763   defsubr (&Sreconsider_frame_fonts);
  6764 #endif
  6765 }

/* [<][>][^][v][top][bottom][index][help] */