]> code.delx.au - gnu-emacs/blobdiff - src/frame.c
Remove buggy non-native image scrolling
[gnu-emacs] / src / frame.c
index a3139173655293269a885f7e4d3db183e020e6e1..00f25f7e911869ab725158b8b694688b64e9a309 100644 (file)
@@ -1,13 +1,13 @@
 /* Generic frame functions.
 
-Copyright (C) 1993-1995, 1997, 1999-2014 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 1997, 1999-2016 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -26,7 +26,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <c-ctype.h>
 
 #include "lisp.h"
-#include "character.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
@@ -34,7 +33,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "buffer.h"
 /* These help us bind and responding to switch-frame events.  */
-#include "commands.h"
 #include "keyboard.h"
 #include "frame.h"
 #include "blockinput.h"
@@ -42,7 +40,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "termhooks.h"
 #include "dispextern.h"
 #include "window.h"
-#include "font.h"
 #ifdef HAVE_WINDOW_SYSTEM
 #include "fontset.h"
 #endif
@@ -55,71 +52,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "widget.h"
 #endif
 
-#ifdef HAVE_NS
-Lisp_Object Qns_parse_geometry;
-#endif
-
-Lisp_Object Qframep, Qframe_live_p;
-Lisp_Object Qicon, Qmodeline;
-Lisp_Object Qonly, Qnone;
-Lisp_Object Qx, Qw32, Qpc, Qns;
-Lisp_Object Qvisible;
-Lisp_Object Qdisplay_type;
-static Lisp_Object Qbackground_mode;
-Lisp_Object Qnoelisp;
-
-static Lisp_Object Qx_frame_parameter;
-Lisp_Object Qx_resource_name;
-Lisp_Object Qterminal;
-
-/* Frame parameters (set or reported).  */
-
-Lisp_Object Qauto_raise, Qauto_lower;
-Lisp_Object Qborder_color, Qborder_width;
-Lisp_Object Qcursor_color, Qcursor_type;
-Lisp_Object Qheight, Qwidth;
-Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
-Lisp_Object Qtooltip;
-Lisp_Object Qinternal_border_width;
-Lisp_Object Qright_divider_width, Qbottom_divider_width;
-Lisp_Object Qmouse_color;
-Lisp_Object Qminibuffer;
-Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
-Lisp_Object Qscroll_bar_height, Qhorizontal_scroll_bars;
-Lisp_Object Qvisibility;
-Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
-Lisp_Object Qscreen_gamma;
-Lisp_Object Qline_spacing;
-static Lisp_Object Quser_position, Quser_size;
-Lisp_Object Qwait_for_wm;
-static Lisp_Object Qwindow_id;
-#ifdef HAVE_X_WINDOWS
-static Lisp_Object Qouter_window_id;
-#endif
-Lisp_Object Qparent_id;
-Lisp_Object Qtitle, Qname;
-static Lisp_Object Qexplicit_name;
-Lisp_Object Qunsplittable;
-Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position;
-Lisp_Object Qleft_fringe, Qright_fringe;
-Lisp_Object Qbuffer_predicate;
-static Lisp_Object Qbuffer_list, Qburied_buffer_list;
-Lisp_Object Qtty_color_mode;
-Lisp_Object Qtty, Qtty_type;
-
-Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth, Qmaximized;
-Lisp_Object Qsticky;
-Lisp_Object Qfont_backend;
-Lisp_Object Qalpha;
-
-Lisp_Object Qface_set_after_frame_default;
-
-static Lisp_Object Qfocus_in_hook;
-static Lisp_Object Qfocus_out_hook;
-static Lisp_Object Qdelete_frame_functions;
-static Lisp_Object Qframe_windows_min_size;
-static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
-
 /* The currently selected frame.  */
 
 Lisp_Object selected_frame;
@@ -132,6 +64,13 @@ static struct frame *last_nonminibuf_frame;
 /* False means there are no visible garbaged frames.  */
 bool frame_garbaged;
 
+/* The default tool bar height for future frames.  */
+#if defined USE_GTK || defined HAVE_NS
+enum { frame_default_tool_bar_height = 0 };
+#else
+int frame_default_tool_bar_height;
+#endif
+
 #ifdef HAVE_WINDOW_SYSTEM
 static void x_report_frame_params (struct frame *, Lisp_Object *);
 #endif
@@ -207,16 +146,61 @@ get_frame_param (register struct frame *frame, Lisp_Object prop)
   return Fcdr (tem);
 }
 
+
+void
+frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
+                       int width, int height, Lisp_Object rest)
+{
+  Lisp_Object frame;
+
+  XSETFRAME (frame, f);
+  if (CONSP (frame_size_history)
+      && INTEGERP (XCAR (frame_size_history))
+      && 0 < XINT (XCAR (frame_size_history)))
+    frame_size_history =
+      Fcons (make_number (XINT (XCAR (frame_size_history)) - 1),
+            Fcons (list4
+                   (frame, fun_symbol,
+                    ((width > 0)
+                     ? list4 (make_number (FRAME_TEXT_WIDTH (f)),
+                              make_number (FRAME_TEXT_HEIGHT (f)),
+                              make_number (width),
+                              make_number (height))
+                     : Qnil),
+                    rest),
+                   XCDR (frame_size_history)));
+}
+
+
 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
    state of frame F would be affected by a vertical (horizontal if
-   HORIZONTAL is true) resize.  */
+   HORIZONTAL is true) resize.  PARAMETER is the symbol of the frame
+   parameter that is changed.  */
 bool
-frame_inhibit_resize (struct frame *f, bool horizontal)
+frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
 {
-
-  return (frame_inhibit_implied_resize
-         || !NILP (get_frame_param (f, Qfullscreen))
-         || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
+  Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+  bool inhibit
+    = (f->after_make_frame
+       ? (EQ (frame_inhibit_implied_resize, Qt)
+         || (CONSP (frame_inhibit_implied_resize)
+             && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
+         || (horizontal
+             && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullheight))
+         || (!horizontal
+             && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullwidth))
+         || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+       : ((horizontal && f->inhibit_horizontal_resize)
+         || (!horizontal && f->inhibit_vertical_resize)));
+  if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
+    frame_size_history_add
+      (f, Qframe_inhibit_resize, 0, 0,
+       list5 (horizontal ? Qt : Qnil, parameter,
+             f->after_make_frame ? Qt : Qnil,
+             frame_inhibit_implied_resize,
+             fullscreen));
+
+  return inhibit;
 }
 
 static void
@@ -255,10 +239,10 @@ DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
        doc: /* Return non-nil if OBJECT is a frame.
 Value is:
   t for a termcap frame (a character-only terminal),
'x' for an Emacs frame that is really an X window,
'w32' for an Emacs frame that is a window on MS-Windows display,
'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
'pc' for a direct-write MS-DOS frame.
`x' for an Emacs frame that is really an X window,
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
 See also `frame-live-p'.  */)
   (Lisp_Object object)
 {
@@ -300,10 +284,10 @@ DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
        doc: /* The name of the window system that FRAME is displaying through.
 The value is a symbol:
  nil for a termcap frame (a character-only terminal),
'x' for an Emacs frame that is really an X window,
'w32' for an Emacs frame that is a window on MS-Windows display,
'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
'pc' for a direct-write MS-DOS frame.
`x' for an Emacs frame that is really an X window,
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
 
 FRAME defaults to the currently selected frame.
 
@@ -327,55 +311,76 @@ predicates which report frame's specific UI-related capabilities.  */)
     return type;
 }
 
+/* Placeholder used by temacs -nw before window.el is loaded.  */
+DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
+       Sframe_windows_min_size, 4, 4, 0,
+       doc: /* */
+       attributes: const)
+     (Lisp_Object frame, Lisp_Object horizontal,
+      Lisp_Object ignore, Lisp_Object pixelwise)
+{
+  return make_number (0);
+}
+
 static int
-frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, Lisp_Object pixelwise)
+frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
+                       Lisp_Object ignore, Lisp_Object pixelwise)
 {
-  return XINT (call3 (Qframe_windows_min_size, frame, horizontal, pixelwise));
+  return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
+                     ignore, pixelwise));
 }
 
 
 /* Make sure windows sizes of frame F are OK.  new_width and new_height
    are in pixels.  A value of -1 means no change is requested for that
    size (but the frame may still have to be resized to accommodate
-   windows with their minimum sizes.
+   windows with their minimum sizes).  This can either issue a request
+   to resize the frame externally (via x_set_window_size), to resize the
+   frame internally (via resize_frame_windows) or do nothing at all.
 
    The argument INHIBIT can assume the following values:
 
    0 means to unconditionally call x_set_window_size even if sizes
-   apparently do not change.  Fx_create_frame uses this to pass the
-   initial size to the window manager.
+     apparently do not change.  Fx_create_frame uses this to pass the
+     initial size to the window manager.
 
-   1 means to call x_set_window_size iff the pixel size really changes.
-   Fset_frame_size, Fset_frame_height, ... use this.
+   1 means to call x_set_window_size if the outer frame size really
+     changes.  Fset_frame_size, Fset_frame_height, ... use this.
 
-   2 means to unconditionally call x_set_window_size provided
-   frame_inhibit_resize allows it.  The menu bar code uses this.
+   2 means to call x_set_window_size provided frame_inhibit_resize
+     allows it.  The menu and tool bar code use this ("3" won't work
+     here in general because menu and tool bar are often not counted in
+     the frame's text height).
 
-   3 means call x_set_window_size iff window minimum sizes must be
-   preserved or frame_inhibit_resize allows it, x_set_left_fringe,
-   x_set_scroll_bar_width, ... use this.
+   3 means call x_set_window_size if window minimum sizes must be
+     preserved or frame_inhibit_resize allows it.  x_set_left_fringe,
+     x_set_scroll_bar_width, x_new_font ... use (or should use) this.
 
-   4 means call x_set_window_size iff window minimum sizes must be
-   preserved.  x_set_tool_bar_lines, x_set_right_divider_width, ... use
-   this.  BUT maybe the toolbar code shouldn't ....
+   4 means call x_set_window_size only if window minimum sizes must be
+     preserved.  x_set_right_divider_width, x_set_border_width and the
+     code responsible for wrapping the tool bar use this.
 
    5 means to never call x_set_window_size.  change_frame_size uses
-   this.
+     this.
 
-   For 2 and 3 note that if frame_inhibit_resize inhibits resizing and
-   minimum sizes are not violated no internal resizing takes place
-   either.  For 2, 3, 4 and 5 note that even if no x_set_window_size
-   call is issued, window sizes may have to be adjusted in order to
-   support minimum size constraints for the frame's windows.
+   Note that even when x_set_window_size is not called, individual
+   windows may have to be resized (via `window--sanitize-window-sizes')
+   in order to support minimum size constraints.
 
-   PRETEND is as for change_frame_size.  */
+   PRETEND is as for change_frame_size.  PARAMETER, if non-nil, is the
+   symbol of the parameter changed (like `menu-bar-lines', `font', ...).
+   This is passed on to frame_inhibit_resize to let the latter decide on
+   a case-by-case basis whether the frame may be resized externally.  */
 void
-adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, bool pretend)
+adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
+                  bool pretend, Lisp_Object parameter)
 {
   int unit_width = FRAME_COLUMN_WIDTH (f);
   int unit_height = FRAME_LINE_HEIGHT (f);
   int old_pixel_width = FRAME_PIXEL_WIDTH (f);
   int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
+  int old_cols = FRAME_COLS (f);
+  int old_lines = FRAME_LINES (f);
   int new_pixel_width, new_pixel_height;
   /* The following two values are calculated from the old frame pixel
      sizes and any "new" settings for tool bar, menu bar and internal
@@ -389,7 +394,7 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
   int old_windows_width = WINDOW_PIXEL_WIDTH (r);
   int old_windows_height
     = (WINDOW_PIXEL_HEIGHT (r)
-       + (FRAME_HAS_MINIBUF_P (f)
+       + ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
          ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
          : 0));
   int new_windows_width, new_windows_height;
@@ -403,23 +408,30 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
   Lisp_Object frame;
 
   XSETFRAME (frame, f);
+
+  frame_size_history_add
+    (f, Qadjust_frame_size_1, new_text_width, new_text_height,
+     list2 (parameter, make_number (inhibit)));
+
   /* The following two values are calculated from the old window body
      sizes and any "new" settings for scroll bars, dividers, fringes and
      margins (though the latter should have been processed already).  */
-  min_windows_width = frame_windows_min_size (frame, Qt, Qt);
-  min_windows_height = frame_windows_min_size (frame, Qnil, Qt);
+  min_windows_width
+    = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
+  min_windows_height
+    = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
 
   if (inhibit >= 2 && inhibit <= 4)
-    /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay
-       within the limits and either frame_inhibit_resize tells us to do
-       so or INHIBIT equals 4.  */
+    /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
+       within the limits and either resizing is inhibited or INHIBIT
+       equals 4.  */
     {
-      inhibit_horizontal = ((windows_width >= min_windows_width
-                            && (inhibit == 4 || frame_inhibit_resize (f, true)))
-                           ? true : false);
-      inhibit_vertical = ((windows_height >= min_windows_height
-                          && (inhibit == 4 || frame_inhibit_resize (f, false)))
-                         ? true : false);
+      inhibit_horizontal = (windows_width >= min_windows_width
+                            && (inhibit == 4
+                                || frame_inhibit_resize (f, true, parameter)));
+      inhibit_vertical = (windows_height >= min_windows_height
+                          && (inhibit == 4
+                              || frame_inhibit_resize (f, false, parameter)));
     }
   else
     /* Otherwise inhibit if INHIBIT equals 5.  */
@@ -448,7 +460,7 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f)
-      && f->official
+      && f->can_x_set_window_size
       && ((!inhibit_horizontal
           && (new_pixel_width != old_pixel_width
               || inhibit == 0 || inhibit == 2))
@@ -466,6 +478,11 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
       else if (inhibit_vertical)
        new_text_height = old_text_height;
 
+      frame_size_history_add
+       (f, Qadjust_frame_size_2, new_text_width, new_text_height,
+        list2 (inhibit_horizontal ? Qt : Qnil,
+               inhibit_vertical ? Qt : Qnil));
+
       x_set_window_size (f, 0, new_text_width, new_text_height, 1);
       f->resized_p = true;
 
@@ -478,7 +495,9 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
       && new_windows_width == old_windows_width
       && new_windows_height == old_windows_height
       && new_pixel_width == old_pixel_width
-      && new_pixel_height == old_pixel_height)
+      && new_pixel_height == old_pixel_height
+      && new_cols == old_cols
+      && new_lines == old_lines)
     /* No change.  Sanitize window sizes and return.  */
     {
       sanitize_window_sizes (frame, Qt);
@@ -490,10 +509,13 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
   block_input ();
 
 #ifdef MSDOS
-  /* We only can set screen dimensions to certain values supported
-     by our video hardware.  Try to find the smallest size greater
-     or equal to the requested dimensions.  */
-  dos_set_window_size (&new_lines, &new_cols);
+  /* We only can set screen dimensions to certain values supported by
+     our video hardware.  Try to find the smallest size greater or
+     equal to the requested dimensions, while accounting for the fact
+     that the menu-bar lines are not counted in the frame height.  */
+  int dos_new_lines = new_lines + FRAME_TOP_MARGIN (f);
+  dos_set_window_size (&dos_new_lines, &new_cols);
+  new_lines = dos_new_lines - FRAME_TOP_MARGIN (f);
 #endif
 
   if (new_windows_width != old_windows_width)
@@ -514,6 +536,8 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
        }
 #endif
     }
+  else if (new_cols != old_cols)
+    call2 (Qwindow_pixel_to_total, frame, Qt);
 
   if (new_windows_height != old_windows_height
       /* When the top margin has changed we have to recalculate the top
@@ -528,6 +552,13 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
        FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
     }
+  else if (new_lines != old_lines)
+    call2 (Qwindow_pixel_to_total, frame, Qnil);
+
+  frame_size_history_add
+    (f, Qadjust_frame_size_3, new_text_width, new_text_height,
+     list4 (make_number (old_pixel_width), make_number (old_pixel_height),
+           make_number (new_pixel_width), make_number (new_pixel_height)));
 
   /* Assign new sizes.  */
   FRAME_TEXT_WIDTH (f) = new_text_width;
@@ -567,15 +598,22 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
   run_window_configuration_change_hook (f);
 }
 
+/* Allocate basically initialized frame.  */
+
+static struct frame *
+allocate_frame (void)
+{
+  return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
+}
 
 struct frame *
 make_frame (bool mini_p)
 {
   Lisp_Object frame;
-  register struct frame *f;
-  register struct window *rw, *mw;
-  register Lisp_Object root_window;
-  register Lisp_Object mini_window;
+  struct frame *f;
+  struct window *rw, *mw IF_LINT (= NULL);
+  Lisp_Object root_window;
+  Lisp_Object mini_window;
 
   f = allocate_frame ();
   XSETFRAME (frame, f);
@@ -593,7 +631,12 @@ make_frame (bool mini_p)
   f->wants_modeline = true;
   f->redisplay = true;
   f->garbaged = true;
-  f->official = false;
+  f->can_x_set_window_size = false;
+  f->after_make_frame = false;
+  f->inhibit_horizontal_resize = false;
+  f->inhibit_vertical_resize = false;
+  f->tool_bar_redisplayed = false;
+  f->tool_bar_resized = false;
   f->column_width = 1;  /* !FRAME_WINDOW_P value.  */
   f->line_height = 1;  /* !FRAME_WINDOW_P value.  */
 #ifdef HAVE_WINDOW_SYSTEM
@@ -694,10 +737,10 @@ make_frame (bool mini_p)
    default (the global minibuffer).  */
 
 struct frame *
-make_frame_without_minibuffer (register Lisp_Object mini_window, KBOARD *kb, Lisp_Object display)
+make_frame_without_minibuffer (Lisp_Object mini_window, KBOARD *kb,
+                              Lisp_Object display)
 {
-  register struct frame *f;
-  struct gcpro gcpro1;
+  struct frame *f;
 
   if (!NILP (mini_window))
     CHECK_LIVE_WINDOW (mini_window);
@@ -718,11 +761,9 @@ make_frame_without_minibuffer (register Lisp_Object mini_window, KBOARD *kb, Lis
           Lisp_Object frame_dummy;
 
           XSETFRAME (frame_dummy, f);
-          GCPRO1 (frame_dummy);
          /* If there's no minibuffer frame to use, create one.  */
          kset_default_minibuffer_frame
            (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
-          UNGCPRO;
        }
 
       mini_window
@@ -829,11 +870,17 @@ make_initial_frame (void)
   /* The default value of menu-bar-mode is t.  */
   set_menu_bar_lines (f, make_number (1), Qnil);
 
+  /* Allocate glyph matrices.  */
+  adjust_frame_glyphs (f);
+
   if (!noninteractive)
     init_frame_faces (f);
 
   last_nonminibuf_frame = f;
 
+  f->can_x_set_window_size = true;
+  f->after_make_frame = true;
+
   return f;
 }
 
@@ -934,7 +981,7 @@ except when you want to create a new frame on another terminal.
 In that case, the `tty' parameter specifies the device file to open,
 and the `tty-type' parameter specifies the terminal type.  Example:
 
-   (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
+   (make-terminal-frame \\='((tty . "/dev/pts/5") (tty-type . "xterm")))
 
 Note that changing the size of one terminal frame automatically
 affects all frames on the same terminal device.  */)
@@ -964,7 +1011,7 @@ affects all frames on the same terminal device.  */)
     if (CONSP (terminal))
       {
         terminal = XCDR (terminal);
-        t = get_terminal (terminal, 1);
+        t = decode_live_terminal (terminal);
       }
 #ifdef MSDOS
     if (t && t != the_only_display_info.terminal)
@@ -1004,7 +1051,8 @@ affects all frames on the same terminal device.  */)
   {
     int width, height;
     get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
-    adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0);
+    adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
+                      5, 0, Qterminal_frame);
   }
 
   adjust_frame_glyphs (f);
@@ -1026,6 +1074,10 @@ affects all frames on the same terminal device.  */)
      be copied as well.  */
   for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
     XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
+
+  f->can_x_set_window_size = true;
+  f->after_make_frame = true;
+
   return frame;
 }
 
@@ -1178,7 +1230,7 @@ This function returns FRAME, or nil if FRAME has been deleted.  */)
   return do_switch_frame (frame, 1, 0, norecord);
 }
 
-DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "e",
+DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
        doc: /* Handle a switch-frame event EVENT.
 Switch-frame events are usually bound to this function.
 A switch-frame event tells Emacs that the window manager has requested
@@ -1191,7 +1243,7 @@ to that frame.  */)
 {
   /* Preserve prefix arg that the command loop just cleared.  */
   kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
-  Frun_hooks (1, &Qmouse_leave_buffer_hook);
+  run_hook (Qmouse_leave_buffer_hook);
   /* `switch-frame' implies a focus in.  */
   call1 (intern ("handle-focus-in"), event);
   return do_switch_frame (event, 0, 0, Qnil);
@@ -1506,7 +1558,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
        }
     }
 
-  is_tooltip_frame = !NILP (Fframe_parameter (frame, intern ("tooltip")));
+  is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
 
   /* Run `delete-frame-functions' unless FORCE is `noelisp' or
      frame is a tooltip.  FORCE is set to `noelisp' when handling
@@ -1774,9 +1826,10 @@ DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
        doc: /* Delete FRAME, permanently eliminating it from use.
 FRAME defaults to the selected frame.
 
-A frame may not be deleted if its minibuffer is used by other frames.
-Normally, you may not delete a frame if all other frames are invisible,
-but if the second optional argument FORCE is non-nil, you may do so.
+A frame may not be deleted if its minibuffer serves as surrogate
+minibuffer for another frame.  Normally, you may not delete a frame if
+all other frames are invisible, but if the second optional argument
+FORCE is non-nil, you may do so.
 
 This function runs `delete-frame-functions' before actually
 deleting the frame, unless the frame is a tooltip.
@@ -1805,7 +1858,6 @@ and returns whatever that function returns.  */)
   struct frame *f;
   Lisp_Object lispy_dummy;
   Lisp_Object x, y, retval;
-  struct gcpro gcpro1;
 
   f = SELECTED_FRAME ();
   x = y = Qnil;
@@ -1831,10 +1883,9 @@ and returns whatever that function returns.  */)
     }
   XSETFRAME (lispy_dummy, f);
   retval = Fcons (lispy_dummy, Fcons (x, y));
-  GCPRO1 (retval);
   if (!NILP (Vmouse_position_function))
     retval = call1 (Vmouse_position_function, retval);
-  RETURN_UNGCPRO (retval);
+  return retval;
 }
 
 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
@@ -1851,7 +1902,6 @@ and nil for X and Y.  */)
   struct frame *f;
   Lisp_Object lispy_dummy;
   Lisp_Object x, y, retval;
-  struct gcpro gcpro1;
 
   f = SELECTED_FRAME ();
   x = y = Qnil;
@@ -1869,10 +1919,9 @@ and nil for X and Y.  */)
 
   XSETFRAME (lispy_dummy, f);
   retval = Fcons (lispy_dummy, Fcons (x, y));
-  GCPRO1 (retval);
   if (!NILP (Vmouse_position_function))
     retval = call1 (Vmouse_position_function, retval);
-  RETURN_UNGCPRO (retval);
+  return retval;
 }
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -2244,6 +2293,27 @@ If there is no window system support, this function does nothing.  */)
   return Qnil;
 }
 
+DEFUN ("frame-after-make-frame",
+       Fframe_after_make_frame,
+       Sframe_after_make_frame, 2, 2, 0,
+       doc: /* Mark FRAME as made.
+FRAME nil means use the selected frame.  Second argument MADE non-nil
+means functions on `window-configuration-change-hook' are called
+whenever the window configuration of FRAME changes.  MADE nil means
+these functions are not called.
+
+This function is currently called by `make-frame' only and should be
+otherwise used with utter care to avoid that running functions on
+`window-configuration-change-hook' is impeded forever.  */)
+  (Lisp_Object frame, Lisp_Object made)
+{
+  struct frame *f = decode_live_frame (frame);
+  f->after_make_frame = !NILP (made);
+  f->inhibit_horizontal_resize = false;
+  f->inhibit_vertical_resize = false;
+  return made;
+}
+
 \f
 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame.  */
 
@@ -2441,13 +2511,11 @@ If FRAME is omitted or nil, return information on the currently selected frame.
   Lisp_Object alist;
   struct frame *f = decode_any_frame (frame);
   int height, width;
-  struct gcpro gcpro1;
 
   if (!FRAME_LIVE_P (f))
     return Qnil;
 
   alist = Fcopy_alist (f->param_alist);
-  GCPRO1 (alist);
 
   if (!FRAME_WINDOW_P (f))
     {
@@ -2476,7 +2544,7 @@ If FRAME is omitted or nil, return information on the currently selected frame.
       else
        store_in_alist (&alist, Qbackground_color,
                        tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
-      store_in_alist (&alist, intern ("font"),
+      store_in_alist (&alist, Qfont,
                      build_string (FRAME_MSDOS_P (f)
                                    ? "ms-dos"
                                    : FRAME_W32_P (f) ? "w32term"
@@ -2517,7 +2585,6 @@ If FRAME is omitted or nil, return information on the currently selected frame.
       store_in_alist (&alist, Qmenu_bar_lines, lines);
     }
 
-  UNGCPRO;
   return alist;
 }
 
@@ -2555,7 +2622,12 @@ If FRAME is nil, describe the currently selected frame.  */)
                 important when param_alist's notion of colors is
                 "unspecified".  We need to do the same here.  */
              if (STRINGP (value) && !FRAME_WINDOW_P (f))
-               value = frame_unspecified_color (f, value);
+               {
+                 Lisp_Object tem = frame_unspecified_color (f, value);
+
+                 if (!NILP (tem))
+                   value = tem;
+               }
            }
          else
            value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
@@ -2575,13 +2647,16 @@ If FRAME is nil, describe the currently selected frame.  */)
 
 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
        Smodify_frame_parameters, 2, 2, 0,
-       doc: /* Modify the parameters of frame FRAME according to ALIST.
+       doc: /* Modify FRAME according to new values of its parameters in ALIST.
 If FRAME is nil, it defaults to the selected frame.
 ALIST is an alist of parameters to change and their new values.
 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
-The meaningful PARMs depend on the kind of frame.
-Undefined PARMs are ignored, but stored in the frame's parameter list
-so that `frame-parameters' will return them.
+Which PARMs are meaningful depends on the kind of frame.
+The meaningful parameters are acted upon, i.e. the frame is changed
+according to their new values, and are also stored in the frame's
+parameter list so that `frame-parameters' will return them.
+PARMs that are not meaningful are still stored in the frame's parameter
+list, but are otherwise ignored.
 
 The value of frame parameter FOO can also be accessed
 as a frame-local binding for the variable FOO, if you have
@@ -2828,11 +2903,15 @@ DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_widt
 }
 
 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
-       doc: /* Specify that the frame FRAME has HEIGHT text lines.
+       doc: /* Set text height of frame FRAME to HEIGHT lines.
 Optional third arg PRETEND non-nil means that redisplay should use
 HEIGHT lines but that the idea of the actual height of the frame should
-not be changed.  Optional fourth argument PIXELWISE non-nil means that
-FRAME should be HEIGHT pixels high.  */)
+not be changed.
+
+Optional fourth argument PIXELWISE non-nil means that FRAME should be
+HEIGHT pixels high.  Note: When `frame-resize-pixelwise' is nil, some
+window managers may refuse to honor a HEIGHT that is not an integer
+multiple of the default frame font height.  */)
   (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
 {
   struct frame *f = decode_live_frame (frame);
@@ -2843,18 +2922,21 @@ FRAME should be HEIGHT pixels high.  */)
   pixel_height = (!NILP (pixelwise)
                  ? XINT (height)
                  : XINT (height) * FRAME_LINE_HEIGHT (f));
-  if (pixel_height != FRAME_TEXT_HEIGHT (f))
-    adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend));
+  adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
 
   return Qnil;
 }
 
 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
-       doc: /* Specify that the frame FRAME has WIDTH columns.
+       doc: /* Set text width of frame FRAME to WIDTH columns.
 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
 columns but that the idea of the actual width of the frame should not
-be changed.  Optional fourth argument PIXELWISE non-nil means that FRAME
-should be WIDTH pixels wide.  */)
+be changed.
+
+Optional fourth argument PIXELWISE non-nil means that FRAME should be
+WIDTH pixels wide.  Note: When `frame-resize-pixelwise' is nil, some
+window managers may refuse to honor a WIDTH that is not an integer
+multiple of the default frame font width.  */)
   (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
 {
   struct frame *f = decode_live_frame (frame);
@@ -2865,15 +2947,18 @@ should be WIDTH pixels wide.  */)
   pixel_width = (!NILP (pixelwise)
                 ? XINT (width)
                 : XINT (width) * FRAME_COLUMN_WIDTH (f));
-  if (pixel_width != FRAME_TEXT_WIDTH (f))
-    adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend));
+  adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
 
   return Qnil;
 }
 
 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
-       doc: /* Sets size of FRAME to WIDTH by HEIGHT, measured in characters.
-Optional argument PIXELWISE non-nil means to measure in pixels.  */)
+       doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
+Optional argument PIXELWISE non-nil means to measure in pixels.  Note:
+When `frame-resize-pixelwise' is nil, some window managers may refuse to
+honor a WIDTH that is not an integer multiple of the default frame font
+width or a HEIGHT that is not an integer multiple of the default frame
+font height.  */)
   (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
 {
   struct frame *f = decode_live_frame (frame);
@@ -2888,32 +2973,45 @@ Optional argument PIXELWISE non-nil means to measure in pixels.  */)
   pixel_height = (!NILP (pixelwise)
                  ? XINT (height)
                  : XINT (height) * FRAME_LINE_HEIGHT (f));
-
-  if (pixel_width != FRAME_TEXT_WIDTH (f)
-      || pixel_height != FRAME_TEXT_HEIGHT (f))
-    adjust_frame_size (f, pixel_width, pixel_height, 1, 0);
+  adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
 
   return Qnil;
 }
 
+DEFUN ("frame-position", Fframe_position,
+       Sframe_position, 0, 1, 0,
+       doc: /* Return top left corner of FRAME in pixels.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is a cons (x, y) of the coordinates of the top left corner of
+FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
+display.  */)
+     (Lisp_Object frame)
+{
+  register struct frame *f = decode_live_frame (frame);
+
+  return Fcons (make_number (f->left_pos), make_number (f->top_pos));
+}
+
 DEFUN ("set-frame-position", Fset_frame_position,
        Sset_frame_position, 3, 3, 0,
-       doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
-If FRAME is nil, the selected frame is used.  XOFFSET and YOFFSET are
-actually the position of the upper left corner of the frame.  Negative
-values for XOFFSET or YOFFSET are interpreted relative to the rightmost
-or bottommost possible position (that stays within the screen).  */)
-  (Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
+       doc: /* Set position of FRAME to (X, Y).
+FRAME must be a live frame and defaults to the selected one.  X and Y,
+if positive, specify the coordinate of the left and top edge of FRAME's
+outer frame in pixels relative to an origin (0, 0) of FRAME's display.
+If any of X or Y is negative, it specifies the coordinates of the right
+or bottom edge of the outer frame of FRAME relative to the right or
+bottom edge of FRAME's display.  */)
+  (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
 {
   register struct frame *f = decode_live_frame (frame);
 
-  CHECK_TYPE_RANGED_INTEGER (int, xoffset);
-  CHECK_TYPE_RANGED_INTEGER (int, yoffset);
+  CHECK_TYPE_RANGED_INTEGER (int, x);
+  CHECK_TYPE_RANGED_INTEGER (int, y);
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
-    x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
+    x_set_offset (f, XINT (x), XINT (y), 1);
 #endif
 
   return Qt;
@@ -2933,48 +3031,48 @@ or bottommost possible position (that stays within the screen).  */)
 
 struct frame_parm_table {
   const char *name;
-  Lisp_Object *variable;
+  int sym;
 };
 
 static const struct frame_parm_table frame_parms[] =
 {
-  {"auto-raise",               &Qauto_raise},
-  {"auto-lower",               &Qauto_lower},
-  {"background-color",         0},
-  {"border-color",             &Qborder_color},
-  {"border-width",             &Qborder_width},
-  {"cursor-color",             &Qcursor_color},
-  {"cursor-type",              &Qcursor_type},
-  {"font",                     0},
-  {"foreground-color",         0},
-  {"icon-name",                        &Qicon_name},
-  {"icon-type",                        &Qicon_type},
-  {"internal-border-width",    &Qinternal_border_width},
-  {"right-divider-width",      &Qright_divider_width},
-  {"bottom-divider-width",     &Qbottom_divider_width},
-  {"menu-bar-lines",           &Qmenu_bar_lines},
-  {"mouse-color",              &Qmouse_color},
-  {"name",                     &Qname},
-  {"scroll-bar-width",         &Qscroll_bar_width},
-  {"scroll-bar-height",                &Qscroll_bar_height},
-  {"title",                    &Qtitle},
-  {"unsplittable",             &Qunsplittable},
-  {"vertical-scroll-bars",     &Qvertical_scroll_bars},
-  {"horizontal-scroll-bars",   &Qhorizontal_scroll_bars},
-  {"visibility",               &Qvisibility},
-  {"tool-bar-lines",           &Qtool_bar_lines},
-  {"scroll-bar-foreground",    &Qscroll_bar_foreground},
-  {"scroll-bar-background",    &Qscroll_bar_background},
-  {"screen-gamma",             &Qscreen_gamma},
-  {"line-spacing",             &Qline_spacing},
-  {"left-fringe",              &Qleft_fringe},
-  {"right-fringe",             &Qright_fringe},
-  {"wait-for-wm",              &Qwait_for_wm},
-  {"fullscreen",                &Qfullscreen},
-  {"font-backend",             &Qfont_backend},
-  {"alpha",                    &Qalpha},
-  {"sticky",                   &Qsticky},
-  {"tool-bar-position",                &Qtool_bar_position},
+  {"auto-raise",               SYMBOL_INDEX (Qauto_raise)},
+  {"auto-lower",               SYMBOL_INDEX (Qauto_lower)},
+  {"background-color",         -1},
+  {"border-color",             SYMBOL_INDEX (Qborder_color)},
+  {"border-width",             SYMBOL_INDEX (Qborder_width)},
+  {"cursor-color",             SYMBOL_INDEX (Qcursor_color)},
+  {"cursor-type",              SYMBOL_INDEX (Qcursor_type)},
+  {"font",                     -1},
+  {"foreground-color",         -1},
+  {"icon-name",                        SYMBOL_INDEX (Qicon_name)},
+  {"icon-type",                        SYMBOL_INDEX (Qicon_type)},
+  {"internal-border-width",    SYMBOL_INDEX (Qinternal_border_width)},
+  {"right-divider-width",      SYMBOL_INDEX (Qright_divider_width)},
+  {"bottom-divider-width",     SYMBOL_INDEX (Qbottom_divider_width)},
+  {"menu-bar-lines",           SYMBOL_INDEX (Qmenu_bar_lines)},
+  {"mouse-color",              SYMBOL_INDEX (Qmouse_color)},
+  {"name",                     SYMBOL_INDEX (Qname)},
+  {"scroll-bar-width",         SYMBOL_INDEX (Qscroll_bar_width)},
+  {"scroll-bar-height",                SYMBOL_INDEX (Qscroll_bar_height)},
+  {"title",                    SYMBOL_INDEX (Qtitle)},
+  {"unsplittable",             SYMBOL_INDEX (Qunsplittable)},
+  {"vertical-scroll-bars",     SYMBOL_INDEX (Qvertical_scroll_bars)},
+  {"horizontal-scroll-bars",   SYMBOL_INDEX (Qhorizontal_scroll_bars)},
+  {"visibility",               SYMBOL_INDEX (Qvisibility)},
+  {"tool-bar-lines",           SYMBOL_INDEX (Qtool_bar_lines)},
+  {"scroll-bar-foreground",    SYMBOL_INDEX (Qscroll_bar_foreground)},
+  {"scroll-bar-background",    SYMBOL_INDEX (Qscroll_bar_background)},
+  {"screen-gamma",             SYMBOL_INDEX (Qscreen_gamma)},
+  {"line-spacing",             SYMBOL_INDEX (Qline_spacing)},
+  {"left-fringe",              SYMBOL_INDEX (Qleft_fringe)},
+  {"right-fringe",             SYMBOL_INDEX (Qright_fringe)},
+  {"wait-for-wm",              SYMBOL_INDEX (Qwait_for_wm)},
+  {"fullscreen",                SYMBOL_INDEX (Qfullscreen)},
+  {"font-backend",             SYMBOL_INDEX (Qfont_backend)},
+  {"alpha",                    SYMBOL_INDEX (Qalpha)},
+  {"sticky",                   SYMBOL_INDEX (Qsticky)},
+  {"tool-bar-position",                SYMBOL_INDEX (Qtool_bar_position)},
 };
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -2994,7 +3092,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
      set them both at once.  So we wait until we've looked at the
      entire list before we set them.  */
   int width IF_LINT (= 0), height IF_LINT (= 0);
-  bool width_change = 0, height_change = 0;
+  bool width_change = false, height_change = false;
 
   /* Same here.  */
   Lisp_Object left, top;
@@ -3002,6 +3100,10 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
   /* Same with these.  */
   Lisp_Object icon_left, icon_top;
 
+  /* And with this.  */
+  Lisp_Object fullscreen;
+  bool fullscreen_change = false;
+
   /* Record in these vectors all the parms specified.  */
   Lisp_Object *parms;
   Lisp_Object *values;
@@ -3034,8 +3136,6 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
   /* TAIL and ALIST are not used again below here.  */
   alist = tail = Qnil;
 
-  /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
-     because their values appear in VALUES and strings are not valid.  */
   top = left = Qunbound;
   icon_left = icon_top = Qunbound;
 
@@ -3077,15 +3177,33 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
       prop = parms[i];
       val = values[i];
 
-      if (EQ (prop, Qwidth) && RANGED_INTEGERP (0, val, INT_MAX))
+      if (EQ (prop, Qwidth))
         {
-         width_change = 1;
-          width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
+         if (RANGED_INTEGERP (0, val, INT_MAX))
+           {
+             width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
+             width_change = true;
+           }
+         else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
+                  && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
+           {
+             width = XFASTINT (XCDR (val));
+             width_change = true;
+           }
         }
-      else if (EQ (prop, Qheight) && RANGED_INTEGERP (0, val, INT_MAX))
+      else if (EQ (prop, Qheight))
         {
-         height_change = 1;
-          height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
+         if (RANGED_INTEGERP (0, val, INT_MAX))
+           {
+             height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
+             height_change = true;
+           }
+         else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
+                  && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
+           {
+             height = XFASTINT (XCDR (val));
+             height_change = true;
+           }
         }
       else if (EQ (prop, Qtop))
        top = val;
@@ -3095,6 +3213,11 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
        icon_top = val;
       else if (EQ (prop, Qicon_left))
        icon_left = val;
+      else if (EQ (prop, Qfullscreen))
+       {
+         fullscreen = val;
+         fullscreen_change = true;
+       }
       else if (EQ (prop, Qforeground_color)
               || EQ (prop, Qbackground_color)
               || EQ (prop, Qfont))
@@ -3168,28 +3291,15 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
     XSETFRAME (frame, f);
 
     if ((width_change && width != FRAME_TEXT_WIDTH (f))
-       || (height_change && height != FRAME_TEXT_HEIGHT (f))
-       || f->new_height || f->new_width)
-      {
-       /* If necessary provide default values for HEIGHT and WIDTH.  Do
-          that here since otherwise a size change implied by an
-          intermittent font change may get lost as in Bug#17142.  */
-       if (!width_change)
-         width = (f->new_width
-                  ? (f->new_pixelwise
-                     ? f->new_width
-                     : (f->new_width * FRAME_COLUMN_WIDTH (f)))
-                  : FRAME_TEXT_WIDTH (f));
-
-       if (!height_change)
-         height = (f->new_height
-                   ? (f->new_pixelwise
-                      ? f->new_height
-                      : (f->new_height * FRAME_LINE_HEIGHT (f)))
-                   : FRAME_TEXT_HEIGHT (f));
-
-       Fset_frame_size (frame, make_number (width), make_number (height), Qt);
-      }
+       || (height_change && height != FRAME_TEXT_HEIGHT (f)))
+      /* We could consider checking f->after_make_frame here, but I
+        don't have the faintest idea why the following is needed at
+        all.  With the old setting it can get a Heisenbug when
+        EmacsFrameResize intermittently provokes a delayed
+        change_frame_size in the middle of adjust_frame_size.  */
+      /**      || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
+      adjust_frame_size (f, width_change ? width : -1,
+                        height_change ? height : -1, 1, 0, Qx_set_frame_parameters);
 
     if ((!NILP (left) || !NILP (top))
        && ! (left_no_change && top_no_change)
@@ -3255,6 +3365,20 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
        /* Actually set that position, and convert to absolute.  */
        x_set_offset (f, leftpos, toppos, -1);
       }
+
+    if (fullscreen_change)
+      {
+       Lisp_Object old_value = get_frame_param (f, Qfullscreen);
+
+       frame_size_history_add
+         (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
+
+       store_frame_param (f, Qfullscreen, fullscreen);
+       if (!EQ (fullscreen, old_value))
+         x_set_fullscreen (f, fullscreen, old_value);
+      }
+
+
 #ifdef HAVE_X_WINDOWS
     if ((!NILP (icon_left) || !NILP (icon_top))
        && ! (icon_left_no_change && icon_top_no_change))
@@ -3431,7 +3555,8 @@ x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
            (f, bgcolor, Qnil);
     }
 
-  Fclear_face_cache (Qnil);
+  clear_face_cache (true);     /* FIXME: Why of all frames?  */
+  fset_redisplay (f);
 }
 
 
@@ -3503,10 +3628,12 @@ x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
          Lisp_Object ascii_font = fontset_ascii (fontset);
          Lisp_Object spec = font_spec_from_name (ascii_font);
 
-         if (NILP (spec))
-           signal_error ("Invalid font name", ascii_font);
-
-         if (! font_match_p (spec, font_object))
+         /* SPEC might be nil because ASCII_FONT's name doesn't parse
+            according to stupid XLFD rules, which, for example,
+            disallow font names that include a dash followed by a
+            number.  So in those cases we simply request x_new_font
+            below to generate a new fontset.  */
+         if (NILP (spec) || ! font_match_p (spec, font_object))
            fontset = -1;
        }
     }
@@ -3530,6 +3657,10 @@ x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   /* Attempt to hunt down bug#16028.  */
   SET_FRAME_GARBAGED (f);
 
+  /* This is important if we are called by some Lisp as part of
+     redisplaying the frame, see redisplay_internal.  */
+  f->fonts_changed = true;
+
   recompute_basic_faces (f);
 
   do_pending_window_change (0);
@@ -3593,7 +3724,7 @@ x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
 
       XSETFRAME (frame, f);
       x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
-      ++face_change_count;
+      face_change = true;
       windows_or_buffers_changed = 18;
     }
 }
@@ -3615,7 +3746,7 @@ x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value
        = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
 
       if (FRAME_X_WINDOW (f) != 0)
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3639,7 +3770,7 @@ x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
        = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
 
       if (FRAME_X_WINDOW (f) != 0)
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3671,7 +3802,7 @@ x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
   if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old)
     {
-      adjust_frame_size (f, -1, -1, 4, 0);
+      adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
       adjust_frame_glyphs (f);
       SET_FRAME_GARBAGED (f);
     }
@@ -3689,7 +3820,7 @@ x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval
     FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
   if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old)
     {
-      adjust_frame_size (f, -1, -1, 4, 0);
+      adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
       adjust_frame_glyphs (f);
       SET_FRAME_GARBAGED (f);
     }
@@ -3753,7 +3884,7 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval
         However, if the window hasn't been created yet, we shouldn't
         call x_set_window_size.  */
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3773,7 +3904,7 @@ x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldv
         However, if the window hasn't been created yet, we shouldn't
         call x_set_window_size.  */
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3790,7 +3921,7 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       x_set_scroll_bar_default_width (f);
 
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3800,7 +3931,7 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
       FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3820,7 +3951,7 @@ x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       x_set_scroll_bar_default_height (f);
 
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3830,7 +3961,7 @@ x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
       FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -4026,23 +4157,23 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
 
   /* Start with emacs.FRAMENAME for the name (the specific one)
      and with `Emacs' for the class key (the general one).  */
-  lispstpcpy (name_key, Vx_resource_name);
-  lispstpcpy (class_key, Vx_resource_class);
+  char *nz = lispstpcpy (name_key, Vx_resource_name);
+  char *cz = lispstpcpy (class_key, Vx_resource_class);
 
-  strcat (class_key, ".");
-  strcat (class_key, SSDATA (class));
+  *cz++ = '.';
+  cz = lispstpcpy (cz, class);
 
   if (!NILP (component))
     {
-      strcat (class_key, ".");
-      strcat (class_key, SSDATA (subclass));
+      *cz++ = '.';
+      lispstpcpy (cz, subclass);
 
-      strcat (name_key, ".");
-      strcat (name_key, SSDATA (component));
+      *nz++ = '.';
+      nz = lispstpcpy (nz, component);
     }
 
-  strcat (name_key, ".");
-  strcat (name_key, SSDATA (attribute));
+  *nz++ = '.';
+  lispstpcpy (nz, attribute);
 
   char *value = x_get_string_resource (rdb, name_key, class_key);
   SAFE_FREE();
@@ -4084,7 +4215,7 @@ display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
                            attribute, class, component, subclass);
 }
 
-#if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT
+#if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT && !defined USE_GTK
 /* Used when C code wants a resource value.  */
 /* Called from oldXMenu/Create.c.  */
 char *
@@ -4437,11 +4568,11 @@ On Nextstep, this just calls `ns-parse-geometry'.  */)
 
    This function does not make the coordinates positive.  */
 
-#define DEFAULT_ROWS 35
+#define DEFAULT_ROWS 36
 #define DEFAULT_COLS 80
 
 long
-x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
+x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x_width, int *x_height)
 {
   Lisp_Object height, width, user_size, top, left, user_position;
   long window_prompting = 0;
@@ -4460,6 +4591,36 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
   f->top_pos = 0;
   f->left_pos = 0;
 
+  /* Calculate a tool bar height so that the user gets a text display
+     area of the size he specified with -g or via .Xdefaults.  Later
+     changes of the tool bar height don't change the frame size.  This
+     is done so that users can create tall Emacs frames without having
+     to guess how tall the tool bar will get.  */
+  if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
+    {
+      if (frame_default_tool_bar_height)
+       FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
+      else
+       {
+         int margin, relief;
+
+         relief = (tool_bar_button_relief >= 0
+                   ? tool_bar_button_relief
+                   : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
+
+         if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
+           margin = XFASTINT (Vtool_bar_button_margin);
+         else if (CONSP (Vtool_bar_button_margin)
+                  && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
+           margin = XFASTINT (XCDR (Vtool_bar_button_margin));
+         else
+           margin = 0;
+
+         FRAME_TOOL_BAR_HEIGHT (f)
+           = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
+       }
+    }
+
   /* Ensure that earlier new_width and new_height settings won't
      override what we specify below.  */
   f->new_width = f->new_height = 0;
@@ -4470,20 +4631,46 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
     {
       if (!EQ (width, Qunbound))
        {
-         CHECK_NUMBER (width);
-         if (! (0 <= XINT (width) && XINT (width) <= INT_MAX))
-           xsignal1 (Qargs_out_of_range, width);
+         if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
+           {
+             CHECK_NUMBER (XCDR (width));
+             if ((XINT (XCDR (width)) < 0 || XINT (XCDR (width)) > INT_MAX))
+               xsignal1 (Qargs_out_of_range, XCDR (width));
 
-         SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
+             SET_FRAME_WIDTH (f, XINT (XCDR (width)));
+             f->inhibit_horizontal_resize = true;
+             *x_width = XINT (XCDR (width));
+           }
+         else
+           {
+             CHECK_NUMBER (width);
+             if ((XINT (width) < 0 || XINT (width) > INT_MAX))
+               xsignal1 (Qargs_out_of_range, width);
+
+             SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
+           }
        }
 
       if (!EQ (height, Qunbound))
        {
-         CHECK_NUMBER (height);
-         if (! (0 <= XINT (height) && XINT (height) <= INT_MAX))
-           xsignal1 (Qargs_out_of_range, height);
+         if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
+           {
+             CHECK_NUMBER (XCDR (height));
+             if ((XINT (XCDR (height)) < 0 || XINT (XCDR (height)) > INT_MAX))
+               xsignal1 (Qargs_out_of_range, XCDR (height));
+
+             SET_FRAME_HEIGHT (f, XINT (XCDR (height)));
+             f->inhibit_vertical_resize = true;
+             *x_height = XINT (XCDR (height));
+           }
+         else
+           {
+             CHECK_NUMBER (height);
+             if ((XINT (height) < 0) || (XINT (height) > INT_MAX))
+               xsignal1 (Qargs_out_of_range, height);
 
-         SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
+             SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
+           }
        }
 
       user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
@@ -4493,32 +4680,6 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
        window_prompting |= PSize;
     }
 
-  /* Add a tool bar height to the initial frame height so that the user
-     gets a text display area of the size he specified with -g or via
-     .Xdefaults.  Later changes of the tool bar height don't change the
-     frame size.  This is done so that users can create tall Emacs
-     frames without having to guess how tall the tool bar will get.  */
-  if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
-    {
-      int margin, relief;
-
-      relief = (tool_bar_button_relief >= 0
-               ? tool_bar_button_relief
-               : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
-
-      if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
-       margin = XFASTINT (Vtool_bar_button_margin);
-      else if (CONSP (Vtool_bar_button_margin)
-              && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
-       margin = XFASTINT (XCDR (Vtool_bar_button_margin));
-      else
-       margin = 0;
-
-      FRAME_TOOL_BAR_HEIGHT (f)
-       = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
-      Vframe_initial_frame_tool_bar_height = make_number (FRAME_TOOL_BAR_HEIGHT (f));
-    }
-
   top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
   left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
   user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
@@ -4728,6 +4889,7 @@ syms_of_frame (void)
   DEFSYM (Qframep, "framep");
   DEFSYM (Qframe_live_p, "frame-live-p");
   DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
+  DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
   DEFSYM (Qexplicit_name, "explicit-name");
   DEFSYM (Qheight, "height");
   DEFSYM (Qicon, "icon");
@@ -4736,6 +4898,7 @@ syms_of_frame (void)
   DEFSYM (Qonly, "only");
   DEFSYM (Qnone, "none");
   DEFSYM (Qwidth, "width");
+  DEFSYM (Qtext_pixels, "text-pixels");
   DEFSYM (Qgeometry, "geometry");
   DEFSYM (Qicon_left, "icon-left");
   DEFSYM (Qicon_top, "icon-top");
@@ -4773,27 +4936,103 @@ syms_of_frame (void)
 
   DEFSYM (Qterminal, "terminal");
 
-  DEFSYM (Qgeometry, "geometry");
   DEFSYM (Qworkarea, "workarea");
   DEFSYM (Qmm_size, "mm-size");
   DEFSYM (Qframes, "frames");
   DEFSYM (Qsource, "source");
 
+  DEFSYM (Qouter_edges, "outer-edges");
+  DEFSYM (Qouter_position, "outer-position");
+  DEFSYM (Qouter_size, "outer-size");
+  DEFSYM (Qnative_edges, "native-edges");
+  DEFSYM (Qinner_edges, "inner-edges");
+  DEFSYM (Qexternal_border_size, "external-border-size");
+  DEFSYM (Qtitle_bar_size, "title-bar-size");
+  DEFSYM (Qmenu_bar_external, "menu-bar-external");
+  DEFSYM (Qmenu_bar_size, "menu-bar-size");
+  DEFSYM (Qtool_bar_external, "tool-bar-external");
+  DEFSYM (Qtool_bar_size, "tool-bar-size");
+  /* The following are used for frame_size_history.  */
+  DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
+  DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
+  DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
+  DEFSYM (Qx_set_frame_parameters, "x-set-frame-parameters");
+  DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
+  DEFSYM (Qset_frame_size, "set-frame-size");
+  DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
+  DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
+  DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
+  DEFSYM (Qxg_frame_resized, "xg-frame-resized");
+  DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
+  DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
+  DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
+  DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
+  DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
+  DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
+  DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
+  DEFSYM (Qx_net_wm_state, "x-net-wm-state");
+  DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
+  DEFSYM (Qtb_size_cb, "tb-size-cb");
+  DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
+  DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
+  DEFSYM (Qx_set_menu_bar_lines, "x-set-menu-bar-lines");
+  DEFSYM (Qchange_frame_size, "change-frame-size");
+  DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
+  DEFSYM (Qset_window_configuration, "set-window-configuration");
+  DEFSYM (Qx_create_frame_1, "x-create-frame-1");
+  DEFSYM (Qx_create_frame_2, "x-create-frame-2");
+  DEFSYM (Qterminal_frame, "terminal-frame");
+
 #ifdef HAVE_NS
   DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
 #endif
 
+  DEFSYM (Qalpha, "alpha");
+  DEFSYM (Qauto_lower, "auto-lower");
+  DEFSYM (Qauto_raise, "auto-raise");
+  DEFSYM (Qborder_color, "border-color");
+  DEFSYM (Qborder_width, "border-width");
+  DEFSYM (Qbottom_divider_width, "bottom-divider-width");
+  DEFSYM (Qcursor_color, "cursor-color");
+  DEFSYM (Qcursor_type, "cursor-type");
+  DEFSYM (Qfont_backend, "font-backend");
+  DEFSYM (Qfullscreen, "fullscreen");
+  DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
+  DEFSYM (Qicon_name, "icon-name");
+  DEFSYM (Qicon_type, "icon-type");
+  DEFSYM (Qinternal_border_width, "internal-border-width");
+  DEFSYM (Qleft_fringe, "left-fringe");
+  DEFSYM (Qline_spacing, "line-spacing");
+  DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
+  DEFSYM (Qupdate_frame_menubar, "update-frame-menubar");
+  DEFSYM (Qfree_frame_menubar_1, "free-frame-menubar-1");
+  DEFSYM (Qfree_frame_menubar_2, "free-frame-menubar-2");
+  DEFSYM (Qmouse_color, "mouse-color");
+  DEFSYM (Qname, "name");
+  DEFSYM (Qright_divider_width, "right-divider-width");
+  DEFSYM (Qright_fringe, "right-fringe");
+  DEFSYM (Qscreen_gamma, "screen-gamma");
+  DEFSYM (Qscroll_bar_background, "scroll-bar-background");
+  DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
+  DEFSYM (Qscroll_bar_height, "scroll-bar-height");
+  DEFSYM (Qscroll_bar_width, "scroll-bar-width");
+  DEFSYM (Qsticky, "sticky");
+  DEFSYM (Qtitle, "title");
+  DEFSYM (Qtool_bar_lines, "tool-bar-lines");
+  DEFSYM (Qtool_bar_position, "tool-bar-position");
+  DEFSYM (Qunsplittable, "unsplittable");
+  DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
+  DEFSYM (Qvisibility, "visibility");
+  DEFSYM (Qwait_for_wm, "wait-for-wm");
+
   {
     int i;
 
     for (i = 0; i < ARRAYELTS (frame_parms); i++)
       {
-       Lisp_Object v = intern_c_string (frame_parms[i].name);
-       if (frame_parms[i].variable)
-         {
-           *frame_parms[i].variable = v;
-           staticpro (frame_parms[i].variable);
-         }
+       Lisp_Object v = (frame_parms[i].sym < 0
+                        ? intern_c_string (frame_parms[i].name)
+                        : builtin_lisp_symbol (frame_parms[i].sym));
        Fput (v, Qx_frame_parameter, make_number (i));
       }
   }
@@ -4833,7 +5072,7 @@ You can also use a floating number between 0.0 and 1.0.  */);
   DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
               doc: /* Alist of default values for frame creation.
 These may be set in your init file, like this:
-  (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
+  (setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
 These override values given in window system configuration data,
  including X Windows' defaults database.
 For values specific to the first Emacs frame, see `initial-frame-alist'.
@@ -4896,12 +5135,10 @@ The pointer becomes visible again when the mouse is moved.  */);
   DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
                doc: /* Normal hook run when a frame gains input focus.  */);
   Vfocus_in_hook = Qnil;
-  DEFSYM (Qfocus_in_hook, "focus-in-hook");
 
   DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
                doc: /* Normal hook run when a frame loses input focus.  */);
   Vfocus_out_hook = Qnil;
-  DEFSYM (Qfocus_out_hook, "focus-out-hook");
 
   DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
               doc: /* Functions run before deleting a frame.
@@ -4935,10 +5172,6 @@ or call the function `tool-bar-mode'.  */);
   Vtool_bar_mode = Qnil;
 #endif
 
-  DEFVAR_LISP ("frame-initial-frame-tool-bar-height", Vframe_initial_frame_tool_bar_height,
-               doc: /* Height of tool bar of initial frame.  */);
-  Vframe_initial_frame_tool_bar_height = make_number (0);
-
   DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
                 doc: /* Minibufferless frames use this frame's minibuffer.
 Emacs cannot create minibufferless frames unless this is set to an
@@ -4968,23 +5201,78 @@ is non-nil, no rounding occurs, hence frame sizes can increase/decrease
 by one pixel.
 
 With some window managers you may have to set this to non-nil in order
-to fully maximize frames.  To resize your initial frame pixelwise, set
-this option to a non-nil value in your init file.  */);
+to set the size of a frame in pixels, to maximize frames or to make them
+fullscreen.  To resize your initial frame pixelwise, set this option to
+a non-nil value in your init file.  */);
   frame_resize_pixelwise = 0;
 
-  DEFVAR_BOOL ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
-              doc: /* Non-nil means do not resize frame implicitly.
-If this option is nil, setting default font, menubar mode, fringe width,
-or scroll bar mode of a specific frame may resize the frame in order to
-preserve the number of columns or lines it displays.  If this option is
-non-nil, no such resizing is done.  */);
-  frame_inhibit_implied_resize = 0;
+  DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
+              doc: /* Whether frames should be resized implicitly.
+If this option is nil, setting font, menu bar, tool bar, internal
+borders, fringes or scroll bars of a specific frame may resize the frame
+in order to preserve the number of columns or lines it displays.  If
+this option is t, no such resizing is done.  Note that the size of
+fullscreen and maximized frames, the height of fullheight frames and the
+width of fullwidth frames never change implicitly.
+
+The value of this option can be also be a list of frame parameters.  In
+this case, resizing is inhibited when changing a parameter that appears
+in that list.  The parameters currently handled by this option include
+`font', `font-backend', `internal-border-width', `menu-bar-lines' and
+`tool-bar-lines'.
+
+Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
+`vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
+`right-fringe' is handled as if the frame contained just one live
+window.  This means, for example, that removing vertical scroll bars on
+a frame containing several side by side windows will shrink the frame
+width by the width of one scroll bar provided this option is nil and
+keep it unchanged if this option is either t or a list containing
+`vertical-scroll-bars'.
+
+The default value is \\='(tool-bar-lines) on Lucid, Motif and Windows
+\(which means that adding/removing a tool bar does not change the frame
+height), nil on all other window systems including GTK+ (which means
+that changing any of the parameters listed above may change the size of
+the frame), and t otherwise (which means the frame size never changes
+implicitly when there's no window system support).
+
+Note that when a frame is not large enough to accommodate a change of
+any of the parameters listed above, Emacs may try to enlarge the frame
+even if this option is non-nil.  */);
+#if defined (HAVE_WINDOW_SYSTEM)
+#if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
+  frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
+#else
+  frame_inhibit_implied_resize = Qnil;
+#endif
+#else
+  frame_inhibit_implied_resize = Qt;
+#endif
+
+  DEFVAR_LISP ("frame-size-history", frame_size_history,
+               doc: /* History of frame size adjustments.
+If non-nil, list recording frame size adjustment.  Adjustments are
+recorded only if the first element of this list is a positive number.
+Adding an adjustment decrements that number by one.
+
+The remaining elements are the adjustments.  Each adjustment is a list
+of four elements `frame', `function', `sizes' and `more'.  `frame' is
+the affected frame and `function' the invoking function.  `sizes' is
+usually a list of four elements `old-width', `old-height', `new-width'
+and `new-height' representing the old and new sizes recorded/requested
+by `function'.  `more' is a list with additional information.
+
+The function `frame--size-history' displays the value of this variable
+in a more readable form.  */);
+    frame_size_history = Qnil;
 
   staticpro (&Vframe_list);
 
   defsubr (&Sframep);
   defsubr (&Sframe_live_p);
   defsubr (&Swindow_system);
+  defsubr (&Sframe_windows_min_size);
   defsubr (&Smake_terminal_frame);
   defsubr (&Shandle_switch_frame);
   defsubr (&Sselect_frame);
@@ -5010,6 +5298,7 @@ non-nil, no such resizing is done.  */);
   defsubr (&Sraise_frame);
   defsubr (&Slower_frame);
   defsubr (&Sx_focus_frame);
+  defsubr (&Sframe_after_make_frame);
   defsubr (&Sredirect_frame_focus);
   defsubr (&Sframe_focus);
   defsubr (&Sframe_parameters);
@@ -5035,6 +5324,7 @@ non-nil, no such resizing is done.  */);
   defsubr (&Sset_frame_height);
   defsubr (&Sset_frame_width);
   defsubr (&Sset_frame_size);
+  defsubr (&Sframe_position);
   defsubr (&Sset_frame_position);
   defsubr (&Sframe_pointer_visible_p);