7474#include "meta/compositor-muffin.h"
7575#include "meta/main.h"
7676#include "meta/meta-backend.h"
77- #include "meta/meta-background-actor.h"
78- #include "meta/meta-background-group.h"
77+ #include "meta/meta-monitor-manager.h"
7978#include "meta/meta-shadow-factory.h"
8079#include "meta/meta-x11-errors.h"
8180#include "meta/meta-x11-background-actor.h"
8584
8685#ifdef HAVE_WAYLAND
8786#include "compositor/meta-window-actor-wayland.h"
87+ #include "meta/meta-wayland-background-actor.h"
88+ #include "wayland/meta-wayland-layer-shell.h"
89+ #include "wayland/meta-wayland-outputs.h"
8890#include "wayland/meta-wayland-private.h"
8991#endif
9092
@@ -127,7 +129,7 @@ typedef struct _MetaCompositorPrivate
127129 ClutterActor * feedback_group ;
128130 ClutterActor * bottom_window_group ;
129131
130- ClutterActor * background_actor ;
132+ GList * background_actors ;
131133 ClutterActor * desklet_container ;
132134
133135 GList * windows ;
@@ -579,6 +581,123 @@ meta_compositor_redirect_x11_windows (MetaCompositor *compositor)
579581 redirect_windows (display -> x11_display );
580582}
581583
584+ static void
585+ rebuild_x11_background_actors (MetaCompositor * compositor )
586+ {
587+ MetaCompositorPrivate * priv =
588+ meta_compositor_get_instance_private (compositor );
589+ MetaDisplay * display = priv -> display ;
590+ int i , n ;
591+
592+ g_list_free_full (priv -> background_actors , (GDestroyNotify ) clutter_actor_destroy );
593+ priv -> background_actors = NULL ;
594+
595+ n = meta_display_get_n_monitors (display );
596+ for (i = 0 ; i < n ; i ++ )
597+ {
598+ ClutterActor * actor ;
599+ MetaRectangle rect ;
600+
601+ actor = meta_x11_background_actor_new_for_monitor (display , i );
602+ if (actor == NULL )
603+ continue ;
604+
605+ meta_display_get_monitor_geometry (display , i , & rect );
606+ clutter_actor_set_position (actor , rect .x , rect .y );
607+ clutter_actor_set_size (actor , rect .width , rect .height );
608+
609+ clutter_actor_add_child (priv -> window_group , actor );
610+ priv -> background_actors = g_list_append (priv -> background_actors , actor );
611+ }
612+ }
613+
614+ static void
615+ on_monitors_changed (MetaMonitorManager * monitor_manager ,
616+ MetaCompositor * compositor )
617+ {
618+ if (!meta_is_wayland_compositor ())
619+ rebuild_x11_background_actors (compositor );
620+ }
621+
622+ #ifdef HAVE_WAYLAND
623+ static int
624+ get_monitor_index_for_layer_surface (MetaWaylandLayerSurface * layer_surface )
625+ {
626+ MetaWaylandCompositor * wl_compositor =
627+ meta_wayland_compositor_get_default ();
628+ MetaWaylandOutput * surface_output =
629+ meta_wayland_layer_surface_get_output (layer_surface );
630+ MetaDisplay * display = meta_get_display ();
631+ int i , n ;
632+
633+ if (!surface_output )
634+ return -1 ;
635+
636+ n = meta_display_get_n_monitors (display );
637+ for (i = 0 ; i < n ; i ++ )
638+ {
639+ MetaWaylandOutput * output =
640+ meta_wayland_compositor_get_output_for_monitor (wl_compositor , i );
641+ if (output == surface_output )
642+ return i ;
643+ }
644+
645+ return -1 ;
646+ }
647+
648+ static void
649+ on_layer_surface_mapped (MetaWaylandLayerShell * layer_shell ,
650+ MetaWaylandLayerSurface * layer_surface ,
651+ MetaCompositor * compositor )
652+ {
653+ MetaCompositorPrivate * priv =
654+ meta_compositor_get_instance_private (compositor );
655+ MetaSurfaceActor * surface_actor ;
656+ int monitor_index ;
657+
658+ if (meta_wayland_layer_surface_get_layer (layer_surface ) !=
659+ META_LAYER_SHELL_LAYER_BACKGROUND )
660+ return ;
661+
662+ surface_actor = meta_wayland_actor_surface_get_actor (
663+ META_WAYLAND_ACTOR_SURFACE (layer_surface ));
664+ if (!surface_actor )
665+ return ;
666+
667+ monitor_index = get_monitor_index_for_layer_surface (layer_surface );
668+
669+ if (monitor_index < 0 )
670+ {
671+ priv -> background_actors =
672+ g_list_append (priv -> background_actors , surface_actor );
673+ return ;
674+ }
675+
676+ priv -> background_actors =
677+ g_list_insert (priv -> background_actors , surface_actor , monitor_index );
678+ }
679+
680+ static void
681+ on_layer_surface_unmapped (MetaWaylandLayerShell * layer_shell ,
682+ MetaWaylandLayerSurface * layer_surface ,
683+ MetaCompositor * compositor )
684+ {
685+ MetaCompositorPrivate * priv =
686+ meta_compositor_get_instance_private (compositor );
687+ MetaSurfaceActor * surface_actor ;
688+
689+ if (meta_wayland_layer_surface_get_layer (layer_surface ) !=
690+ META_LAYER_SHELL_LAYER_BACKGROUND )
691+ return ;
692+
693+ surface_actor = meta_wayland_actor_surface_get_actor (
694+ META_WAYLAND_ACTOR_SURFACE (layer_surface ));
695+
696+ priv -> background_actors =
697+ g_list_remove (priv -> background_actors , surface_actor );
698+ }
699+ #endif
700+
582701gboolean
583702meta_compositor_do_manage (MetaCompositor * compositor ,
584703 GError * * error )
@@ -615,14 +734,11 @@ meta_compositor_do_manage (MetaCompositor *compositor,
615734 priv -> feedback_group = meta_window_group_new (display );
616735
617736 if (!meta_is_wayland_compositor ())
618- {
619- priv -> background_actor = meta_x11_background_actor_new_for_display (display );
620- clutter_actor_add_child (priv -> window_group , priv -> background_actor );
621- }
737+ rebuild_x11_background_actors (compositor );
622738
623739 clutter_actor_add_child (priv -> window_group , priv -> bottom_window_group );
624740
625- // This needs to remain stacked just above the background actor in the window group.
741+ // This needs to remain stacked just above the background actors in the window group.
626742 // So sync_actor_stacking() has to be able to reference it. The deskletManager
627743 // will take this and finish setting it up.
628744 priv -> desklet_container = clutter_actor_new ();
@@ -634,6 +750,27 @@ meta_compositor_do_manage (MetaCompositor *compositor,
634750 if (!META_COMPOSITOR_GET_CLASS (compositor )-> manage (compositor , error ))
635751 return FALSE;
636752
753+ g_signal_connect (meta_monitor_manager_get (), "monitors-changed" ,
754+ G_CALLBACK (on_monitors_changed ), compositor );
755+
756+ #ifdef HAVE_WAYLAND
757+ if (meta_is_wayland_compositor ())
758+ {
759+ MetaWaylandCompositor * wl_compositor =
760+ meta_wayland_compositor_get_default ();
761+ MetaWaylandLayerShell * layer_shell =
762+ meta_wayland_compositor_get_layer_shell (wl_compositor );
763+
764+ if (layer_shell )
765+ {
766+ g_signal_connect (layer_shell , "layer-surface-mapped" ,
767+ G_CALLBACK (on_layer_surface_mapped ), compositor );
768+ g_signal_connect (layer_shell , "layer-surface-unmapped" ,
769+ G_CALLBACK (on_layer_surface_unmapped ), compositor );
770+ }
771+ }
772+ #endif
773+
637774 priv -> plugin_mgr = meta_plugin_manager_new (compositor );
638775
639776 clutter_actor_show (priv -> stage );
@@ -963,9 +1100,7 @@ sync_actor_stacking (MetaCompositor *compositor)
9631100 {
9641101 ClutterActor * actor = old -> data ;
9651102
966- if (META_IS_BACKGROUND_GROUP (actor ) ||
967- META_IS_BACKGROUND_ACTOR (actor ) ||
968- META_IS_X11_BACKGROUND_ACTOR (actor ))
1103+ if (META_IS_X11_BACKGROUND_ACTOR (actor ))
9691104 {
9701105 backgrounds = g_list_prepend (backgrounds , actor );
9711106
@@ -1018,31 +1153,6 @@ sync_actor_stacking (MetaCompositor *compositor)
10181153 // Then the bottom window group (which META_WINDOW_DESKTOP windows like nemo-desktop's get placed in).
10191154 clutter_actor_set_child_below_sibling (priv -> window_group , priv -> bottom_window_group , NULL );
10201155
1021- if (meta_is_wayland_compositor ())
1022- {
1023- children = clutter_actor_get_children (priv -> bottom_window_group );
1024- for (tmp = children ; tmp != NULL ; tmp = tmp -> next )
1025- {
1026- MetaWindowActor * child = tmp -> data ;
1027- MetaWindow * mw = meta_window_actor_get_meta_window (child );
1028-
1029- if (mw != NULL )
1030- {
1031- // CsdBackground manager sets _NET_WM_STATE_BELOW (gtk_window_set_keep_below)
1032- // This sets its stack layer to META_LAYER_BOTTOM, so we can keep these below
1033- // the nemo-desktop, etc..
1034- MetaStackLayer layer = meta_window_get_default_layer (mw );
1035-
1036- if (layer == META_LAYER_BOTTOM )
1037- {
1038- clutter_actor_set_child_below_sibling (priv -> bottom_window_group , CLUTTER_ACTOR (child ), NULL );
1039- }
1040- }
1041- }
1042-
1043- g_list_free (children );
1044- }
1045-
10461156 // and finally backgrounds..
10471157
10481158 /* we prepended the backgrounds above so the last actor in the list
@@ -1438,7 +1548,12 @@ meta_compositor_dispose (GObject *object)
14381548 g_clear_signal_handler (& priv -> top_window_actor_destroy_id ,
14391549 priv -> top_window_actor );
14401550
1441- g_clear_pointer (& priv -> background_actor , clutter_actor_destroy );
1551+ if (!meta_is_wayland_compositor ())
1552+ {
1553+ for (GList * l = priv -> background_actors ; l ; l = l -> next )
1554+ clutter_actor_destroy (l -> data );
1555+ }
1556+ g_clear_pointer (& priv -> background_actors , g_list_free );
14421557 g_clear_pointer (& priv -> bottom_window_group , clutter_actor_destroy );
14431558 g_clear_pointer (& priv -> desklet_container , clutter_actor_destroy );
14441559 g_clear_pointer (& priv -> window_group , clutter_actor_destroy );
@@ -1783,24 +1898,21 @@ meta_compositor_get_laters (MetaCompositor *compositor)
17831898 * meta_get_x11_background_actor_for_display:
17841899 * @display: a #MetaDisplay
17851900 *
1786- * Gets the actor that draws the root window background under the windows.
1787- * The root window background automatically tracks the image or color set
1788- * by the environment.
1901+ * Deprecated. Returns the first per-monitor X11 background actor, or NULL.
1902+ * Use meta_get_background_actors_for_display() instead.
17891903 *
1790- * Returns: (transfer none): The background actor corresponding to @display
1904+ * Returns: (transfer none) (nullable): A background actor, or NULL
17911905 */
17921906ClutterActor *
17931907meta_get_x11_background_actor_for_display (MetaDisplay * display )
17941908{
17951909 MetaCompositorPrivate * priv =
17961910 meta_compositor_get_instance_private (display -> compositor );
17971911
1798- if (meta_is_wayland_compositor ())
1799- {
1800- return NULL ;
1801- }
1912+ if (meta_is_wayland_compositor () || priv -> background_actors == NULL )
1913+ return NULL ;
18021914
1803- return priv -> background_actor ;
1915+ return priv -> background_actors -> data ;
18041916}
18051917
18061918/**
@@ -1853,3 +1965,50 @@ meta_update_desklet_stacking (MetaCompositor *compositor)
18531965
18541966 meta_stack_tracker_queue_sync_stack (priv -> display -> stack_tracker );
18551967}
1968+
1969+ /**
1970+ * meta_create_background_for_monitor:
1971+ * @display: a #MetaDisplay
1972+ * @monitor: the monitor index
1973+ *
1974+ * Creates a new standalone actor that displays the desktop background for the
1975+ * given monitor. On X11, this returns a per-monitor root pixmap actor. On
1976+ * Wayland, this returns a monitor-sized clone of the layer-shell background
1977+ * surface.
1978+ *
1979+ * These are independent copies, not the live compositor background actors.
1980+ * Use meta_get_background_actors_for_display() to get the actual actors
1981+ * in the scene graph.
1982+ *
1983+ * Returns: (transfer full): The background actor for @monitor
1984+ */
1985+ ClutterActor *
1986+ meta_create_background_for_monitor (MetaDisplay * display ,
1987+ int monitor )
1988+ {
1989+ #ifdef HAVE_WAYLAND
1990+ if (meta_is_wayland_compositor ())
1991+ return meta_wayland_background_actor_new_for_monitor (display , monitor );
1992+ #endif
1993+
1994+ return g_object_ref_sink (meta_x11_background_actor_new_for_monitor (display , monitor ));
1995+ }
1996+
1997+ /**
1998+ * meta_get_background_actors_for_display:
1999+ * @display: a #MetaDisplay
2000+ *
2001+ * Returns a list of the live per-monitor background actors in the compositor's
2002+ * scene graph. These actors can have effects applied to them directly.
2003+ *
2004+ * Returns: (transfer none) (element-type Clutter.Actor): The list of
2005+ * background actors
2006+ */
2007+ GList *
2008+ meta_get_background_actors_for_display (MetaDisplay * display )
2009+ {
2010+ MetaCompositorPrivate * priv =
2011+ meta_compositor_get_instance_private (display -> compositor );
2012+
2013+ return priv -> background_actors ;
2014+ }
0 commit comments