Subject: bug#21317: 25.0.50; frame-resize-pixelwise has no effect (GTK, no window manager)

From: martin rudalics <[email-masked]>
Date: Sat, 22 Aug 2015 16:16:47 +0200

> Thanks for responding!

Thanks for investigating!

 > On Sat, Aug 22, 2015 at 6:40 AM, martin rudalics <[email-masked]> wrote:
 >>> When starting Emacs (GTK build) on an X server which has no window
 >>> manager (such as a newly-created Xnest session), setting
 >>> `frame-resize-pixelwise' to t followed by a resize operation often has
 >>> no effect.
 >>
 >> According to the manual
 >>
 >>       Setting this variable usually causes the next resize operation to
 >>       pass the corresponding size hints to the window manager.  This
 >>       means that this variable should be set only in a user's initial
 >>       file; applications should never bind it temporarily.
 >
 > That documentation is outdated and does not apply to GTK builds in all
 > cases, I'm afraid. It is not the window manager that decides to honor
 > or dishonor frame-resize-pixelwise but GDK.

"Window manager" was an attempt to catch the behavior of all toolkits
including Windows which doesn't have a window manager either.  Feel free
to suggest a better term.

 > See x_wm_set_size_hint and
 > gtk_window_move_resize (gtkwindow.c, in the GTK sources). In
 > particular, gtk_window_compute_configure_request calls
 > gtk_window_constrain_size which calls gdk_window_constrain_size which
 > calculates
 >
 >    width = base_width + FLOOR (width - base_width, xinc);
 >    height = base_height + FLOOR (height - base_height, yinc);
 >
 > (where FLOOR is defined as #define FLOOR(value, base)    ( ((gint)
 > ((value) / (base))) * (base) ) )

I can't find that in the version from

https://github.com/GNOME/gtk/blob/master/gtk/gtkwindow.c

and also must admit that I have forgotten most of the GTK code by now.

IIRC base_width and base_height are somehow calculated from a minimum
size and what Emacs requested earlier.  If frame_resize_pixelwise is
true we _should_ have requested 1 from this

   size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
   size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);

Can you check how apparently an "integral" (the increment is a multiple
of either FRAME_COLUMN_WIDTH or FRAME_LINE_HEIGHT) value gets passed via
size_hints in your case?

 >> So it's possible that Xnest or some other X component refuses to resize
 >> your frame because the size hints were set up inappropriately.
 >
 > I'm pretty sure that's not what's happening, but I'll be happy to
 > provide traces to demonstrate my analysis is correct...or to prove it
 > wrong, of course! The attached gdb log shows quite clearly that it's
 > GDK making the second (erroneous) call to XResizeWindow, not Xnest
 > (there is no window manager).

OK.  I won't doubt what you say here.

 >> Does it also fail when `frame-resize-pixelwise' is set to t in your
 >> initial file?
 >
 > Yes, it does.

That's bad.  It can only mean that we send an integral resize request
_before_ Emacs reads the initial file and the subsequent "real" resize
request fails because the size hints have been already set up wrongly.

 >> Does it fail when you set `frame-resize-pixelwise' to t, request an
 >> integral resize first and a second non-integral one afterwards?
 >
 > I'm not sure I fully understand how you define "integral".

See above.  Also the "first and a second" above was meant to do this in
two consecutive commands (that is, with a redisplay in between).
Passing different size requests in one and the same command can have
unpredictable consequences (at least on other platforms).

 > In short,
 > non-full-screen resize + redisplay + full-screen resize works, the
 > other combinations do not.
 >
 > If I run this code (Xnest running on display :3):
 >
 > DISPLAY=:3 emacs -Q --eval "(progn (setq frame-resize-pixelwise t)
 > (set-frame-height (selected-frame) (1+ (frame-pixel-height
 > (selected-frame))) nil t) (redisplay) (set-frame-parameter
 > (selected-frame) 'fullscreen 'fullboth))"
 >
 > Things work, but without the "(redisplay)" they don't. (So that's a
 > non-full-screen resize first, then a full-screen resize). Doing the
 > full-screen resize first breaks things.

"Breaks" in what sense?  That it does nothing or not fully resize?

 > I must also point out that without the "(redisplay)", there are
 > unexpected results: the full screen resize appears to be ignored
 > entirely.

I'd have expected that.

 > But, again, I currently stand by my initial analysis of what's
 > happening. The problem is that we cannot simply do the right thing
 > because of the KWin bug...

What is the "KWin bug"?

I'm probably too silly to give you a good advice.  However, in
xg_frame_set_char_size (which is responsible for the resize in the GTK
case) we could do the

x_wm_set_size_hint (f, 0, 0);

_before_ calling gtk_window_resize.  Could you play around with that?

BTW if you set `frame-size-history' to a non-nil value you should get a
list of frame resizing operations you can watch with the function
`frame--size-history'.  IIRC I found GDB occasionally not 100% reliable
to reproduce the actual history as of a normal, optimized build.

martin