window-props: Also check for actual values change

Commit e28c1ab4 added a hints_have_changed() function to only
recalculate windows features when the WM_NORMAL_HINTS change.

That function hints_have_changed() however was merely checking whether
the various XSizeHints flags where flipped, which is not sufficient
because the hints may remain the same while the actual values are
changed.

Not checking for the actual value differences would prevent some windows
from being able to switch fullscreen.

Improve the helper function hints_have_changed() to check not only for
flags being flipped, but also for the values being changed for each
relevant XSizeHints flags being set currently.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1534
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1566>
This commit is contained in:
Olivier Fourdan 2020-11-16 16:50:24 +01:00 committed by Marge Bot
parent b2126fec92
commit 06e604cfef

View File

@ -1080,13 +1080,19 @@ reload_update_counter (MetaWindow *window,
} }
} }
#define FLAG_IS_ON(hints,flag) \
(((hints)->flags & (flag)) != 0)
#define FLAG_IS_OFF(hints,flag) \
(((hints)->flags & (flag)) == 0)
#define FLAG_TOGGLED_ON(old,new,flag) \ #define FLAG_TOGGLED_ON(old,new,flag) \
(((old)->flags & (flag)) == 0 && \ (FLAG_IS_OFF(old,flag) && \
((new)->flags & (flag)) != 0) FLAG_IS_ON(new,flag))
#define FLAG_TOGGLED_OFF(old,new,flag) \ #define FLAG_TOGGLED_OFF(old,new,flag) \
(((old)->flags & (flag)) != 0 && \ (FLAG_IS_ON(old,flag) && \
((new)->flags & (flag)) == 0) FLAG_IS_OFF(new,flag))
#define FLAG_CHANGED(old,new,flag) \ #define FLAG_CHANGED(old,new,flag) \
(FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag)) (FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag))
@ -1144,16 +1150,80 @@ static gboolean
hints_have_changed (const XSizeHints *old, hints_have_changed (const XSizeHints *old,
const XSizeHints *new) const XSizeHints *new)
{ {
return FLAG_CHANGED (old, new, USPosition) || /* 1. Check if the relevant values have changed if the flag is set. */
FLAG_CHANGED (old, new, USSize) ||
FLAG_CHANGED (old, new, PPosition) || if (FLAG_TOGGLED_ON (old, new, USPosition) ||
FLAG_CHANGED (old, new, PSize) || (FLAG_IS_ON (new, USPosition) &&
FLAG_CHANGED (old, new, PMinSize) || (old->x != new->x ||
FLAG_CHANGED (old, new, PMaxSize) || old->y != new->y)))
FLAG_CHANGED (old, new, PResizeInc) || return TRUE;
FLAG_CHANGED (old, new, PAspect) ||
FLAG_CHANGED (old, new, PBaseSize) || if (FLAG_TOGGLED_ON (old, new, USSize) ||
FLAG_CHANGED (old, new, PWinGravity); (FLAG_IS_ON (new, USSize) &&
(old->width != new->width ||
old->height != new->height)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PPosition) ||
(FLAG_IS_ON (new, PPosition) &&
(old->x != new->x ||
old->y != new->y)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PSize) ||
(FLAG_IS_ON (new, PSize) &&
(old->width != new->width ||
old->height != new->height)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PMinSize) ||
(FLAG_IS_ON (new, PMinSize) &&
(old->min_width != new->min_width ||
old->min_height != new->min_height)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PMaxSize) ||
(FLAG_IS_ON (new, PMaxSize) &&
(old->max_width != new->max_width ||
old->max_height != new->max_height)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PResizeInc) ||
(FLAG_IS_ON (new, PResizeInc) &&
(old->width_inc != new->width_inc ||
old->height_inc != new->height_inc)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PAspect) ||
(FLAG_IS_ON (new, PAspect) &&
(old->min_aspect.x != new->min_aspect.x ||
old->min_aspect.y != new->min_aspect.y ||
old->max_aspect.x != new->max_aspect.x ||
old->max_aspect.y != new->max_aspect.y)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PBaseSize) ||
(FLAG_IS_ON (new, PBaseSize) &&
(old->base_width != new->base_width ||
old->base_height != new->base_height)))
return TRUE;
if (FLAG_TOGGLED_ON (old, new, PWinGravity) ||
(FLAG_IS_ON (new, PWinGravity) &&
(old->win_gravity != new->win_gravity)))
return TRUE;
/* 2. Check if the flags have been unset. */
return FLAG_TOGGLED_OFF (old, new, USPosition) ||
FLAG_TOGGLED_OFF (old, new, USSize) ||
FLAG_TOGGLED_OFF (old, new, PPosition) ||
FLAG_TOGGLED_OFF (old, new, PSize) ||
FLAG_TOGGLED_OFF (old, new, PMinSize) ||
FLAG_TOGGLED_OFF (old, new, PMaxSize) ||
FLAG_TOGGLED_OFF (old, new, PResizeInc) ||
FLAG_TOGGLED_OFF (old, new, PAspect) ||
FLAG_TOGGLED_OFF (old, new, PBaseSize) ||
FLAG_TOGGLED_OFF (old, new, PWinGravity);
} }
void void