emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master d4fe840: Allow setting frame pixel sizes from frame


From: Martin Rudalics
Subject: [Emacs-diffs] master d4fe840: Allow setting frame pixel sizes from frame parameters (Bug#21415)
Date: Tue, 13 Oct 2015 10:13:12 +0000

branch: master
commit d4fe840df0b5fdb3aed538fae2ced143a471f60a
Author: Martin Rudalics <address@hidden>
Commit: Martin Rudalics <address@hidden>

    Allow setting frame pixel sizes from frame parameters (Bug#21415)
    
    Also fix some misfeatures in frame (re-)sizing code, add more
    debugging information and remove some dead code.
    
    * lisp/frame.el (frame-notice-user-settings, make-frame): Change
    parameter names when setting `frame-size-history'.
    (frame--size-history): New function.
    
    * src/frame.c (frame_inhibit_resize): If frame has not been made
    yet, return t if inhibit_horizontal_resize or
    inhibit_vertical_resize bit have been set.
    (adjust_frame_size): Simplify.
    (make_frame): Initialize inhibit_horizontal_resize,
    inhibit_vertical_resize, tool_bar_redisplayed, tool_bar_resized.
    (Fframe_after_make_frame): Reset inhibit_horizontal_resize and
    inhibit_vertical_resize slots.
    (x_set_frame_parameters): Handle `text-pixels' specification for
    width and height parameters.  Don't consider new_height or
    new_width changes.  Call adjust_frame_size instead of
    Fset_frame_size.
    (x_figure_window_size): Two new arguments x_width and y_width
    returning frame's figures width and height.  Calculate tool bar
    height before frame sizes so SET_FRAME_HEIGHT can pick it up.
    Handle `text-pixels' specification for width and height
    parameters.
    (Qtext_pixels, Qx_set_frame_parameters, Qset_frame_size)
    (Qx_set_window_size_1, Qx_set_window_size_2)
    (Qx_set_window_size_3, Qx_set_menu_bar_lines)
    (Qupdate_frame_menubar, Qfree_frame_menubar_1)
    (Qfree_frame_menubar_2): New symbols.
    * src/frame.h (structure frame): New booleans
    tool_bar_redisplayed, tool_bar_resized,
    inhibit_horizontal_resize, inhibit_vertical_resize.
    (x_figure_window_size): Update external declaration.
    * src/gtkutil.c (xg_frame_set_char_size): Set size hints before
    calling gtk_window_resize.
    (update_frame_tool_bar): Make inhibiting of frame resizing more
    discriminative.  Set tool_bar_resized bit.
    * src/nsfns.m (x_set_tool_bar_lines): Make inhibiting of frame
    resizing more discriminative.  Call adjust_frame_size instead of
    x_set_window_size.
    (Fx_create_frame): Handle x_width and x_height if
    set by x_figure_window_size.
    * src/nsterm.m (x_set_window_size): For GNUSTEP build don't
    subtract 3 from tool bar height.
    (x_set_window_size): Add frame_size_history_add call.
    (x_new_font): Call adjust_frame_size instead of
    x_set_window_size.
    * src/w32fns.c (x_change_tool_bar_height): Reset
    tool_bar_redisplayed and tool_bar_resized bits when adding tool
    bar.  Make inhibiting of frame resizing more discriminative.
    (w32_wnd_proc): Remove dead code in WM_WINDOWPOSCHANGING case.
    (Fx_create_frame): Handle x_width and x_height if set by
    x_figure_window_size.  Set size hints before adjusting frame size.
    (x_create_tip_frame): Adjust x_figure_window_size call.
    * src/w32term.c (x_set_window_size): Add frame_size_history_add
    call.
    * src/widget.c (set_frame_size): Remove dead code.  Add
    frame_size_history_add call.  When frame_resize_pixelwise is t
    use FRAME_PIXEL_WIDTH and FRAME_PIXEL_HEIGHT instead of
    pixel_width and pixel_height.
    (update_various_frame_slots): Remove dead code.
    (EmacsFrameResize): Add more information in
    frame_size_history_add call.
    (EmacsFrameQueryGeometry): Round only when frame_resize_pixelwise
    is not set.
    * src/xdisp.c (redisplay_tool_bar): Set tool_bar_redisplayed bits.
    * src/xfns.c (x_set_menu_bar_lines): Change argument name.
    (x_change_tool_bar_height): Reset tool_bar_redisplayed and
    tool_bar_resized bits when adding tool bar.  Make inhibiting of
    frame resizing more discriminative.
    (Fx_create_frame): Handle x_width and x_height if set by
    x_figure_window_size.  Set size hints before adjusting frame size.
    (x_create_tip_frame): Adjust x_figure_window_size call.
    * src/xmenu.c (update_frame_menubar): Don't handle Lucid specially.
    (set_frame_menubar): On Lucid never add core-border-width to
    avoid that adding XtNinternalBorderWidth adds it again.
    (free_frame_menubar): Handle frame_inhibit_resize true for Motif.
    * src/xterm.c (x_new_font): In non-toolkit case handle size
    change of menu bar.
    (x_set_window_size_1): Fix calls to frame_size_history_add.
    (x_wm_set_size_hint): Remove dead code.  Set
    size_hints.min_width and size_hints.min_height to base_width and
    base_height.
---
 lisp/frame.el |   25 ++++++-
 src/frame.c   |  221 ++++++++++++++++++++++++++++++++++-----------------------
 src/frame.h   |   10 +++-
 src/gtkutil.c |   40 +++++++----
 src/nsfns.m   |   26 ++++++-
 src/nsterm.m  |   16 ++++-
 src/w32fns.c  |  121 ++++++-------------------------
 src/w32term.c |    7 ++
 src/widget.c  |  196 +++++++--------------------------------------------
 src/xdisp.c   |    1 +
 src/xfns.c    |   39 +++++++---
 src/xmenu.c   |   34 +++++----
 src/xterm.c   |   52 ++++++++------
 13 files changed, 363 insertions(+), 425 deletions(-)

diff --git a/lisp/frame.el b/lisp/frame.el
index bbf0a63..b9e63d5 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -461,7 +461,7 @@ there (in decreasing order of priority)."
                    (cons (1- (car frame-size-history))
                          (cons
                           (list frame-initial-frame
-                                "frame-notice-user-settings"
+                                "FRAME-NOTICE-USER"
                                 nil newparms)
                           (cdr frame-size-history)))))
 
@@ -702,7 +702,7 @@ the new frame according to its own rules."
     (when (numberp (car frame-size-history))
       (setq frame-size-history
            (cons (1- (car frame-size-history))
-                 (cons (list frame "make-frame")
+                 (cons (list frame "MAKE-FRAME")
                        (cdr frame-size-history)))))
 
     ;; We can run `window-configuration-change-hook' for this frame now.
@@ -1382,6 +1382,27 @@ and width values are in pixels.
        (cons 'internal-border-width
             (frame-parameter frame 'internal-border-width)))))))
 
+(defun frame--size-history (&optional frame)
+  "Print history of resize operations for FRAME.
+Print prettified version of `frame-size-history' into a buffer
+called *frame-size-history*.  Optional argument FRAME denotes the
+frame whose history will be printed.  FRAME defaults to the
+selected frame."
+  (let ((history (reverse frame-size-history))
+       entry)
+    (setq frame (window-normalize-frame frame))
+    (with-current-buffer (get-buffer-create "*frame-size-history*")
+      (erase-buffer)
+      (insert (format "Frame size history of %s\n" frame))
+      (while (listp (setq entry (pop history)))
+       (when (eq (car entry) frame)
+          (pop entry)
+          (insert (format "%s" (pop entry)))
+          (move-to-column 24 t)
+          (while entry
+            (insert (format " %s" (pop entry))))
+          (insert "\n"))))))
+
 (declare-function x-frame-edges "xfns.c" (&optional frame type))
 (declare-function w32-frame-edges "w32fns.c" (&optional frame type))
 (declare-function ns-frame-edges "nsfns.m" (&optional frame type))
diff --git a/src/frame.c b/src/frame.c
index 77ead08..98a7a57 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -184,16 +184,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,
@@ -425,17 +426,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.  */
@@ -634,6 +633,10 @@ make_frame (bool mini_p)
   f->garbaged = true;
   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
@@ -2303,6 +2306,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;
 }
 
@@ -3166,15 +3171,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;
@@ -3262,28 +3285,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)
@@ -4552,7 +4562,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;
@@ -4571,44 +4581,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)
@@ -4634,6 +4611,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);
@@ -4852,6 +4888,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");
@@ -4909,7 +4946,9 @@ syms_of_frame (void)
   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");
@@ -4917,13 +4956,16 @@ syms_of_frame (void)
   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");
@@ -4952,6 +4994,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");
diff --git a/src/frame.h b/src/frame.h
index af0dadb..acac514 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -335,6 +335,14 @@ struct frame
   /* Set to true after this frame was made by `make-frame'.  */
   bool_bf after_make_frame : 1;
 
+  /* Whether the tool bar height change should be taken into account.  */
+  bool_bf tool_bar_redisplayed : 1;
+  bool_bf tool_bar_resized : 1;
+
+  /* Inhibit implied resize before after_make_frame is set.  */
+  bool_bf inhibit_horizontal_resize : 1;
+  bool_bf inhibit_vertical_resize : 1;
+
   /* Non-zero if this frame's faces need to be recomputed.  */
   bool_bf face_change : 1;
 
@@ -1375,7 +1383,7 @@ extern void x_set_horizontal_scroll_bars (struct frame *, 
Lisp_Object, Lisp_Obje
 extern void x_set_scroll_bar_width (struct frame *, Lisp_Object, Lisp_Object);
 extern void x_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object);
 
-extern long x_figure_window_size (struct frame *, Lisp_Object, bool);
+extern long x_figure_window_size (struct frame *, Lisp_Object, bool, int *, 
int *);
 
 extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object);
 
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 34e81b5..ad71b9c 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -951,6 +951,8 @@ xg_frame_set_char_size (struct frame *f, int width, int 
height)
       totalwidth /= scale;
     }
 
+  x_wm_set_size_hint (f, 0, 0);
+
   /* Resize the top level widget so rows and columns remain constant.
 
      When the frame is fullheight and we only want to change the width
@@ -964,41 +966,34 @@ xg_frame_set_char_size (struct frame *f, int width, int 
height)
     {
       frame_size_history_add
        (f, Qxg_frame_set_char_size_1, width, height,
-        list2 (make_number (gheight),
-               make_number (totalheight)));
+        list2 (make_number (gheight), make_number (totalheight)));
 
       gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                        gwidth,
-                        totalheight);
+                        gwidth, totalheight);
     }
   else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
     {
       frame_size_history_add
        (f, Qxg_frame_set_char_size_2, width, height,
-        list2 (make_number (gwidth),
-               make_number (totalwidth)));
+        list2 (make_number (gwidth), make_number (totalwidth)));
 
       gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                        totalwidth,
-                        gheight);
+                        totalwidth, gheight);
     }
   else
     {
       frame_size_history_add
        (f, Qxg_frame_set_char_size_3, width, height,
-        list2 (make_number (totalwidth),
-               make_number (totalheight)));
+        list2 (make_number (totalwidth), make_number (totalheight)));
 
       gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                        totalwidth,
-                        totalheight);
+                        totalwidth, totalheight);
       fullscreen = Qnil;
     }
 
   SET_FRAME_GARBAGED (f);
   cancel_mouse_face (f);
 
-  x_wm_set_size_hint (f, 0, 0);
   /* We can not call change_frame_size for a mapped frame,
      we can not set pixel width/height either.  The window manager may
      override our resize request, XMonad does this all the time.
@@ -1399,7 +1394,8 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool 
user_position)
 
   hint_flags |= GDK_HINT_BASE_SIZE;
   /* Use one row/col here so base_height/width does not become zero.
-     Gtk+ and/or Unity on Ubuntu 12.04 can't handle it.  */
+     Gtk+ and/or Unity on Ubuntu 12.04 can't handle it.
+     Obviously this makes the row/col value displayed off by 1.  */
   base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 1) + FRAME_TOOLBAR_WIDTH (f);
   base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1)
     + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
@@ -4998,9 +4994,23 @@ update_frame_tool_bar (struct frame *f)
       gtk_widget_show_all (x->toolbar_widget);
       if (xg_update_tool_bar_sizes (f))
        {
+         int inhibit
+           = ((f->after_make_frame
+               && !f->tool_bar_resized
+               && (EQ (frame_inhibit_implied_resize, Qt)
+                   || (CONSP (frame_inhibit_implied_resize)
+                       && !NILP (Fmemq (Qtool_bar_lines,
+                                        frame_inhibit_implied_resize))))
+               /* This will probably fail to DTRT in the
+                  fullheight/-width cases.  */
+               && NILP (get_frame_param (f, Qfullscreen)))
+              ? 0
+              : 2);
+
          frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
-         adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
+         adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
        }
+      f->tool_bar_resized = f->tool_bar_redisplayed;
     }
 
   unblock_input ();
diff --git a/src/nsfns.m b/src/nsfns.m
index ad71a50..43002ca 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -679,7 +679,23 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, 
Lisp_Object oldval)
         }
     }
 
-  x_set_window_size (f, 0, f->text_cols, f->text_lines, 0);
+  {
+    int inhibit
+      = ((f->after_make_frame
+         && !f->tool_bar_resized
+         && (EQ (frame_inhibit_implied_resize, Qt)
+             || (CONSP (frame_inhibit_implied_resize)
+                 && !NILP (Fmemq (Qtool_bar_lines,
+                                  frame_inhibit_implied_resize))))
+         /* This will probably fail to DTRT in the
+            fullheight/-width cases.  */
+         && NILP (get_frame_param (f, Qfullscreen)))
+        ? 0
+        : 2);
+
+    frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
+    adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
+  }
 }
 
 
@@ -1082,6 +1098,7 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   Lisp_Object parent;
   struct kboard *kb;
   static int desc_ctr = 1;
+  int x_width = 0, x_height = 0;
 
   /* x_get_arg modifies parms.  */
   parms = Fcopy_alist (parms);
@@ -1268,7 +1285,7 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
                        RES_TYPE_STRING);
 
   parms = get_geometry_from_preferences (dpyinfo, parms);
-  window_prompting = x_figure_window_size (f, parms, 1);
+  window_prompting = x_figure_window_size (f, parms, true, &x_width, 
&x_height);
 
   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
@@ -1322,6 +1339,11 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   /* Allow x_set_window_size, now.  */
   f->can_x_set_window_size = true;
 
+  if (x_width > 0)
+    SET_FRAME_WIDTH (f, x_width);
+  if (x_height > 0)
+    SET_FRAME_HEIGHT (f, x_height);
+
   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1,
                     Qx_create_frame_2);
 
diff --git a/src/nsterm.m b/src/nsterm.m
index 65d07b2..c4bfd7c 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1365,9 +1365,12 @@ x_set_window_size (struct frame *f,
     FRAME_TOOLBAR_HEIGHT (f) =
       NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
         - FRAME_NS_TITLEBAR_HEIGHT (f);
+#if 0
+      /* Only breaks things here, removed by martin 2015-09-30.  */
 #ifdef NS_IMPL_GNUSTEP
       FRAME_TOOLBAR_HEIGHT (f) -= 3;
 #endif
+#endif
     }
   else
     FRAME_TOOLBAR_HEIGHT (f) = 0;
@@ -1386,6 +1389,14 @@ x_set_window_size (struct frame *f,
  else
    wr.origin.y += orig_height - wr.size.height;
 
+ frame_size_history_add
+   (f, Qx_set_window_size_1, width, height,
+    list5 (Fcons (make_number (pixelwidth), make_number (pixelheight)),
+          Fcons (make_number (wr.size.width), make_number (wr.size.height)),
+          make_number (f->border_width),
+          make_number (FRAME_NS_TITLEBAR_HEIGHT (f)),
+          make_number (FRAME_TOOLBAR_HEIGHT (f))));
+
   [view setRows: rows andColumns: cols];
   [window setFrame: wr display: YES];
 
@@ -7741,8 +7752,9 @@ x_new_font (struct frame *f, Lisp_Object font_object, int 
fontset)
 
   /* Now make the frame display the given font.  */
   if (FRAME_NS_WINDOW (f) != 0 && ! [view isFullscreen])
-    x_set_window_size (f, false, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
-                       FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), true);
+    adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
+                      false, Qfont);
 
   return font_object;
 }
diff --git a/src/w32fns.c b/src/w32fns.c
index 97dd40b..3773923 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -1762,14 +1762,24 @@ x_change_tool_bar_height (struct frame *f, int height)
 
   /* Recalculate toolbar height.  */
   f->n_tool_bar_rows = 0;
+  if (old_height == 0
+      && (!f->after_make_frame
+         || NILP (frame_inhibit_implied_resize)
+         || (CONSP (frame_inhibit_implied_resize)
+             && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize)))))
+    f->tool_bar_redisplayed = f->tool_bar_resized = false;
 
   adjust_frame_size (f, -1, -1,
-                    ((NILP (fullscreen = get_frame_param (f, Qfullscreen))
-                      || EQ (fullscreen, Qfullwidth)) ? 1
+                    ((!f->tool_bar_resized
+                      && (NILP (fullscreen =
+                                get_frame_param (f, Qfullscreen))
+                          || EQ (fullscreen, Qfullwidth))) ? 1
                      : (old_height == 0 || height == 0) ? 2
                      : 4),
                     false, Qtool_bar_lines);
 
+  f->tool_bar_resized = f->tool_bar_redisplayed;
+
   /* adjust_frame_size might not have done anything, garbage frame
      here.  */
   adjust_frame_glyphs (f);
@@ -4368,97 +4378,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM 
lParam)
     case WM_WINDOWPOSCHANGING:
       /* Don't restrict the sizing of any kind of frames.  If the window
         manager doesn't, there's no reason to do it ourselves.  */
-#if 0
-       if (frame_resize_pixelwise || hwnd == tip_window)
-#endif
-         return 0;
-
-#if 0
-      /* Don't restrict the sizing of fullscreened frames, allowing them to be
-        flush with the sides of the screen.  */
-      f = x_window_to_frame (dpyinfo, hwnd);
-      if (f && FRAME_PREV_FSMODE (f) != FULLSCREEN_NONE)
-       return 0;
-
-      {
-       WINDOWPLACEMENT wp;
-       LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
-
-       wp.length = sizeof (WINDOWPLACEMENT);
-       GetWindowPlacement (hwnd, &wp);
-
-       if (wp.showCmd != SW_SHOWMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED
-           && (lppos->flags & SWP_NOSIZE) == 0)
-         {
-           RECT rect;
-           int wdiff;
-           int hdiff;
-           DWORD font_width;
-           DWORD line_height;
-           DWORD internal_border;
-           DWORD vscrollbar_extra;
-           DWORD hscrollbar_extra;
-           RECT wr;
-
-           wp.length = sizeof (wp);
-           GetWindowRect (hwnd, &wr);
-
-           enter_crit ();
-
-           font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
-           line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
-           internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
-           vscrollbar_extra = GetWindowLong (hwnd, WND_VSCROLLBAR_INDEX);
-           hscrollbar_extra = GetWindowLong (hwnd, WND_HSCROLLBAR_INDEX);
-
-           leave_crit ();
-
-           memset (&rect, 0, sizeof (rect));
-           AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
-                             GetMenu (hwnd) != NULL);
-
-           /* Force width and height of client area to be exact
-              multiples of the character cell dimensions.  */
-           wdiff = (lppos->cx - (rect.right - rect.left)
-                    - 2 * internal_border - vscrollbar_extra)
-             % font_width;
-           hdiff = (lppos->cy - (rect.bottom - rect.top)
-                    - 2 * internal_border - hscrollbar_extra)
-             % line_height;
-
-           if (wdiff || hdiff)
-             {
-               /* For right/bottom sizing we can just fix the sizes.
-                  However for top/left sizing we will need to fix the X
-                  and Y positions as well.  */
-
-               int cx_mintrack = GetSystemMetrics (SM_CXMINTRACK);
-               int cy_mintrack = GetSystemMetrics (SM_CYMINTRACK);
-
-               lppos->cx = max (lppos->cx - wdiff, cx_mintrack);
-               lppos->cy = max (lppos->cy - hdiff, cy_mintrack);
-
-               if (wp.showCmd != SW_SHOWMAXIMIZED
-                   && (lppos->flags & SWP_NOMOVE) == 0)
-                 {
-                   if (lppos->x != wr.left || lppos->y != wr.top)
-                     {
-                       lppos->x += wdiff;
-                       lppos->y += hdiff;
-                     }
-                   else
-                     {
-                       lppos->flags |= SWP_NOMOVE;
-                     }
-                 }
-
-               return 0;
-             }
-         }
-      }
-
-      goto dflt;
-#endif
+      return 0;
 
     case WM_GETMINMAXINFO:
       /* Hack to allow resizing the Emacs frame above the screen size.
@@ -4977,6 +4897,7 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   struct w32_display_info *dpyinfo = NULL;
   Lisp_Object parent;
   struct kboard *kb;
+  int x_width = 0, x_height = 0;
 
   if (!FRAME_W32_P (SELECTED_FRAME ())
       && !FRAME_INITIAL_P (SELECTED_FRAME ()))
@@ -5199,7 +5120,7 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
 
   f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
 
-  window_prompting = x_figure_window_size (f, parameters, true);
+  window_prompting = x_figure_window_size (f, parameters, true, &x_width, 
&x_height);
 
   tem = x_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
@@ -5233,8 +5154,10 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   /* Allow x_set_window_size, now.  */
   f->can_x_set_window_size = true;
 
-  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, true,
-                    Qx_create_frame_2);
+  if (x_width > 0)
+    SET_FRAME_WIDTH (f, x_width);
+  if (x_height > 0)
+    SET_FRAME_HEIGHT (f, x_height);
 
   /* Tell the server what size and position, etc, we want, and how
      badly we want them.  This should be done after we have the menu
@@ -5243,6 +5166,9 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   x_wm_set_size_hint (f, window_prompting, false);
   unblock_input ();
 
+  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, true,
+                    Qx_create_frame_2);
+
   /* Process fullscreen parameter here in the hope that normalizing a
      fullheight/fullwidth frame will produce the size set by the last
      adjust_frame_size call.  */
@@ -6179,6 +6105,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
   bool face_change_before = face_change;
   Lisp_Object buffer;
   struct buffer *old_buffer;
+  int x_width = 0, x_height = 0;
 
   /* Use this general default value to start with until we know if
      this frame has a specified name.  */
@@ -6309,7 +6236,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
   f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
 
-  window_prompting = x_figure_window_size (f, parms, false);
+  window_prompting = x_figure_window_size (f, parms, true, &x_width, 
&x_height);
 
   /* No fringes on tip frame.  */
   f->fringe_cols = 0;
diff --git a/src/w32term.c b/src/w32term.c
index 9dc6b17..bd6070f 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -6176,6 +6176,13 @@ x_set_window_size (struct frame *f, bool change_gravity,
 
   if (pixelwidth > 0 || pixelheight > 0)
     {
+      frame_size_history_add
+       (f, Qx_set_window_size_1, width, height,
+        list2 (Fcons (make_number (pixelwidth),
+                      make_number (pixelheight)),
+               Fcons (make_number (rect.right - rect.left),
+                      make_number (rect.bottom - rect.top))));
+
       my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
                         0, 0,
                         rect.right - rect.left,
diff --git a/src/widget.c b/src/widget.c
index 0986ba6..48872f5 100644
--- a/src/widget.c
+++ b/src/widget.c
@@ -268,167 +268,26 @@ set_frame_size (EmacsFrame ew)
    */
 
   /* Hairily merged geometry */
-  int w = FRAME_COLS (ew->emacs_frame.frame);
-  int h = FRAME_LINES (ew->emacs_frame.frame);
-
+  struct frame *f = ew->emacs_frame.frame;
+  int w = FRAME_COLS (f);
+  int h = FRAME_LINES (f);
   Widget wmshell = get_wm_shell ((Widget) ew);
+  Dimension pixel_width, pixel_height;
   /* Each Emacs shell is now independent and top-level.  */
 
   if (! XtIsSubclass (wmshell, shellWidgetClass)) emacs_abort ();
 
-  /* We don't need this for the moment. The geometry is computed in
-     xfns.c.  */
-#if 0
-  /* If the EmacsFrame doesn't have a geometry but the shell does,
-     treat that as the geometry of the frame.  (Is this bogus?
-     I'm not sure.) */
-  if (ew->emacs_frame.geometry == 0)
-    XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
-
-  /* If the Shell is iconic, then the EmacsFrame is iconic.  (Is
-     this bogus? I'm not sure.) */
-  if (!ew->emacs_frame.iconic)
-    XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
-
-
-  {
-    char *geom = 0;
-    XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
-    if (geom)
-      app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
-  }
-
-  if (ew->emacs_frame.geometry)
-    frame_flags = XParseGeometry (ew->emacs_frame.geometry,
-                                  &frame_x, &frame_y,
-                                  &frame_w, &frame_h);
-
-  if (first_frame_p)
-    {
-      /* If this is the first frame created:
-         ====================================
-
-         - Use the ApplicationShell's size/position, if specified.
-           (This is "Emacs.geometry", or the "-geometry" command line arg.)
-         - Else use the EmacsFrame's size/position.
-           (This is "*Frame-NAME.geometry")
-
-        - If the AppShell is iconic, the frame should be iconic.
-
-        AppShell comes first so that -geometry always applies to the first
-        frame created, even if there is an "every frame" entry in the
-        resource database.
-       */
-      if (app_flags & (XValue | YValue))
-       {
-         x = app_x; y = app_y;
-         flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
-       }
-      else if (frame_flags & (XValue | YValue))
-       {
-         x = frame_x; y = frame_y;
-         flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
-       }
-
-      if (app_flags & (WidthValue | HeightValue))
-       {
-         w = app_w; h = app_h;
-         flags |= (app_flags & (WidthValue | HeightValue));
-       }
-      else if (frame_flags & (WidthValue | HeightValue))
-       {
-         w = frame_w; h = frame_h;
-         flags |= (frame_flags & (WidthValue | HeightValue));
-       }
-
-      /* If the AppShell is iconic, then the EmacsFrame is iconic. */
-      if (!ew->emacs_frame.iconic)
-       XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
-
-      first_frame_p = False;
-    }
-  else
-    {
-      /* If this is not the first frame created:
-         ========================================
-
-         - use the EmacsFrame's size/position if specified
-         - Otherwise, use the ApplicationShell's size, but not position.
-
-         So that means that one can specify the position of the first frame
-         with "Emacs.geometry" or `-geometry'; but can only specify the
-        position of subsequent frames with "*Frame-NAME.geometry".
-
-        AppShell comes second so that -geometry does not apply to subsequent
-        frames when there is an "every frame" entry in the resource db,
-        but does apply to the first frame.
-       */
-      if (frame_flags & (XValue | YValue))
-       {
-         x = frame_x; y = frame_y;
-         flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
-       }
+  char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
+  ew->core.width = (frame_resize_pixelwise
+                   ? FRAME_PIXEL_WIDTH (f)
+                   : pixel_width);
+  ew->core.height = (frame_resize_pixelwise
+                    ? FRAME_PIXEL_HEIGHT (f)
+                    : pixel_height);
 
-      if (frame_flags & (WidthValue | HeightValue))
-       {
-         w = frame_w; h = frame_h;
-         flags |= (frame_flags & (WidthValue | HeightValue));
-       }
-      else if (app_flags & (WidthValue | HeightValue))
-       {
-         w = app_w;
-         h = app_h;
-         flags |= (app_flags & (WidthValue | HeightValue));
-       }
-    }
-#endif /* 0 */
-  {
-    Dimension pixel_width, pixel_height;
-
-    /* Take into account the size of the scrollbar.  Always use the
-       number of columns occupied by the scroll bar here otherwise we
-       might end up with a frame width that is not a multiple of the
-       frame's character width which is bad for vertically split
-       windows.  */
-
-#if 0 /* This can run Lisp code, and it is dangerous to give
-        out the frame to Lisp code before it officially exists.
-        This is handled in Fx_create_frame so not needed here.  */
-    change_frame_size (f, w, h, 1, 0, 0, 0);
-#endif
-    char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
-    ew->core.width = pixel_width;
-    ew->core.height = pixel_height;
-
-#if 0 /* xfns.c takes care of this now.  */
-    /* If a position was specified, assign it to the shell widget.
-       (Else WM won't do anything with it.)
-     */
-    if (flags & (XValue | YValue))
-      {
-       /* the tricky things with the sign is to make sure that
-          -0 is printed -0. */
-       sprintf (shell_position, "=%c%d%c%d",
-                flags & XNegative ? '-' : '+', x < 0 ? -x : x,
-                flags & YNegative ? '-' : '+', y < 0 ? -y : y);
-       XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
-      }
-    else if (flags & (WidthValue | HeightValue))
-      {
-       sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
-       XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
-      }
-
-    /* If the geometry spec we're using has W/H components, mark the size
-       in the WM_SIZE_HINTS as user specified. */
-    if (flags & (WidthValue | HeightValue))
-      mark_shell_size_user_specified (wmshell);
-
-    /* Also assign the iconic status of the frame to the Shell, so that
-       the WM sees it. */
-    XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
-#endif /* 0 */
-  }
+  frame_size_history_add
+    (f, Qset_frame_size, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+     list2 (make_number (ew->core.width), make_number (ew->core.height)));
 }
 
 static void
@@ -486,16 +345,6 @@ update_various_frame_slots (EmacsFrame ew)
 {
   struct frame *f = ew->emacs_frame.frame;
 
-  /* Don't do that: It confuses the check in change_frame_size_1 whether
-     the pixel size of the frame changed due to a change of the internal
-     border width.  Bug#16736.  */
-  if (false)
-    {
-      struct x_output *x = f->output_data.x;
-      FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
-      FRAME_PIXEL_WIDTH (f) = ew->core.width;
-    }
-
   f->internal_border_width = ew->emacs_frame.internal_border_width;
 }
 
@@ -504,6 +353,7 @@ update_from_various_frame_slots (EmacsFrame ew)
 {
   struct frame *f = ew->emacs_frame.frame;
   struct x_output *x = f->output_data.x;
+
   ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
   ew->core.width = FRAME_PIXEL_WIDTH (f);
   ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
@@ -576,7 +426,10 @@ EmacsFrameResize (Widget widget)
 
   frame_size_history_add
     (f, QEmacsFrameResize, width, height,
-     list2 (make_number (ew->core.width), make_number (ew->core.height)));
+     list5 (make_number (ew->core.width), make_number (ew->core.height),
+           make_number (FRAME_TOP_MARGIN_HEIGHT (f)),
+           make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (f)),
+           make_number (2 * FRAME_INTERNAL_BORDER_WIDTH (f))));
 
   change_frame_size (f, width, height, 0, 1, 0, 1);
 
@@ -596,11 +449,12 @@ EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry 
*request, XtWidgetGeome
 
   if (mask & (CWWidth | CWHeight))
     {
-      round_size_to_char (ew,
-                         (mask & CWWidth) ? request->width : ew->core.width,
-                         ((mask & CWHeight) ? request->height
-                          : ew->core.height),
-                         &ok_width, &ok_height);
+      if (!frame_resize_pixelwise)
+       round_size_to_char (ew,
+                           (mask & CWWidth) ? request->width : ew->core.width,
+                           ((mask & CWHeight) ? request->height
+                            : ew->core.height),
+                           &ok_width, &ok_height);
       if ((mask & CWWidth) && (ok_width != request->width))
        {
          result->request_mode |= CWWidth;
diff --git a/src/xdisp.c b/src/xdisp.c
index 44983bb..a793157 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12342,6 +12342,7 @@ PIXELWISE non-nil means return the height of the tool 
bar in pixels.  */)
 static bool
 redisplay_tool_bar (struct frame *f)
 {
+  f->tool_bar_redisplayed = true;
 #if defined (USE_GTK) || defined (HAVE_NS)
 
   if (FRAME_EXTERNAL_TOOL_BAR (f))
diff --git a/src/xfns.c b/src/xfns.c
index fefd8e8..8251f93 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1090,7 +1090,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, 
Lisp_Object oldval)
 #else /* not USE_X_TOOLKIT && not USE_GTK */
   FRAME_MENU_BAR_LINES (f) = nlines;
   FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
-  adjust_frame_size (f, -1, -1, 2, true, Qmenu_bar_lines);
+  adjust_frame_size (f, -1, -1, 2, true, Qx_set_menu_bar_lines);
   if (FRAME_X_WINDOW (f))
     x_clear_under_internal_border (f);
 
@@ -1212,14 +1212,24 @@ x_change_tool_bar_height (struct frame *f, int height)
 
   /* Recalculate toolbar height.  */
   f->n_tool_bar_rows = 0;
+  if (old_height == 0
+      && (!f->after_make_frame
+         || NILP (frame_inhibit_implied_resize)
+         || (CONSP (frame_inhibit_implied_resize)
+             && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize)))))
+    f->tool_bar_redisplayed = f->tool_bar_resized = false;
 
   adjust_frame_size (f, -1, -1,
-                    ((NILP (fullscreen = get_frame_param (f, Qfullscreen))
-                      || EQ (fullscreen, Qfullwidth)) ? 1
+                    ((!f->tool_bar_resized
+                      && (NILP (fullscreen =
+                                get_frame_param (f, Qfullscreen))
+                          || EQ (fullscreen, Qfullwidth))) ? 1
                      : (old_height == 0 || height == 0) ? 2
                      : 4),
                     false, Qtool_bar_lines);
 
+  f->tool_bar_resized = f->tool_bar_redisplayed;
+
   /* adjust_frame_size might not have done anything, garbage frame
      here.  */
   adjust_frame_glyphs (f);
@@ -3001,6 +3011,7 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   struct x_display_info *dpyinfo = NULL;
   Lisp_Object parent;
   struct kboard *kb;
+  int x_width = 0, x_height = 0;
 
   parms = Fcopy_alist (parms);
 
@@ -3275,7 +3286,7 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
                        FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
 
   /* Compute the size of the X window.  */
-  window_prompting = x_figure_window_size (f, parms, true);
+  window_prompting = x_figure_window_size (f, parms, true, &x_width, 
&x_height);
 
   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
@@ -3317,12 +3328,6 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   x_default_parameter (f, parms, Qalpha, Qnil,
                       "alpha", "Alpha", RES_TYPE_NUMBER);
 
-  /* Consider frame official, now.  */
-  f->can_x_set_window_size = true;
-
-  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, true,
-                    Qx_create_frame_2);
-
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   /* Create the menu bar.  */
   if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
@@ -3341,6 +3346,14 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
     }
 #endif /* USE_X_TOOLKIT || USE_GTK */
 
+  /* Consider frame official, now.  */
+  f->can_x_set_window_size = true;
+
+  if (x_width > 0)
+    SET_FRAME_WIDTH (f, x_width);
+  if (x_height > 0)
+    SET_FRAME_HEIGHT (f, x_height);
+
   /* Tell the server what size and position, etc, we want, and how
      badly we want them.  This should be done after we have the menu
      bar so that its size can be taken into account.  */
@@ -3348,6 +3361,9 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
   x_wm_set_size_hint (f, window_prompting, false);
   unblock_input ();
 
+  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+                    0, true, Qx_create_frame_2);
+
   /* Process fullscreen parameter here in the hope that normalizing a
      fullheight/fullwidth frame will produce the size set by the last
      adjust_frame_size call.  */
@@ -5161,6 +5177,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
   bool face_change_before = face_change;
   Lisp_Object buffer;
   struct buffer *old_buffer;
+  int x_width = 0, x_height = 0;
 
   if (!dpyinfo->terminal->name)
     error ("Terminal is not live, can't create new frames on it");
@@ -5333,7 +5350,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
 
   f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
 
-  x_figure_window_size (f, parms, false);
+  x_figure_window_size (f, parms, false, &x_width, &x_height);
 
   {
     XSetWindowAttributes attrs;
diff --git a/src/xmenu.c b/src/xmenu.c
index 192ed89..4379cdd 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -636,13 +636,7 @@ update_frame_menubar (struct frame *f)
   lw_refigure_widget (x->column_widget, True);
 
   /* Force the pane widget to resize itself.  */
-  int new_height = -1;
-#ifdef USE_LUCID
-  /* For reasons I don't know Lucid wants to add one pixel to the frame
-     height when adding the menu bar.  Compensate that here.  */
-  new_height = FRAME_TEXT_HEIGHT (f) - 1;
-#endif /* USE_LUCID */
-  adjust_frame_size (f, -1, new_height, 2, false, Qmenu_bar_lines);
+  adjust_frame_size (f, -1, -1, 2, false, Qupdate_frame_menubar);
   unblock_input ();
 #endif /* USE_GTK */
 }
@@ -979,7 +973,15 @@ set_frame_menubar (struct frame *f, bool first_time, bool 
deep_p)
     menubar_size
       = (f->output_data.x->menubar_widget
         ? (f->output_data.x->menubar_widget->core.height
-           + f->output_data.x->menubar_widget->core.border_width)
+#ifndef USE_LUCID
+           /* Damn me...  With Lucid I get a core.border_width of 1
+              only the first time this is called and an ibw of 1 every
+              time this is called.  So the first time this is called I
+              was off by one.  Fix that here by never adding
+              core.border_width for Lucid.  */
+           + f->output_data.x->menubar_widget->core.border_width
+#endif /* USE_LUCID */
+           )
         : 0);
 
 #ifdef USE_LUCID
@@ -990,9 +992,10 @@ set_frame_menubar (struct frame *f, bool first_time, bool 
deep_p)
     if (FRAME_EXTERNAL_MENU_BAR (f))
       {
         Dimension ibw = 0;
+
         XtVaGetValues (f->output_data.x->column_widget,
                       XtNinternalBorderWidth, &ibw, NULL);
-        menubar_size += ibw;
+       menubar_size += ibw;
       }
 #endif /* USE_LUCID */
 
@@ -1073,21 +1076,24 @@ free_frame_menubar (struct frame *f)
 
       if (f->output_data.x->widget)
        {
-         int new_height = -1;
 #ifdef USE_MOTIF
          XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
          if (x1 == 0 && y1 == 0)
            XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
          if (frame_inhibit_resize (f, false, Qmenu_bar_lines))
-           new_height = old_height;
+           adjust_frame_size (f, -1, old_height, 1, false, 
Qfree_frame_menubar_1);
+         else
+           adjust_frame_size (f, -1, -1, 2, false, Qfree_frame_menubar_1);
+#else
+         adjust_frame_size (f, -1, -1, 2, false, Qfree_frame_menubar_1);
 #endif /* USE_MOTIF */
-         adjust_frame_size (f, -1, new_height, 2, false, Qmenu_bar_lines);
        }
       else
        {
 #ifdef USE_MOTIF
-         if (frame_inhibit_resize (f, false, Qmenu_bar_lines))
-           adjust_frame_size (f, -1, old_height, 1, false, Qmenu_bar_lines);
+         if (WINDOWP (FRAME_ROOT_WINDOW (f))
+             && frame_inhibit_resize (f, false, Qmenu_bar_lines))
+           adjust_frame_size (f, -1, old_height, 1, false, 
Qfree_frame_menubar_2);
 #endif
        }
 
diff --git a/src/xterm.c b/src/xterm.c
index dd57a54..fdf0eee 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -9579,6 +9579,10 @@ x_new_font (struct frame *f, Lisp_Object font_object, 
int fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
   int unit, font_ascent, font_descent;
+#ifndef USE_X_TOOLKIT
+  int old_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+  Lisp_Object fullscreen;
+#endif
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -9615,9 +9619,25 @@ x_new_font (struct frame *f, Lisp_Object font_object, 
int fontset)
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+       {
          adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
                             FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
                             false, Qfont);
+#ifndef USE_X_TOOLKIT
+         if (FRAME_MENU_BAR_HEIGHT (f) != old_menu_bar_height
+             && !f->after_make_frame
+             && (EQ (frame_inhibit_implied_resize, Qt)
+                 || (CONSP (frame_inhibit_implied_resize)
+                     && NILP (Fmemq (Qfont, frame_inhibit_implied_resize))))
+             && (NILP (fullscreen = get_frame_param (f, Qfullscreen))
+                 || EQ (fullscreen, Qfullwidth)))
+           /* If the menu bar height changes, try to keep text height
+              constant.  */
+           adjust_frame_size
+             (f, -1, FRAME_TEXT_HEIGHT (f) + FRAME_MENU_BAR_HEIGHT (f)
+              - old_menu_bar_height, 1, false, Qfont);
+#endif /* USE_X_TOOLKIT  */
+       }
     }
 
 #ifdef HAVE_X_I18N
@@ -10549,7 +10569,7 @@ x_set_window_size_1 (struct frame *f, bool 
change_gravity,
   if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
     {
       frame_size_history_add
-       (f, Qxg_frame_set_char_size_1, width, height,
+       (f, Qx_set_window_size_1, width, height,
         list2 (make_number (old_height),
                make_number (pixelheight + FRAME_MENUBAR_HEIGHT (f))));
 
@@ -10559,7 +10579,7 @@ x_set_window_size_1 (struct frame *f, bool 
change_gravity,
   else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
     {
       frame_size_history_add
-       (f, Qxg_frame_set_char_size_2, width, height,
+       (f, Qx_set_window_size_2, width, height,
         list2 (make_number (old_width), make_number (pixelwidth)));
 
       XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
@@ -10569,10 +10589,11 @@ x_set_window_size_1 (struct frame *f, bool 
change_gravity,
   else
     {
       frame_size_history_add
-       (f, Qxg_frame_set_char_size_3, width, height,
-        list2 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
+       (f, Qx_set_window_size_3, width, height,
+        list3 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
                make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
-                            + FRAME_MENUBAR_HEIGHT (f))));
+                            + FRAME_MENUBAR_HEIGHT (f)),
+               make_number (FRAME_MENUBAR_HEIGHT (f))));
 
       XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
                     pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
@@ -11342,8 +11363,8 @@ x_wm_set_size_hint (struct frame *f, long flags, bool 
user_position)
   size_hints.x = f->left_pos;
   size_hints.y = f->top_pos;
 
-  size_hints.height = FRAME_PIXEL_HEIGHT (f);
   size_hints.width = FRAME_PIXEL_WIDTH (f);
+  size_hints.height = FRAME_PIXEL_HEIGHT (f);
 
   size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
   size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
@@ -11356,34 +11377,21 @@ x_wm_set_size_hint (struct frame *f, long flags, bool 
user_position)
   /* Calculate the base and minimum sizes.  */
   {
     int base_width, base_height;
-    int min_rows = 0, min_cols = 0;
 
     base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
     base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
-    if (frame_resize_pixelwise)
-      /* Needed to prevent a bad protocol error crash when making the
-        frame size very small.  */
-      {
-       min_cols = 2 * min_cols;
-       min_rows = 2 * min_rows;
-      }
-
     /* The window manager uses the base width hints to calculate the
        current number of rows and columns in the frame while
        resizing; min_width and min_height aren't useful for this
        purpose, since they might not give the dimensions for a
-       zero-row, zero-column frame.
-
-       We use the base_width and base_height members if we have
-       them; otherwise, we set the min_width and min_height members
-       to the size for a zero x zero frame.  */
+       zero-row, zero-column frame.  */
 
     size_hints.flags |= PBaseSize;
     size_hints.base_width = base_width;
     size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
-    size_hints.min_width  = base_width + min_cols * FRAME_COLUMN_WIDTH (f);
-    size_hints.min_height = base_height + min_rows * FRAME_LINE_HEIGHT (f);
+    size_hints.min_width  = base_width;
+    size_hints.min_height = base_height;
   }
 
   /* If we don't need the old flags, we don't need the old hint at all.  */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]