summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2026-05-27 09:01:55 -0400
committerVictor Kareh <[email protected]>2026-05-27 17:19:24 -0400
commit42ceb8b7b8f09d6180ac5e506943cd070cf3bfc3 (patch)
treea7a9c3bd7b16b9fc03c3fba5ec3837bcaaaf2b5b /plugins
parent266af6a7fbe059649ce8d14af88f43cdeebba0cb (diff)
downloadmate-settings-daemon-42ceb8b7b8f09d6180ac5e506943cd070cf3bfc3.tar.bz2
mate-settings-daemon-42ceb8b7b8f09d6180ac5e506943cd070cf3bfc3.tar.xz
background: simplify desktop detection to use EWMH standard
This replaces caja desktop detection with a generic check for _NET_WM_WINDOW_TYPE_DESKTOP windows and makes the background plugin work with any EWMH-compliant file manager. It now treats the background plugin as a fallback: If there's no file manager drawing the background, then m-s-d will draw it. This also allows us to remove a bunch of unnecessary code: - D-Bus session manager listener - startup delays - screen size tracking - crossfade support (this is broken on msd anyway) - checking show-desktop-icons gsettings (this is only used by caja) - checking draw-background gsettings (this should be deprecated) Fixes #335 Fixes mate-desktop/mate-session-manager#159
Diffstat (limited to 'plugins')
-rw-r--r--plugins/background/msd-background-manager.c401
1 files changed, 79 insertions, 322 deletions
diff --git a/plugins/background/msd-background-manager.c b/plugins/background/msd-background-manager.c
index 78a38bf..5264bfa 100644
--- a/plugins/background/msd-background-manager.c
+++ b/plugins/background/msd-background-manager.c
@@ -47,107 +47,88 @@
#include "mate-settings-profile.h"
#include "msd-background-manager.h"
-#define MATE_SESSION_MANAGER_DBUS_NAME "org.gnome.SessionManager"
-#define MATE_SESSION_MANAGER_DBUS_PATH "/org/gnome/SessionManager"
-
struct _MsdBackgroundManager {
GObject parent;
GSettings *settings;
MateBG *bg;
cairo_surface_t *surface;
- MateBGCrossfade *fade;
- GList *scr_sizes;
- gboolean msd_can_draw;
- gboolean caja_can_draw;
- gboolean do_fade;
gboolean draw_in_progress;
-
- guint timeout_id;
-
- GDBusProxy *proxy;
- gulong proxy_signal_id;
};
G_DEFINE_TYPE (MsdBackgroundManager, msd_background_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
-/* Whether MSD is allowed to draw background */
-static gboolean
-msd_can_draw_bg (MsdBackgroundManager *manager)
-{
- return g_settings_get_boolean (manager->settings, MATE_BG_KEY_DRAW_BACKGROUND);
-}
-
-/* Whether to change background with a fade effect */
-static gboolean
-can_fade_bg (MsdBackgroundManager *manager)
-{
- return g_settings_get_boolean (manager->settings, MATE_BG_KEY_BACKGROUND_FADE);
-}
-
-/* Whether Caja is configured to draw desktop (show-desktop-icons) */
+/* Check if any window with _NET_WM_WINDOW_TYPE_DESKTOP exists */
static gboolean
-caja_can_draw_bg (MsdBackgroundManager *manager)
-{
- return g_settings_get_boolean (manager->settings, MATE_BG_KEY_SHOW_DESKTOP);
-}
-
-static gboolean
-caja_is_drawing_bg (MsdBackgroundManager *manager)
+desktop_window_exists (void)
{
Display *display = gdk_x11_get_default_xdisplay ();
Window window = gdk_x11_get_default_root_xwindow ();
- Atom caja_prop, wmclass_prop, type;
- Window caja_window;
+ Atom client_list, desktop_type, window_type, type;
int format;
unsigned long nitems, after;
unsigned char *data;
GdkDisplay *gdk_display;
gboolean running = FALSE;
- if (!manager->caja_can_draw)
+ /* This atom will be present if a window owns the desktop (e.g. caja) */
+ desktop_type = XInternAtom (display, "_NET_WM_WINDOW_TYPE_DESKTOP", True);
+ if (desktop_type == None)
return FALSE;
- caja_prop = XInternAtom (display, "CAJA_DESKTOP_WINDOW_ID", True);
- if (caja_prop == None)
+ /* This atom will contain the list of all windows managed by the window manager */
+ client_list = XInternAtom (display, "_NET_CLIENT_LIST", True);
+ if (client_list == None)
return FALSE;
- XGetWindowProperty (display, window, caja_prop, 0, 1, False,
+ XGetWindowProperty (display, window, client_list, 0, 1024, False,
XA_WINDOW, &type, &format, &nitems, &after, &data);
if (data == NULL)
return FALSE;
- caja_window = *(Window *) data;
- XFree (data);
-
- if (type != XA_WINDOW || format != 32)
+ if (type != XA_WINDOW || format != 32) {
+ XFree (data);
return FALSE;
+ }
- wmclass_prop = XInternAtom (display, "WM_CLASS", True);
- if (wmclass_prop == None)
+ window_type = XInternAtom (display, "_NET_WM_WINDOW_TYPE", True);
+ if (window_type == None) {
+ XFree (data);
return FALSE;
+ }
gdk_display = gdk_display_get_default ();
- gdk_x11_display_error_trap_push (gdk_display);
-
- XGetWindowProperty (display, caja_window, wmclass_prop, 0, 20, False,
- XA_STRING, &type, &format, &nitems, &after, &data);
-
- XSync (display, False);
-
- if (gdk_x11_display_error_trap_pop (gdk_display) == BadWindow || data == NULL)
- return FALSE;
-
- /* See: caja_desktop_window_new(), in src/caja-desktop-window.c */
- if (nitems == 20 && after == 0 && format == 8 &&
- !strcmp((char*) data, "desktop_window") &&
- !strcmp((char*) data + strlen((char*) data) + 1, "Caja"))
- {
- running = TRUE;
+ Window *windows = (Window *) data;
+
+ /* Read all the windows and determine if any of them own the desktop */
+ for (unsigned long i = 0; i < nitems && !running; i++) {
+ Atom wm_type;
+ int wm_format;
+ unsigned long wm_nitems, wm_after;
+ unsigned char *wm_data;
+
+ gdk_x11_display_error_trap_push (gdk_display);
+
+ XGetWindowProperty (display, windows[i], window_type, 0, 32, False,
+ XA_ATOM, &wm_type, &wm_format, &wm_nitems, &wm_after, &wm_data);
+
+ if (wm_data != NULL) {
+ Atom *types = (Atom *) wm_data;
+ for (unsigned long j = 0; j < wm_nitems; j++) {
+ /* Found a window managing the desktop. Bail out. */
+ if (types[j] == desktop_type) {
+ running = TRUE;
+ break;
+ }
+ }
+ XFree (wm_data);
+ }
+
+ gdk_x11_display_error_trap_pop_ignored (gdk_display);
}
XFree (data);
@@ -155,15 +136,6 @@ caja_is_drawing_bg (MsdBackgroundManager *manager)
}
static void
-free_fade (MsdBackgroundManager *manager)
-{
- if (manager->fade != NULL) {
- g_object_unref (manager->fade);
- manager->fade = NULL;
- }
-}
-
-static void
free_bg_surface (MsdBackgroundManager *manager)
{
if (manager->surface != NULL) {
@@ -173,100 +145,53 @@ free_bg_surface (MsdBackgroundManager *manager)
}
static void
-free_scr_sizes (MsdBackgroundManager *manager)
+draw_background (MsdBackgroundManager *manager)
{
- if (manager->scr_sizes != NULL) {
- g_list_free_full (manager->scr_sizes, g_free);
- manager->scr_sizes = NULL;
- }
-}
+ if (manager->draw_in_progress || desktop_window_exists ())
+ return;
-static void
-real_draw_bg (MsdBackgroundManager *manager,
- GdkScreen *screen)
-{
+ GdkDisplay *display = gdk_display_get_default ();
+ GdkScreen *screen = gdk_display_get_default_screen (display);
GdkWindow *window = gdk_screen_get_root_window (screen);
gint scale = gdk_window_get_scale_factor (window);
gint width = WidthOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale;
gint height = HeightOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale;
+ manager->draw_in_progress = TRUE;
+
free_bg_surface (manager);
manager->surface = mate_bg_create_surface_scale (manager->bg, window, width, height, scale, TRUE);
+ mate_bg_set_surface_as_root (screen, manager->surface);
- if (manager->do_fade)
- {
- free_fade (manager);
- manager->fade = mate_bg_set_surface_as_root_with_crossfade (screen, manager->surface);
- g_signal_connect_swapped (manager->fade, "finished", G_CALLBACK (free_fade), manager);
- }
- else
- {
- mate_bg_set_surface_as_root (screen, manager->surface);
- }
- manager->scr_sizes = g_list_prepend (manager->scr_sizes, g_strdup_printf ("%dx%d", width, height));
+ manager->draw_in_progress = FALSE;
}
-static void
-draw_background (MsdBackgroundManager *manager,
- gboolean may_fade)
+static gboolean
+queue_draw_background (MsdBackgroundManager *manager)
{
- if (!manager->msd_can_draw || manager->draw_in_progress || caja_is_drawing_bg (manager))
- return;
-
- mate_settings_profile_start (NULL);
-
- GdkDisplay *display = gdk_display_get_default ();
-
- manager->draw_in_progress = TRUE;
- manager->do_fade = may_fade && can_fade_bg (manager);
- free_scr_sizes (manager);
-
- g_debug ("Drawing background on Screen");
- real_draw_bg (manager, gdk_display_get_default_screen (display));
-
- manager->scr_sizes = g_list_reverse (manager->scr_sizes);
-
- manager->draw_in_progress = FALSE;
- mate_settings_profile_end (NULL);
+ draw_background (manager);
+ return FALSE;
}
static void
on_bg_changed (MateBG *bg G_GNUC_UNUSED,
MsdBackgroundManager *manager)
{
- g_debug ("Background changed");
- draw_background (manager, TRUE);
+ g_idle_add ((GSourceFunc) queue_draw_background, manager);
}
static void
on_bg_transitioned (MateBG *bg G_GNUC_UNUSED,
MsdBackgroundManager *manager)
{
- g_debug ("Background transitioned");
- draw_background (manager, FALSE);
+ g_idle_add ((GSourceFunc) queue_draw_background, manager);
}
static void
-on_screen_size_changed (GdkScreen *screen,
+on_screen_size_changed (GdkScreen *screen G_GNUC_UNUSED,
MsdBackgroundManager *manager)
{
- if (!manager->msd_can_draw || manager->draw_in_progress || caja_is_drawing_bg (manager))
- return;
-
- GdkWindow *window = gdk_screen_get_root_window (screen);
- gint scale = gdk_window_get_scale_factor (window);
- gint scr_num = gdk_x11_screen_get_screen_number (screen);
- gchar *old_size = g_list_nth_data (manager->scr_sizes, (guint) scr_num);
- gchar *new_size = g_strdup_printf ("%dx%d", WidthOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale,
- HeightOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale);
- if (g_strcmp0 (old_size, new_size) != 0)
- {
- g_debug ("Screen%d size changed: %s -> %s", scr_num, old_size, new_size);
- draw_background (manager, FALSE);
- } else {
- g_debug ("Screen%d size unchanged (%s). Ignoring.", scr_num, old_size);
- }
- g_free (new_size);
+ g_idle_add ((GSourceFunc) queue_draw_background, manager);
}
static void
@@ -295,13 +220,8 @@ connect_screen_signals (MsdBackgroundManager *manager)
static gboolean
settings_change_event_idle_cb (MsdBackgroundManager *manager)
{
- mate_settings_profile_start ("settings_change_event_idle_cb");
-
mate_bg_load_from_preferences (manager->bg);
-
- mate_settings_profile_end ("settings_change_event_idle_cb");
-
- return FALSE; /* remove from the list of event sources */
+ return FALSE;
}
static gboolean
@@ -310,27 +230,20 @@ settings_change_event_cb (GSettings *settings G_GNUC_UNUSED,
gint n_keys G_GNUC_UNUSED,
MsdBackgroundManager *manager)
{
- /* Complements on_bg_handling_changed() */
- manager->msd_can_draw = msd_can_draw_bg (manager);
- manager->caja_can_draw = caja_can_draw_bg (manager);
-
- if (manager->msd_can_draw && manager->bg != NULL && !caja_is_drawing_bg (manager))
- {
- /* Defer signal processing to avoid making the dconf backend deadlock */
- g_idle_add ((GSourceFunc) settings_change_event_idle_cb, manager);
- }
-
- return FALSE; /* let the event propagate further */
+ g_idle_add ((GSourceFunc) settings_change_event_idle_cb, manager);
+ return FALSE;
}
-static void
-setup_background (MsdBackgroundManager *manager)
+gboolean
+msd_background_manager_start (MsdBackgroundManager *manager,
+ GError **error)
{
- g_return_if_fail (manager->bg == NULL);
+ g_debug ("Starting background manager");
+ mate_settings_profile_start (NULL);
- manager->bg = mate_bg_new();
+ manager->settings = g_settings_new (MATE_BG_SCHEMA);
- manager->draw_in_progress = FALSE;
+ manager->bg = mate_bg_new();
g_signal_connect(manager->bg, "changed", G_CALLBACK (on_bg_changed), manager);
@@ -342,16 +255,20 @@ setup_background (MsdBackgroundManager *manager)
g_signal_connect (manager->settings, "change-event",
G_CALLBACK (settings_change_event_cb), manager);
+
+ mate_settings_profile_end (NULL);
+ return TRUE;
}
-static void
-remove_background (MsdBackgroundManager *manager)
+void
+msd_background_manager_stop (MsdBackgroundManager *manager)
{
- disconnect_screen_signals (manager);
+ g_debug ("Stopping background manager");
- g_signal_handlers_disconnect_by_func (manager->settings, settings_change_event_cb, manager);
+ disconnect_screen_signals (manager);
if (manager->settings != NULL) {
+ g_signal_handlers_disconnect_by_func (manager->settings, settings_change_event_cb, manager);
g_object_unref (manager->settings);
manager->settings = NULL;
}
@@ -361,167 +278,7 @@ remove_background (MsdBackgroundManager *manager)
manager->bg = NULL;
}
- free_scr_sizes (manager);
free_bg_surface (manager);
- free_fade (manager);
-}
-
-static void
-on_bg_handling_changed (GSettings *settings G_GNUC_UNUSED,
- const char *key G_GNUC_UNUSED,
- MsdBackgroundManager *manager)
-{
- mate_settings_profile_start (NULL);
-
- if (caja_is_drawing_bg (manager))
- {
- if (manager->bg != NULL)
- remove_background (manager);
- }
- else if (manager->msd_can_draw && manager->bg == NULL)
- {
- setup_background (manager);
- }
-
- mate_settings_profile_end (NULL);
-}
-
-static gboolean
-queue_setup_background (MsdBackgroundManager *manager)
-{
- manager->timeout_id = 0;
-
- setup_background (manager);
-
- return FALSE;
-}
-
-static void
-queue_timeout (MsdBackgroundManager *manager)
-{
- if (manager->timeout_id > 0)
- return;
-
- /* SessionRunning: now check if Caja is drawing background, and if not, set it.
- *
- * FIXME: We wait a few seconds after the session is up because Caja tells the
- * session manager that its ready before it sets the background.
- * https://bugzilla.gnome.org/show_bug.cgi?id=568588
- */
- manager->timeout_id =
- g_timeout_add_seconds (8, (GSourceFunc) queue_setup_background, manager);
-}
-
-static void
-disconnect_session_manager_listener (MsdBackgroundManager* manager)
-{
-#if GLIB_CHECK_VERSION(2,62,0)
- if (manager->proxy) {
- g_clear_signal_handler (&manager->proxy_signal_id, manager->proxy);
- }
-#else
- if (manager->proxy && manager->proxy_signal_id) {
- g_signal_handler_disconnect (manager->proxy, manager->proxy_signal_id);
- manager->proxy_signal_id = 0;
- }
-#endif
-}
-
-static void
-on_session_manager_signal (GDBusProxy *proxy G_GNUC_UNUSED,
- const gchar *sender_name G_GNUC_UNUSED,
- const gchar *signal_name,
- GVariant *parameters G_GNUC_UNUSED,
- gpointer user_data)
-{
- MsdBackgroundManager *manager = MSD_BACKGROUND_MANAGER (user_data);
-
- if (g_strcmp0 (signal_name, "SessionRunning") == 0) {
- queue_timeout (manager);
- disconnect_session_manager_listener (manager);
- }
-}
-
-static void
-draw_bg_after_session_loads (MsdBackgroundManager *manager)
-{
- GError *error = NULL;
- GDBusProxyFlags flags;
-
- flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
- G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
- manager->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
- flags,
- NULL, /* GDBusInterfaceInfo */
- MATE_SESSION_MANAGER_DBUS_NAME,
- MATE_SESSION_MANAGER_DBUS_PATH,
- MATE_SESSION_MANAGER_DBUS_NAME,
- NULL, /* GCancellable */
- &error);
- if (manager->proxy == NULL) {
- g_warning ("Could not listen to session manager: %s",
- error->message);
- g_error_free (error);
- return;
- }
-
- manager->proxy_signal_id = g_signal_connect (manager->proxy,
- "g-signal",
- G_CALLBACK (on_session_manager_signal),
- manager);
-}
-
-gboolean
-msd_background_manager_start (MsdBackgroundManager *manager,
- GError **error)
-{
- g_debug ("Starting background manager");
- mate_settings_profile_start (NULL);
-
- manager->settings = g_settings_new (MATE_BG_SCHEMA);
-
- manager->msd_can_draw = msd_can_draw_bg (manager);
- manager->caja_can_draw = caja_can_draw_bg (manager);
-
- g_signal_connect (manager->settings, "changed::" MATE_BG_KEY_DRAW_BACKGROUND,
- G_CALLBACK (on_bg_handling_changed), manager);
- g_signal_connect (manager->settings, "changed::" MATE_BG_KEY_SHOW_DESKTOP,
- G_CALLBACK (on_bg_handling_changed), manager);
-
- /* If Caja is set to draw the background, it is very likely in our session.
- * But it might not be started yet, so caja_is_drawing_bg() would fail.
- * In this case, we wait till the session is loaded, to avoid double-draws.
- */
- if (manager->msd_can_draw)
- {
- if (manager->caja_can_draw)
- draw_bg_after_session_loads (manager);
- else
- setup_background (manager);
- }
-
- mate_settings_profile_end (NULL);
-
- return TRUE;
-}
-
-void
-msd_background_manager_stop (MsdBackgroundManager *manager)
-{
- g_debug ("Stopping background manager");
-
- if (manager->proxy)
- {
- disconnect_session_manager_listener (manager);
- g_object_unref (manager->proxy);
- }
-
- if (manager->timeout_id != 0) {
- g_source_remove (manager->timeout_id);
- manager->timeout_id = 0;
- }
-
- remove_background (manager);
}
static GObject*