]> code.delx.au - gnu-emacs/blobdiff - src/frame.c
Merge from origin/emacs-25
[gnu-emacs] / src / frame.c
index aa07219d152d90cb21f8f2686afaad495c5d399e..fd9f3ce0203a9f703ae813ff35a5f4f33f2af04d 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic frame functions.
 
-Copyright (C) 1993-1995, 1997, 1999-2015 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 1997, 1999-2016 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -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
@@ -184,16 +181,17 @@ frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
 {
   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));
-
+    = (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,
@@ -241,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)
 {
@@ -286,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.
 
@@ -396,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;
@@ -425,17 +423,15 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
 
   if (inhibit >= 2 && inhibit <= 4)
     /* When 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.  */
+       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, parameter)))
-                           ? true : false);
-      inhibit_vertical = ((windows_height >= min_windows_height
-                          && (inhibit == 4
-                              || frame_inhibit_resize (f, false, parameter)))
-                         ? 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.  */
@@ -595,8 +591,6 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
                  || new_pixel_height != old_pixel_height);
 
   unblock_input ();
-
-  run_window_configuration_change_hook (f);
 }
 
 /* Allocate basically initialized frame.  */
@@ -611,10 +605,10 @@ 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);
@@ -634,7 +628,10 @@ make_frame (bool mini_p)
   f->garbaged = true;
   f->can_x_set_window_size = false;
   f->after_make_frame = false;
-  f->tool_bar_redisplayed_once = 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
@@ -735,10 +732,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);
@@ -759,11 +756,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
@@ -870,6 +865,9 @@ 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);
 
@@ -978,7 +976,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.  */)
@@ -1823,9 +1821,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.
@@ -1854,7 +1853,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;
@@ -1880,10 +1878,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,
@@ -1900,7 +1897,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;
@@ -1918,10 +1914,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
@@ -2309,6 +2304,8 @@ otherwise used with utter care to avoid that running functions on
 {
   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;
 }
 
@@ -2509,13 +2506,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))
     {
@@ -2585,7 +2580,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;
 }
 
@@ -2648,13 +2642,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
@@ -2976,24 +2973,40 @@ font height.  */)
   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;
@@ -3118,8 +3131,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;
 
@@ -3161,15 +3172,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;
@@ -3257,28 +3286,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->can_x_set_window_size && (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->can_x_set_window_size && 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->can_x_set_window_size && 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)
@@ -3534,7 +3550,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);
 }
 
 
@@ -3606,10 +3623,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;
        }
     }
@@ -3626,7 +3645,6 @@ x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 #endif
   /* Recalculate toolbar height.  */
   f->n_tool_bar_rows = 0;
-  f->tool_bar_redisplayed_once = false;
 
   /* Ensure we redraw it.  */
   clear_current_matrices (f);
@@ -3634,6 +3652,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);
@@ -4188,7 +4210,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 *
@@ -4545,7 +4567,7 @@ On Nextstep, this just calls `ns-parse-geometry'.  */)
 #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;
@@ -4564,44 +4586,11 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
   f->top_pos = 0;
   f->left_pos = 0;
 
-  /* Ensure that earlier new_width and new_height settings won't
-     override what we specify below.  */
-  f->new_width = f->new_height = 0;
-
-  height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
-  width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
-  if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
-    {
-      if (!EQ (width, Qunbound))
-       {
-         CHECK_NUMBER (width);
-         if (! (0 <= XINT (width) && 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);
-
-         SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
-       }
-
-      user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
-      if (!NILP (user_size) && !EQ (user_size, Qunbound))
-       window_prompting |= USSize;
-      else
-       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.  */
+  /* 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)
@@ -4627,6 +4616,65 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
        }
     }
 
+  /* Ensure that earlier new_width and new_height settings won't
+     override what we specify below.  */
+  f->new_width = f->new_height = 0;
+
+  height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+  width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+  if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
+    {
+      if (!EQ (width, Qunbound))
+       {
+         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 (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))
+       {
+         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));
+           }
+       }
+
+      user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
+      if (!NILP (user_size) && !EQ (user_size, Qunbound))
+       window_prompting |= USSize;
+      else
+       window_prompting |= PSize;
+    }
+
   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);
@@ -4845,6 +4893,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");
@@ -4887,41 +4936,46 @@ syms_of_frame (void)
   DEFSYM (Qframes, "frames");
   DEFSYM (Qsource, "source");
 
-  DEFSYM (Qframe_position, "frame-position");
-  DEFSYM (Qframe_outer_size, "frame-outer-size");
+  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_height, "title-height");
+  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");
-  DEFSYM (Qframe_inner_size, "frame-inner-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 (Qx_set_window_size_1, "x-set-window-size-1");
   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 (Qtip_frame, "tip-frame");
   DEFSYM (Qterminal_frame, "terminal-frame");
 
 #ifdef HAVE_NS
@@ -4945,6 +4999,9 @@ syms_of_frame (void)
   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");
@@ -5010,7 +5067,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'.
@@ -5073,12 +5130,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.
@@ -5151,7 +5206,7 @@ a non-nil value in your init file.  */);
 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
+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.
 
@@ -5167,14 +5222,14 @@ Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
 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
+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
+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
+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
@@ -5264,6 +5319,7 @@ in a more readable form.  */);
   defsubr (&Sset_frame_height);
   defsubr (&Sset_frame_width);
   defsubr (&Sset_frame_size);
+  defsubr (&Sframe_position);
   defsubr (&Sset_frame_position);
   defsubr (&Sframe_pointer_visible_p);