window-props: Check for actual size hints changes

The XSizeHints set by X11 clients give a hint to the window manager
about size increment, aspect ratio, base, minimum and maximum size, etc.

When an X11 client changes those values, there is a good chance that it
will affect the actual window size in some way, and mutter rightfully
queue a window resize in that case.

However, mutter does not check if any of the hints have actually changed
and unconditionally queue a window resize whenever a client changes its
WM_NORMAL_HINTS property.

That can be a problem when a zealous client such as xterm decides to
update its WM_NORMAL_HINTS property on resize, because in return mutter
will queue a non-user driven resize in the middle of user-driven events,
hence defeating the purpose of the META_MOVE_RESIZE_USER_ACTION flag.

To avoid that issue, make mutter a bit smarter and avoid queuing a
window resize if the XSizeHints haven't actually changed.

https://gitlab.gnome.org/GNOME/mutter/-/issues/543
This commit is contained in:
Olivier Fourdan 2020-10-15 14:23:41 +02:00
parent 03c69ed8cf
commit deaa9480a8

View File

@ -1140,6 +1140,22 @@ spew_size_hints_differences (const XSizeHints *old,
old->win_gravity, new->win_gravity);
}
static gboolean
hints_have_changed (const XSizeHints *old,
const XSizeHints *new)
{
return FLAG_CHANGED (old, new, USPosition) ||
FLAG_CHANGED (old, new, USSize) ||
FLAG_CHANGED (old, new, PPosition) ||
FLAG_CHANGED (old, new, PSize) ||
FLAG_CHANGED (old, new, PMinSize) ||
FLAG_CHANGED (old, new, PMaxSize) ||
FLAG_CHANGED (old, new, PResizeInc) ||
FLAG_CHANGED (old, new, PAspect) ||
FLAG_CHANGED (old, new, PBaseSize) ||
FLAG_CHANGED (old, new, PWinGravity);
}
void
meta_set_normal_hints (MetaWindow *window,
XSizeHints *hints)
@ -1490,6 +1506,7 @@ reload_normal_hints (MetaWindow *window,
if (value->type != META_PROP_VALUE_INVALID)
{
XSizeHints old_hints;
gboolean hints_have_differences;
meta_topic (META_DEBUG_GEOMETRY, "Updating WM_NORMAL_HINTS for %s", window->desc);
@ -1497,12 +1514,16 @@ reload_normal_hints (MetaWindow *window,
meta_set_normal_hints (window, value->v.size_hints.hints);
spew_size_hints_differences (&old_hints, &window->size_hints);
hints_have_differences = hints_have_changed (&old_hints,
&window->size_hints);
if (hints_have_differences)
{
spew_size_hints_differences (&old_hints, &window->size_hints);
meta_window_recalc_features (window);
meta_window_recalc_features (window);
if (!initial)
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
if (!initial)
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
}
}
}