GNOME Bugzilla – Bug 777072
window shrinks when restored from maximized
Last modified: 2017-10-26 19:50:16 UTC
I have experienced that window sizes consistently decreases beyond whats to be expected when restored from a maximized state.
The behavior became clear after opening four terminals in a square (2x2) and using super + arrow up/down to maximize and restore one window. Repeatedly maximizing and restoring the same terminal window shrunk the size from 80x25 to 32x3 characters. The window did not shrink beyond that. Maximizing and restoring window sizes by double clicking the titlebar produces the same behavior.
I have also reported this at https://bugzilla.redhat.com/show_bug.cgi?id=1411876. I attached a short demo to that bug showing the window size after each resize.
I'm pretty sure the problem only occurs only with programs whose geometry has "steps", like gnome-terminal. The window shrinks by one step each time it's restored from a maximized state.
*** Bug 780563 has been marked as a duplicate of this bug. ***
Reproduced this on Wayland, and as far I could tell, gnome-shell did the correct thing. I verified this by inspecting what sizes it got from the client, and how it restored them. What I could see was:
1. gnome-shell got the original terminal window size "S1"
2. gnome-shell maximized the window, telling the client to resize to size "SM" (maximized size)
3. the client resized to "SM"
4. gnome-shell unmaximized the window, telling the client to resize back to "S1"
5. the client resized to "S2", a size smaller than "S1"
So the bug is either in GTK+ or in gnome-terminal. Moving to gtk+ for now.
gnome-terminal sets geometry hints with GDK_HINT_RESIZE_INC, with this parameter window shrinking from maximum happens some time.
In function gdk_window_constrain_size
if (flags & GDK_HINT_RESIZE_INC)
xinc = MAX (xinc, geometry->width_inc);
yinc = MAX (yinc, geometry->height_inc);
/* shrink to base + N * inc
width = base_width + FLOOR (width - base_width, xinc);
height = base_height + FLOOR (height - base_height, yinc);
#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
With GDK_HINT_RESIZE_INC flag, xinc an yinc will equal width_inc and height_inc, width_inc and height_inc are character width and height.
From xinc and base_width, get window width by formula 'base_width + FLOOR (width - base_width, xinc)'.
On my computer, when run on X11, base_width is 2, new width is same size as old.
When run on Wayland, base_width is 54, after calculation new width shrinks than old.
So here base_width and base_height are important, some value will make window size shrink.
base_width and base_height come from function terminal_window_update_geometry in gnome-terminal
hints.base_width = chrome_width + csd_width;
hints.base_height = chrome_height + csd_height;
Here csd_width makes base_width different. On X11, csd_width is 0. On Wayland, csd_width is 52.
csd_width = toplevel_allocation.width - vbox_allocation.width;
csd_height = toplevel_allocation.height - vbox_allocation.height;
toplevel_allocation.width is different on X11 and Wayland. Now I don't know why they are different.
Maybe formula 'base_width + FLOOR (width - base_width, xinc)' needs to be changed.
Created attachment 354151 [details] [review]
[PATCH] wayland: Do not constrain saved window size
Under Wayland, an xdg_surface.configure with size 0x0 means it's up to
the client to set its size.
When transitioning from maximized state to un-maximized, the Wayland
compositor will send such an 0x0 configure so that the client can
restore its original size.
However, the original size was already constrained, so re-applying
size constrains can lead to a smaller size when using size increments.
Avoid this caveat by not applying size constrains when we are restoring
the original size.