compositor: Update topmost window actor after visibility changes

The compositor currently only updates the topmost window actor that is
visible to it after stacking changes. The visibility of a window actor
to the compositor however might only change via the display idle queue
after the stacking changes. This could then lead to the topmost window
actor being assumed to be NULL on Wayland after switching from an empty
workspace or when opening the first window on an empty workspace. The
result of this is direct scanout being disabled in these cases.

To fix this also trigger the update when the visibility of windows
changes.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2269
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2413>
This commit is contained in:
Sebastian Keller 2022-05-12 17:42:20 +02:00 committed by Marge Bot
parent 0bc142ec1b
commit bb76d6fcc3

View File

@ -107,6 +107,7 @@ typedef struct _MetaCompositorPrivate
gulong stage_presented_id;
gulong before_paint_handler_id;
gulong after_paint_handler_id;
gulong window_visibility_updated_id;
int64_t server_time_query_time;
int64_t server_time_offset;
@ -1042,6 +1043,16 @@ on_after_paint (ClutterStage *stage,
meta_compositor_after_paint (compositor, stage_view);
}
static void
on_window_visibility_updated (MetaDisplay *display,
GList *unplaced,
GList *should_show,
GList *should_hide,
MetaCompositor *compositor)
{
update_top_window_actor (compositor);
}
static void
meta_compositor_set_property (GObject *object,
guint prop_id,
@ -1116,6 +1127,12 @@ meta_compositor_constructed (GObject *object)
G_CALLBACK (on_after_paint),
compositor);
priv->window_visibility_updated_id =
g_signal_connect (priv->display,
"window-visibility-updated",
G_CALLBACK (on_window_visibility_updated),
compositor);
priv->laters = meta_laters_new (compositor);
G_OBJECT_CLASS (meta_compositor_parent_class)->constructed (object);
@ -1134,6 +1151,7 @@ meta_compositor_dispose (GObject *object)
g_clear_signal_handler (&priv->stage_presented_id, stage);
g_clear_signal_handler (&priv->before_paint_handler_id, stage);
g_clear_signal_handler (&priv->after_paint_handler_id, stage);
g_clear_signal_handler (&priv->window_visibility_updated_id, priv->display);
g_clear_pointer (&priv->windows, g_list_free);