Subject: Re: bug#72986: Disabling menu-bar-mode changes size of new frames

From: martin rudalics <[email-masked]>
Date: Mon, 9 Sep 2024 10:58:05 +0200

The important fact is that in the entire sequence of the initial frame's
setup you never experience one of those strange ConfigureNotify events
asking to shrink the frame.  Why they happen only for subsequent frame
creations will probably remain a mystery.

A new mystery is that your creation of the initial frame has one
xg_frame_set_char_size call followed by two ConfigureNotify events where
the first event asks for 1328x1260 and the second one for 1328x1258
pixels.  The same happens again after setting up the tool bar only that
there the first event has 1328x1258 (which matches the previous) and the
second one asks for 1280x1354 pixels.  In the first event
xg_frame_resized concludes that nothing changed, in the second event it
notices a change.

When I do the same thing on my system I get

Frame size history of #<frame *scratch* - GNU Emacs at restno 0x1f668c0>
x_create_frame_1 (5), TS=80x25~>720x550, NS=80x25~>736x550, IS=80x25~>736x550, MS=18x44 IH IV
gui_figure_window_size (5), TS=720x550~>720x792, TC=80x25~>80x36, NS=736x550~>736x792, IS=736x550~>736x792, MS=18x44 IH IV
scroll-bar-width (3), NS=736x792~>752x792, IS=736x792~>752x792, MS=90x110
scroll-bar-height (3), MS=90x110
x_create_frame_2 (0), MS=90x110
xg_frame_set_char_size, invisible, PS=752x792, XS=752x792, DS=752x792
xg_frame_set_char_size (5), MS=18x44 IH IV
MapNotify, not hidden & not iconified, PS=752x792, DS=752x792
ConfigureNotify, PS=752x792, XS=752x792, DS=752x792
xg_frame_resized, unchanged, PS=752x792, XS=752x792
menu-bar-lines (2), MS=90x110
xg_frame_set_char_size, visible, PS=752x792, XS=752x792, DS=752x792
ConfigureNotify, PS=752x792, XS=752x792, DS=752x792
xg_frame_resized, unchanged, PS=752x792, XS=752x792
tool-bar-lines (2), MS=90x110
xg_frame_set_char_size, visible, PS=752x792, XS=752x792, DS=752x792
ConfigureNotify, PS=752x792, XS=752x792, DS=752x792
xg_frame_resized, unchanged, PS=752x792, XS=752x792

and the sizes requested by xg_frame_set_char_size and the ones received
by ConfigureNotify remain the same throughout - 752x792.

I have no hope that anyone will tell us what's going on here.  Hence
this new mystery will remain unsolved too, I presume.  But maybe I'm
missing an important detail here.

I forgot whether creating an initial frame without menubar works
reasonably on your system.  So please do the same once more but this
time with --eval "(setq default-frame-alist '((menu-bar-lines . 0)))"
appended to your emacs call.  This will conclude our experiments with
the history of the initial frame.

Next let's try the following: Upon receiving a ConfigureNotify event we
don't call change_frame_size when _we_ conclude that nothing has
changed.  This conclusion might be wrong so let's _always_ process a
ConfigureNotify event via change_frame_size with the trivial patch I
attached as gtkutil-change.diff.

If this doesn't accomplish anything (as I'd expect), let's try to be
stubborn.  For this purpose apply the less trivial patch attached as
gtkutil-reject.diff, do

(setq frame-size-history '(100))

C-x 5 2

(frame--size-history)

and tell me what *frame-size-history* says in the new frame (if we're
unlucky and I did something wrong, this might get your Emacs run into an
infinite loop and you have to kill it by external means).

martin

diff --git a/src/gtkutil.c b/src/gtkutil.c
index d57627f152f..c5c99d6f1bd 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1129,11 +1129,49 @@ xg_set_geometry (struct frame *f)
     }
 }
 
+static struct frame *last_resize_frame = NULL;
+static int last_resize_height = -1;
+static int last_resize_width = -1;
+static int last_resize_count = 0;
+
 /** Function to handle resize of native frame F to WIDTH and HEIGHT
     pixels after we got a ConfigureNotify event.  */
 void
 xg_frame_resized (struct frame *f, int width, int height)
 {
+#ifndef HAVE_PGTK
+  if (f == last_resize_frame
+      && width != last_resize_width
+      && height != last_resize_height
+      && last_resize_count <= 3)
+    /* We did not get what we wanted, retry.  */
+    {
+      if (CONSP (frame_size_history))
+	frame_size_history_extra
+	  (f, build_string ("xg_frame_resized, rejected"),
+	   FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
+	   last_resize_width, last_resize_height);
+
+      if (FRAME_GTK_OUTER_WIDGET (f))
+	gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+			   last_resize_width, last_resize_height);
+      else
+	gtk_widget_set_size_request (FRAME_GTK_WIDGET (f),
+				     last_resize_width, last_resize_height);
+
+      last_resize_count++;
+
+      return;
+    }
+  else
+    /* We either got what we asked for or lost the battle.  */
+    {
+      last_resize_frame = NULL;
+      last_resize_height = -1;
+      last_resize_width = -1;
+      last_resize_count = 0;
+    }
+#endif
   /* Ignore case where size of native rectangle didn't change.  */
   if (width != FRAME_PIXEL_WIDTH (f)
       || height != FRAME_PIXEL_HEIGHT (f)
@@ -1300,16 +1338,17 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
       gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
 			 outer_width, outer_height);
 #else
+      last_resize_frame = f;
+      last_resize_height = outer_height;
+      last_resize_width = outer_width;
+      last_resize_count = 0;
+
       if (FRAME_GTK_OUTER_WIDGET (f))
-	{
-	  gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-			     outer_width, outer_height);
-	}
+	gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+			   outer_width, outer_height);
       else
-	{
-	  gtk_widget_set_size_request (FRAME_GTK_WIDGET (f),
-				       outer_width, outer_height);
-	}
+	gtk_widget_set_size_request (FRAME_GTK_WIDGET (f),
+				     outer_width, outer_height);
 #endif
       fullscreen = Qnil;
     }
diff --git a/src/gtkutil.c b/src/gtkutil.c
index d57627f152f..68ae38550e0 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1135,12 +1135,12 @@ xg_set_geometry (struct frame *f)
 xg_frame_resized (struct frame *f, int width, int height)
 {
   /* Ignore case where size of native rectangle didn't change.  */
-  if (width != FRAME_PIXEL_WIDTH (f)
-      || height != FRAME_PIXEL_HEIGHT (f)
-      || (f->new_size_p
-	  && ((f->new_width >= 0 && width != f->new_width)
-	      || (f->new_height >= 0 && height != f->new_height))))
-    {
+/**   if (width != FRAME_PIXEL_WIDTH (f) **/
+/**       || height != FRAME_PIXEL_HEIGHT (f) **/
+/**       || (f->new_size_p **/
+/** 	  && ((f->new_width >= 0 && width != f->new_width) **/
+/** 	      || (f->new_height >= 0 && height != f->new_height)))) **/
+/**     { **/
       if (CONSP (frame_size_history))
 	frame_size_history_extra
 	  (f, build_string ("xg_frame_resized, changed"),
@@ -1152,13 +1152,13 @@ xg_frame_resized (struct frame *f, int width, int height)
       change_frame_size (f, width, height, false, true, false);
       SET_FRAME_GARBAGED (f);
       cancel_mouse_face (f);
-    }
-  else if (CONSP (frame_size_history))
-    frame_size_history_extra
-      (f, build_string ("xg_frame_resized, unchanged"),
-       FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
-       f->new_size_p ? f->new_width : -1,
-       f->new_size_p ? f->new_height : -1);
+/**     } **/
+/**   else if (CONSP (frame_size_history)) **/
+/**     frame_size_history_extra **/
+/**       (f, build_string ("xg_frame_resized, unchanged"), **/
+/**        FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, **/
+/**        f->new_size_p ? f->new_width : -1, **/
+/**        f->new_size_p ? f->new_height : -1); **/
 
 }