diff options
| author | Victor Kareh <[email protected]> | 2026-05-27 09:01:55 -0400 |
|---|---|---|
| committer | Victor Kareh <[email protected]> | 2026-05-27 17:19:24 -0400 |
| commit | 42ceb8b7b8f09d6180ac5e506943cd070cf3bfc3 (patch) | |
| tree | a7a9c3bd7b16b9fc03c3fba5ec3837bcaaaf2b5b /plugins | |
| parent | 266af6a7fbe059649ce8d14af88f43cdeebba0cb (diff) | |
| download | mate-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.c | 401 |
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* |
