Skip to content

Commit 266f4ad

Browse files
committed
csd-background: Use gtk-layer-shell if available to run under
wayland. Current csd-background runs as an xwayland client and has special handling built in to muffin to 'make it work'. This will allow it to run as a native client, if muffin has the capability, and if csd-background has been built with support. ref: linuxmint/muffin#784 linuxmint/nemo#3684
1 parent 3298eae commit 266f4ad

13 files changed

Lines changed: 218 additions & 64 deletions

debian/control

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Build-Depends:
1414
libfontconfig1-dev,
1515
libglib2.0-dev (>= 2.37.3),
1616
libgtk-3-dev (>= 3.9.10),
17+
libgtk-layer-shell-dev,
1718
libgudev-1.0-dev [linux-any],
1819
liblcms2-dev,
1920
libnotify-dev (>= 0.7.0),
@@ -24,6 +25,7 @@ Build-Depends:
2425
libsystemd-dev [linux-any],
2526
libupower-glib-dev (>= 0.99.11),
2627
libwacom-dev (>= 0.4) [!s390x !hurd-any !kfreebsd-any],
28+
libwayland-dev,
2729
libx11-dev,
2830
libxext-dev,
2931
libxi-dev,

debian/rules

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
1515
override_dh_auto_configure:
1616
dh_auto_configure -- \
1717
--libexecdir=/usr/libexec \
18+
-D gtk_layer_shell=true \
1819
$(CONFFLAGS)
1920

2021

meson.build

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ if not get_option('use_logind').disabled()
8989
endif
9090
endif
9191

92+
gtk_layer_shell_enabled = get_option('gtk_layer_shell')
93+
gtk_layer_shell = dependency('', required: false)
94+
wayland_client = dependency('', required: false)
95+
if gtk_layer_shell_enabled
96+
gtk_layer_shell = dependency('gtk-layer-shell-0', version: '>= 0.8', required: true)
97+
wayland_client = dependency('wayland-client', required: true)
98+
endif
99+
92100
cc = meson.get_compiler('c')
93101
math = cc.find_library('m', required: false)
94102

@@ -105,6 +113,9 @@ csd_conf.set_quoted('LIBEXECDIR', join_paths(prefix, libexecdir))
105113
csd_conf.set_quoted('SYSCONFDIR', sysconfdir)
106114
csd_conf.set_quoted('LIBDIR', libdir)
107115
csd_conf.set10('HAVE_TIMERFD', has_timerfd_create)
116+
if gtk_layer_shell_enabled
117+
csd_conf.set('HAVE_GTK_LAYER_SHELL', 1)
118+
endif
108119

109120
if gudev.found()
110121
cargs += '-DHAVE_GUDEV'

meson_options.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,9 @@ option(
7070
value: '/usr/share/zoneinfo/zone.tab',
7171
description: 'Path to tzdata zone.tab or zone1970.tab'
7272
)
73+
option(
74+
'gtk_layer_shell',
75+
type: 'boolean',
76+
value: false,
77+
description: 'Use gtk-layer-shell for native Wayland background windows'
78+
)

plugins/background/csd-background-manager.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,14 @@ struct CsdBackgroundManagerPrivate
5959
guint proxy_signal_id;
6060

6161
GPtrArray *mbs;
62+
63+
guint screen_changed_id;
6264
};
6365

6466
static void csd_background_manager_finalize (GObject *object);
6567

6668
static void setup_bg (CsdBackgroundManager *manager);
69+
static void setup_monitors (CsdBackgroundManager *manager);
6770
static void connect_screen_signals (CsdBackgroundManager *manager);
6871

6972
G_DEFINE_TYPE (CsdBackgroundManager, csd_background_manager, G_TYPE_OBJECT)
@@ -177,12 +180,31 @@ settings_change_event_cb (GSettings *settings,
177180
return FALSE;
178181
}
179182

183+
static gboolean
184+
on_screen_changed_idle (gpointer user_data)
185+
{
186+
CsdBackgroundManager *manager = CSD_BACKGROUND_MANAGER (user_data);
187+
188+
manager->priv->screen_changed_id = 0;
189+
190+
if (session_is_wayland ()) {
191+
setup_monitors (manager);
192+
}
193+
194+
draw_background (manager);
195+
196+
return G_SOURCE_REMOVE;
197+
}
198+
180199
static void
181200
on_screen_size_changed (GdkScreen *screen,
182201
CsdBackgroundManager *manager)
183202
{
203+
if (manager->priv->screen_changed_id != 0)
204+
return;
184205

185-
draw_background (manager);
206+
manager->priv->screen_changed_id =
207+
g_timeout_add (250, on_screen_changed_idle, manager);
186208
}
187209

188210
static void
@@ -396,6 +418,8 @@ csd_background_manager_stop (CsdBackgroundManager *manager)
396418

397419
g_debug ("Stopping background manager");
398420

421+
g_clear_handle_id (&manager->priv->screen_changed_id, g_source_remove);
422+
399423
disconnect_screen_signals (manager);
400424

401425
if (manager->priv->proxy) {

plugins/background/main.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
#include "config.h"
2+
3+
#include <glib.h>
4+
#include <gdk/gdk.h>
5+
16
#define NEW csd_background_manager_new
27
#define START csd_background_manager_start
38
#define STOP csd_background_manager_stop
@@ -12,8 +17,34 @@
1217
// Setting this to TRUE makes the plugin force GDK_SCALE=1
1318
#define FORCE_GDK_SCALE TRUE
1419

15-
// This plugin must run under x11/xwayland
20+
// When gtk-layer-shell is available, check at runtime if the compositor
21+
// supports wlr-layer-shell. If not, fall back to X11/XWayland.
22+
#ifdef HAVE_GTK_LAYER_SHELL
23+
#include "wayland-utils.h"
24+
25+
static void
26+
pre_gtk_init (void)
27+
{
28+
if (csd_check_layer_shell_support ()) {
29+
g_message ("csd-background: using Wayland backend, gtk-layer-shell supported");
30+
} else {
31+
g_message ("csd-background: not a Wayland session or wlr-layer-shell protocol not supported, using X11 backend");
32+
gdk_set_allowed_backends ("x11");
33+
}
34+
}
35+
36+
#define PRE_GTK_INIT pre_gtk_init
37+
#define FORCE_X11_BACKEND FALSE
38+
#else
39+
static void
40+
pre_gtk_init (void)
41+
{
42+
g_message ("csd-background: gtk-layer-shell not built, using X11 backend");
43+
}
44+
45+
#define PRE_GTK_INIT pre_gtk_init
1646
#define FORCE_X11_BACKEND TRUE
47+
#endif
1748

1849
#include "csd-background-manager.h"
1950

plugins/background/meson.build

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ background_deps = [
1313
libnotify,
1414
]
1515

16+
if gtk_layer_shell_enabled
17+
background_deps += gtk_layer_shell
18+
endif
19+
1620
executable(
1721
'csd-background',
1822
background_sources,

plugins/background/monitor-background.c

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,14 @@
1111
#include <glib/gstdio.h>
1212
#include <gtk/gtk.h>
1313

14+
#ifdef HAVE_GTK_LAYER_SHELL
15+
#include <gtk-layer-shell/gtk-layer-shell.h>
16+
#endif
17+
1418
#include "monitor-background.h"
1519

1620
G_DEFINE_TYPE (MonitorBackground, monitor_background, G_TYPE_OBJECT)
1721

18-
enum {
19-
INVALIDATED,
20-
N_SIGNALS
21-
};
22-
23-
static guint signals[N_SIGNALS] = { 0 };
24-
25-
static void
26-
invalidate_mb (MonitorBackground *mb)
27-
{
28-
mb->valid = FALSE;
29-
30-
g_signal_emit (mb, signals[INVALIDATED], 0);
31-
}
32-
33-
static void
34-
on_gdk_monitor_dispose (gpointer data,
35-
GObject *monitor)
36-
{
37-
MonitorBackground *mb = MONITOR_BACKGROUND (data);
38-
invalidate_mb (mb);
39-
}
40-
41-
static void
42-
on_gdk_monitor_invalidate (gpointer data)
43-
{
44-
MonitorBackground *mb = MONITOR_BACKGROUND (data);
45-
invalidate_mb (mb);
46-
}
47-
4822
static void
4923
on_window_realized (GtkWidget *widget,
5024
gpointer user_data)
@@ -60,14 +34,33 @@ static void
6034
build_monitor_background (MonitorBackground *mb)
6135
{
6236
GdkRectangle geometry;
37+
#ifdef HAVE_GTK_LAYER_SHELL
38+
gboolean use_layer_shell = gtk_layer_is_supported ();
39+
#else
40+
gboolean use_layer_shell = FALSE;
41+
#endif
6342

6443
mb->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
65-
gtk_window_set_type_hint (GTK_WINDOW (mb->window), GDK_WINDOW_TYPE_HINT_DESKTOP);
6644
gtk_window_set_decorated (GTK_WINDOW (mb->window), FALSE);
6745

68-
// Set keep below so muffin recognizes the backgrounds and keeps them
69-
// at the bottom of the bottom window layer (under file managers, etc..)
70-
gtk_window_set_keep_below (GTK_WINDOW (mb->window), TRUE);
46+
#ifdef HAVE_GTK_LAYER_SHELL
47+
if (use_layer_shell) {
48+
gtk_layer_init_for_window (GTK_WINDOW (mb->window));
49+
gtk_layer_set_layer (GTK_WINDOW (mb->window), GTK_LAYER_SHELL_LAYER_BACKGROUND);
50+
gtk_layer_set_namespace (GTK_WINDOW (mb->window), "csd-background");
51+
gtk_layer_set_keyboard_mode (GTK_WINDOW (mb->window), GTK_LAYER_SHELL_KEYBOARD_MODE_NONE);
52+
gtk_layer_set_exclusive_zone (GTK_WINDOW (mb->window), -1);
53+
gtk_layer_set_anchor (GTK_WINDOW (mb->window), GTK_LAYER_SHELL_EDGE_TOP, TRUE);
54+
gtk_layer_set_anchor (GTK_WINDOW (mb->window), GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE);
55+
gtk_layer_set_anchor (GTK_WINDOW (mb->window), GTK_LAYER_SHELL_EDGE_LEFT, TRUE);
56+
gtk_layer_set_anchor (GTK_WINDOW (mb->window), GTK_LAYER_SHELL_EDGE_RIGHT, TRUE);
57+
gtk_layer_set_monitor (GTK_WINDOW (mb->window), mb->monitor);
58+
} else
59+
#endif
60+
{
61+
gtk_window_set_type_hint (GTK_WINDOW (mb->window), GDK_WINDOW_TYPE_HINT_DESKTOP);
62+
gtk_window_set_keep_below (GTK_WINDOW (mb->window), TRUE);
63+
}
7164

7265
mb->stack = gtk_stack_new ();
7366
g_object_set (mb->stack,
@@ -81,22 +74,25 @@ build_monitor_background (MonitorBackground *mb)
8174
mb->width = geometry.width;
8275
mb->height = geometry.height;
8376

84-
gtk_window_set_default_size (GTK_WINDOW (mb->window), geometry.width, geometry.height);
77+
if (!use_layer_shell) {
78+
gtk_window_set_default_size (GTK_WINDOW (mb->window), geometry.width, geometry.height);
79+
g_signal_connect (mb->window, "realize", G_CALLBACK (on_window_realized), mb);
80+
}
8581

86-
g_signal_connect (mb->window, "realize", G_CALLBACK (on_window_realized), mb);
8782
gtk_widget_show_all (mb->window);
8883
}
8984

9085
static void
9186
monitor_background_init (MonitorBackground *mb)
9287
{
93-
mb->valid = TRUE;
9488
}
9589

9690
static void
9791
monitor_background_dispose (GObject *object)
9892
{
99-
g_debug ("MonitorBackground dispose (%p)", object);
93+
MonitorBackground *mb = MONITOR_BACKGROUND (object);
94+
95+
g_clear_pointer (&mb->window, gtk_widget_destroy);
10096

10197
G_OBJECT_CLASS (monitor_background_parent_class)->dispose (object);
10298
}
@@ -117,13 +113,6 @@ monitor_background_class_init (MonitorBackgroundClass *klass)
117113

118114
gobject_class->dispose = monitor_background_dispose;
119115
gobject_class->finalize = monitor_background_finalize;
120-
121-
signals[INVALIDATED] = g_signal_new ("invalidated",
122-
G_OBJECT_CLASS_TYPE (gobject_class),
123-
G_SIGNAL_RUN_LAST,
124-
0,
125-
NULL, NULL, NULL,
126-
G_TYPE_NONE, 0);
127116
}
128117

129118
MonitorBackground *
@@ -133,9 +122,6 @@ monitor_background_new (gint index, GdkMonitor *monitor)
133122
mb->monitor_index = index;
134123
mb->monitor = monitor;
135124

136-
g_object_weak_ref (G_OBJECT (monitor), (GWeakNotify) on_gdk_monitor_dispose, mb);
137-
g_signal_connect_swapped (monitor, "invalidate", G_CALLBACK (on_gdk_monitor_invalidate), mb);
138-
139125
build_monitor_background (mb);
140126

141127
return mb;
@@ -144,12 +130,6 @@ monitor_background_new (gint index, GdkMonitor *monitor)
144130
GtkImage *
145131
monitor_background_get_pending_image (MonitorBackground *mb)
146132
{
147-
if (!mb->valid)
148-
{
149-
g_warning ("Asked for pending image when monitor is no longer valid");
150-
return NULL;
151-
}
152-
153133
if (!mb->pending)
154134
{
155135
mb->pending = gtk_image_new ();
@@ -165,12 +145,6 @@ monitor_background_show_next_image (MonitorBackground *mb)
165145
{
166146
g_return_if_fail (mb->pending != NULL);
167147

168-
if (!mb->valid)
169-
{
170-
g_warning ("Asked for pending image when monitor is no longer valid");
171-
return;
172-
}
173-
174148
GtkWidget *tmp;
175149

176150
tmp = mb->current;

plugins/background/monitor-background.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ struct _MonitorBackground
2020
GtkWidget *current;
2121
GtkWidget *pending;
2222

23-
gboolean valid;
24-
2523
gint monitor_index;
2624
gint width;
2725
gint height;

plugins/common/daemon-skeleton-gtk.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
#define INIT_LIBNOTIFY FALSE
3232
#endif
3333

34+
#ifndef PRE_GTK_INIT
35+
#define PRE_GTK_INIT()
36+
#endif
37+
3438
#define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager"
3539
#define GNOME_SESSION_DBUS_PATH "/org/gnome/SessionManager"
3640
#define GNOME_SESSION_CLIENT_PRIVATE_NAME "org.gnome.SessionManager.ClientPrivate"
@@ -210,6 +214,8 @@ main (int argc, char **argv)
210214
g_type_ensure (G_TYPE_DBUS_CONNECTION);
211215
g_type_ensure (G_TYPE_DBUS_PROXY);
212216

217+
PRE_GTK_INIT();
218+
213219
if (FORCE_X11_BACKEND) {
214220
const gchar *setup_display = getenv ("GNOME_SETUP_DISPLAY");
215221
if (setup_display && *setup_display != '\0')

0 commit comments

Comments
 (0)