diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h index 6d62af855..096373fbf 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 53db2df4a..a32f7affa 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 5bc16de3b..b95cec7e8 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 bed3404f7..5588867fd 100644 --- a/src/compositor/meta-compositor-view.h +++ b/src/compositor/meta-compositor-view.h @@ -28,6 +28,7 @@ #include #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 ae1fa4d90..9fd9f758c 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);