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

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