compositor: Keep track of the top window actor on each view

First, add logic in MetaCompositorView to find topmost visible
MetaWindowActor on its view, and expose it through a new API.

Then, queue an update to find the top MetaWindowActor of each
MetaCompositorView in the following cases:
  1. The MetaCompositor is in its initial state.
  2. The window stack order has changed.
  3. A window has changed its visibility.
  4. A "stage-views-changed" signal was emitted for a MetaWindowActor.

Finally, perform the queued update in meta_compositor_before_paint (),
and assert that an update isn't queued during painting. This ensures
that the top window actor in the MetaCompositorView remains up-to-date
and available to child classes of MetaCompositor throughout the entire
paint stage.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
This commit is contained in:
Dor Askayo 2022-07-02 22:51:13 +03:00 committed by Marge Bot
parent 2ead3874f5
commit 85b8632cd6
5 changed files with 153 additions and 0 deletions

View File

@ -43,6 +43,8 @@ gboolean meta_compositor_do_manage (MetaCompositor *compositor,
void meta_compositor_remove_window_actor (MetaCompositor *compositor,
MetaWindowActor *window_actor);
void meta_compositor_window_actor_stage_views_changed (MetaCompositor *compositor);
void meta_switch_workspace_completed (MetaCompositor *compositor);
MetaPluginManager * meta_compositor_get_plugin_manager (MetaCompositor *compositor);

View File

@ -123,6 +123,8 @@ typedef struct _MetaCompositorPrivate
CoglContext *context;
gboolean needs_update_top_window_actors;
MetaWindowActor *top_window_actor;
gulong top_window_actor_destroy_id;
@ -592,6 +594,23 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
meta_window_actor_update_opacity (window_actor);
}
static void
invalidate_top_window_actor_for_views (MetaCompositor *compositor)
{
MetaCompositorPrivate *priv =
meta_compositor_get_instance_private (compositor);
g_assert (!priv->frame_in_progress);
priv->needs_update_top_window_actors = TRUE;
}
void
meta_compositor_window_actor_stage_views_changed (MetaCompositor *compositor)
{
invalidate_top_window_actor_for_views (compositor);
}
gboolean
meta_compositor_filter_keybinding (MetaCompositor *compositor,
MetaKeyBinding *binding)
@ -913,6 +932,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
sync_actor_stacking (compositor);
update_top_window_actor (compositor);
invalidate_top_window_actor_for_views (compositor);
}
void
@ -931,6 +951,39 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
meta_plugin_manager_event_size_changed (priv->plugin_mgr, window_actor);
}
static void
maybe_update_top_window_actor_for_views (MetaCompositor *compositor)
{
MetaCompositorPrivate *priv =
meta_compositor_get_instance_private (compositor);
ClutterStage *stage;
GList *l;
if (!priv->needs_update_top_window_actors)
return;
priv->needs_update_top_window_actors = FALSE;
COGL_TRACE_BEGIN_SCOPED (UpdateTopWindowActorForViews,
"Compositor (update top window actors)");
stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
{
ClutterStageView *stage_view = l->data;
MetaCompositorView *compositor_view;
compositor_view = g_object_get_qdata (G_OBJECT (stage_view),
quark_compositor_view);
g_assert (compositor_view != NULL);
meta_compositor_view_update_top_window_actor (compositor_view,
priv->windows);
}
}
static void
meta_compositor_ensure_compositor_views (MetaCompositor *compositor)
{
@ -1011,6 +1064,8 @@ meta_compositor_before_paint (MetaCompositor *compositor,
COGL_TRACE_BEGIN_SCOPED (MetaCompositorPrePaint,
"Compositor (before-paint)");
maybe_update_top_window_actor_for_views (compositor);
priv->frame_in_progress = TRUE;
META_COMPOSITOR_GET_CLASS (compositor)->before_paint (compositor, compositor_view);
@ -1116,6 +1171,7 @@ on_window_visibility_updated (MetaDisplay *display,
MetaCompositor *compositor)
{
update_top_window_actor (compositor);
invalidate_top_window_actor_for_views (compositor);
}
static void
@ -1174,6 +1230,7 @@ meta_compositor_get_property (GObject *object,
static void
meta_compositor_init (MetaCompositor *compositor)
{
invalidate_top_window_actor_for_views (compositor);
}
static void

View File

@ -26,6 +26,10 @@
#include "compositor/meta-compositor-view.h"
#include "core/window-private.h"
#include "meta/boxes.h"
#include "meta/window.h"
enum
{
PROP_0,
@ -40,6 +44,8 @@ static GParamSpec *obj_props[N_PROPS];
typedef struct _MetaCompositorViewPrivate
{
ClutterStageView *stage_view;
MetaWindowActor *top_window_actor;
} MetaCompositorViewPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCompositorView, meta_compositor_view,
@ -55,6 +61,58 @@ meta_compositor_view_new (ClutterStageView *stage_view)
NULL);
}
static MetaWindowActor *
find_top_window_actor_on_view (ClutterStageView *stage_view,
GList *window_actors)
{
GList *l;
for (l = g_list_last (window_actors); l; l = l->prev)
{
MetaWindowActor *window_actor = l->data;
MetaWindow *window =
meta_window_actor_get_meta_window (window_actor);
MetaRectangle buffer_rect;
MetaRectangle view_layout;
if (!window->visible_to_compositor)
continue;
meta_window_get_buffer_rect (window, &buffer_rect);
clutter_stage_view_get_layout (stage_view,
&view_layout);
if (meta_rectangle_overlap (&view_layout, &buffer_rect))
return window_actor;
}
return NULL;
}
void
meta_compositor_view_update_top_window_actor (MetaCompositorView *compositor_view,
GList *window_actors)
{
MetaCompositorViewPrivate *priv =
meta_compositor_view_get_instance_private (compositor_view);
MetaWindowActor *top_window_actor;
top_window_actor = find_top_window_actor_on_view (priv->stage_view,
window_actors);
g_set_weak_pointer (&priv->top_window_actor,
top_window_actor);
}
MetaWindowActor *
meta_compositor_view_get_top_window_actor (MetaCompositorView *compositor_view)
{
MetaCompositorViewPrivate *priv =
meta_compositor_view_get_instance_private (compositor_view);
return priv->top_window_actor;
}
ClutterStageView *
meta_compositor_view_get_stage_view (MetaCompositorView *compositor_view)
{
@ -104,6 +162,16 @@ meta_compositor_view_get_property (GObject *object,
}
}
static void
meta_compositor_view_finalize (GObject *object)
{
MetaCompositorView *compositor_view = META_COMPOSITOR_VIEW (object);
MetaCompositorViewPrivate *priv =
meta_compositor_view_get_instance_private (compositor_view);
g_clear_weak_pointer (&priv->top_window_actor);
}
static void
meta_compositor_view_class_init (MetaCompositorViewClass *klass)
{
@ -111,6 +179,7 @@ meta_compositor_view_class_init (MetaCompositorViewClass *klass)
object_class->set_property = meta_compositor_view_set_property;
object_class->get_property = meta_compositor_view_get_property;
object_class->finalize = meta_compositor_view_finalize;
obj_props[PROP_STAGE_VIEW] =
g_param_spec_object ("stage-view",

View File

@ -28,6 +28,7 @@
#include <glib-object.h>
#include "clutter/clutter-mutter.h"
#include "meta/meta-window-actor.h"
struct _MetaCompositorViewClass
{
@ -40,6 +41,11 @@ G_DECLARE_FINAL_TYPE (MetaCompositorView, meta_compositor_view,
MetaCompositorView *meta_compositor_view_new (ClutterStageView *stage_view);
void meta_compositor_view_update_top_window_actor (MetaCompositorView *compositor_view,
GList *window_actors);
MetaWindowActor *meta_compositor_view_get_top_window_actor (MetaCompositorView *compositor_view);
ClutterStageView *meta_compositor_view_get_stage_view (MetaCompositorView *compositor_view);
#endif /* META_COMPOSITOR_VIEW_H */

View File

@ -53,6 +53,8 @@ typedef struct _MetaWindowActorPrivate
MetaWindow *window;
MetaCompositor *compositor;
gulong stage_views_changed_id;
MetaSurfaceActor *surface;
int geometry_scale;
@ -402,6 +404,15 @@ init_surface_actor (MetaWindowActor *self)
meta_window_actor_assign_surface_actor (self, surface_actor);
}
static void
on_stage_views_changed (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv =
meta_window_actor_get_instance_private (self);
meta_compositor_window_actor_stage_views_changed (priv->compositor);
}
static void
meta_window_actor_constructed (GObject *object)
{
@ -412,6 +423,12 @@ meta_window_actor_constructed (GObject *object)
priv->compositor = window->display->compositor;
priv->stage_views_changed_id =
g_signal_connect (self,
"stage-views-changed",
G_CALLBACK (on_stage_views_changed),
NULL);
/* Hang our compositor window state off the MetaWindow for fast retrieval */
meta_window_set_compositor_private (window, object);
@ -445,6 +462,8 @@ meta_window_actor_dispose (GObject *object)
priv->disposed = TRUE;
g_clear_signal_handler (&priv->stage_views_changed_id, self);
meta_compositor_remove_window_actor (compositor, self);
g_clear_object (&priv->window);