Subject: bug#21415: 25.0.50; Emacs Trunk -- pixelwise width/height for x-create-frame

From: martin rudalics <[email-masked]>
Date: Sat, 12 Sep 2015 13:12:11 +0200

> I had previously thought that the above-mentioned problem (now fixed)
 > was responsible for the frame increasing in size with the example
 > labeled BROKEN.  I see now that the difference between the WORKING
 > example and the BROKEN example is caused by the fact that
 > `frame-after-make-frame` has already run in the WORKING example before
 > `set-face-attribute` is called with the `font` parameter.  If we
 > modify `x-create-frame-with-faces` by commenting out
 > `(face-set-after-frame-default frame parameters)` and move that over
 > to `make-frame` following `(frame-after-make-frame frame t)`, then
 > both examples work as expected.
 >
 > I understand that may not be the preferred solution, but at least we
 > know for sure that calling `frame-after-make-frame` BEFORE
 > `set-face-attribute` fixes the problem with the frame expanding even
 > though `frame-inhibit-implied-resize` is set to `t`.

Yes.  I forgot that we try to keep the number of lines and faces
constant when making the initial frame.  Try the attached patch.  It
should cover everything we have investigated so far.  Unfortunately, it
won't work with an internal tool bar like we have on Lucid, Motif, and
Windows.  There's something I haven't fathomed yet :-(

martin
diff --git a/src/frame.c b/src/frame.c
index 6debcb8..01c7166 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -428,13 +428,15 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
        within the limits and either frame_inhibit_resize tells us to do
        so or INHIBIT equals 4.  */
     {
-      inhibit_horizontal = ((windows_width >= min_windows_width
-			     && (inhibit == 4
-				 || frame_inhibit_resize (f, true, parameter)))
+      inhibit_horizontal = ((f->inhibit_implied_resize
+			     || (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)))
+      inhibit_vertical = ((f->inhibit_implied_resize
+			   || (windows_height >= min_windows_height
+			       && (inhibit == 4
+				   || frame_inhibit_resize (f, false, parameter))))
 			  ? true : false);
     }
   else
@@ -634,6 +636,7 @@ make_frame (bool mini_p)
   f->garbaged = true;
   f->can_x_set_window_size = false;
   f->after_make_frame = false;
+  f->inhibit_implied_resize = false;
   f->tool_bar_redisplayed_once = false;
   f->column_width = 1;  /* !FRAME_WINDOW_P value.  */
   f->line_height = 1;  /* !FRAME_WINDOW_P value.  */
@@ -2304,6 +2307,7 @@ 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_implied_resize = false;
   return made;
 }

@@ -3167,15 +3171,25 @@ 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) ;
+	  else if (FLOATP (val)
+		   && XFLOAT_DATA (val) >= 0
+		   && (int) XFLOAT_DATA (val) <= INT_MAX)
+	    width = (int) XFLOAT_DATA (val);
         }
-      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);
+	  else if (FLOATP (val)
+		   && XFLOAT_DATA (val) >= 0
+		   && (int) XFLOAT_DATA (val) <= INT_MAX)
+	    height = (int) XFLOAT_DATA (val);
         }
       else if (EQ (prop, Qtop))
 	top = val;
@@ -4582,20 +4596,50 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
     {
       if (!EQ (width, Qunbound))
 	{
-	  CHECK_NUMBER (width);
-	  if (! (0 <= XINT (width) && XINT (width) <= INT_MAX))
-	    xsignal1 (Qargs_out_of_range, width);
+	  if (FLOATP (width))
+	    {
+	      if ((int) XFLOAT_DATA (width) < (FRAME_SCROLL_BAR_AREA_WIDTH (f)
+					       + FRAME_TOTAL_FRINGE_WIDTH (f)
+					       + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+		  || (int) XFLOAT_DATA (width) > INT_MAX)
+		xsignal1 (Qargs_out_of_range, width);
+	      else
+		SET_FRAME_WIDTH (f, (int) XFLOAT_DATA (width));

-	  SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
+	      f->inhibit_implied_resize = true;
+	    }
+	  else
+	    {
+	      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);
+	  if (FLOATP (height))
+	    {
+	      if ((int) XFLOAT_DATA (height) < (FRAME_TOP_MARGIN_HEIGHT (f)
+						+ FRAME_SCROLL_BAR_AREA_HEIGHT (f)
+						+ 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+		  || (int) XFLOAT_DATA (height) > INT_MAX)
+		xsignal1 (Qargs_out_of_range, height);
+	      else
+		SET_FRAME_HEIGHT (f, (int) XFLOAT_DATA (height));

-	  SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
+	      f->inhibit_implied_resize = true;
+	    }
+	  else
+	    {
+	      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);
diff --git a/src/frame.h b/src/frame.h
index 17e356d..21918ba 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -335,6 +335,9 @@ struct frame
   /* Set to true after this frame was made by `make-frame'.  */
   bool_bf after_make_frame : 1;

+  /* Inhibit implied resize before after_make_frame is set.  */
+  bool_bf inhibit_implied_resize : 1;
+
   /* True means tool bar has been redisplayed at least once in current
      session.  */
   bool_bf tool_bar_redisplayed_once : 1;
diff --git a/src/nsfns.m b/src/nsfns.m
index 9c805ac..e589929 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -679,7 +679,8 @@ 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);
+  frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
+  adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
 }

diff --git a/src/nsterm.m b/src/nsterm.m
index 2806f31..48b88e1 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7196,8 +7196,8 @@ if (cols > 0 && rows > 0)
   NSTRACE (constrainFrameRect);
   NSTRACE_RECT ("input", frameRect);

-  if (ns_menu_bar_should_be_hidden ())
-    return frameRect;
+///   if (ns_menu_bar_should_be_hidden ())
+///     return frameRect;

   if (nr_screens == 1)
     return [super constrainFrameRect:frameRect toScreen:screen];
@@ -7738,8 +7738,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;
 }