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



commit 85b8632cd65aecc4c3cb3de70772dcd7f01875e7
Author: Dor Askayo <dor askayo gmail com>
Date:   Sat Jul 2 22:51:13 2022 +0300

    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>

 src/compositor/compositor-private.h   |  2 +
 src/compositor/compositor.c           | 57 +++++++++++++++++++++++++++++
 src/compositor/meta-compositor-view.c | 69 +++++++++++++++++++++++++++++++++++
 src/compositor/meta-compositor-view.h |  6 +++
 src/compositor/meta-window-actor.c    | 19 ++++++++++
 5 files changed, 153 insertions(+)
---
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 6d62af8558..096373fbfb 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -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);
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 53db2df4a6..a32f7affa6 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -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
diff --git a/src/compositor/meta-compositor-view.c b/src/compositor/meta-compositor-view.c
index 5bc16de3bf..b95cec7e87 100644
--- a/src/compositor/meta-compositor-view.c
+++ b/src/compositor/meta-compositor-view.c
@@ -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",
diff --git a/src/compositor/meta-compositor-view.h b/src/compositor/meta-compositor-view.h
index bed3404f78..5588867fd7 100644
--- a/src/compositor/meta-compositor-view.h
+++ b/src/compositor/meta-compositor-view.h
@@ -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 */
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index ae1fa4d903..9fd9f758c6 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]