[Xfce4-commits] <xfdesktop:eric/wallpaper-and-settings-improvements> Correctly handle workspaces being removed

Eric Koegel noreply at xfce.org
Mon Mar 25 17:30:01 CET 2013


Updating branch refs/heads/eric/wallpaper-and-settings-improvements
         to 9f81066800a9de6a2a20f5436e69fad2492564e2 (commit)
       from 963d829f123b7cd4da36c25fa03cf5754897e195 (commit)

commit 9f81066800a9de6a2a20f5436e69fad2492564e2
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Mar 25 19:20:41 2013 +0300

    Correctly handle workspaces being removed
    
    When workspaces are removed the xfconf bindings need to be removed
    and it also handles the single workspace number set to an invalid
    workspace.

 src/xfce-desktop.c   |   67 +++++++++++------
 src/xfce-workspace.c |  199 ++++++++++++++++++++++++++++++++++----------------
 2 files changed, 177 insertions(+), 89 deletions(-)

diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c
index 2623547..bf00f2d 100644
--- a/src/xfce-desktop.c
+++ b/src/xfce-desktop.c
@@ -481,6 +481,9 @@ screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
     if(desktop->priv->nworkspaces <= current_workspace)
         return;
 
+    if(current_workspace < 0)
+        return;
+
     /* special case for 1 backdrop to handle xinerama stretching */
     if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
        backdrop_changed_cb(xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], 0), desktop);
@@ -549,33 +552,36 @@ workspace_changed_cb(WnckScreen *wnck_screen,
     TRACE("entering");
 
     current_workspace = desktop->priv->current_workspace;
-    desktop->priv->current_workspace = xfce_desktop_get_current_workspace(desktop);
-    new_workspace = desktop->priv->current_workspace;
+    new_workspace = xfce_desktop_get_current_workspace(desktop);
 
-    DBG("current_workspace %d, new_workspace %d",
-        current_workspace, new_workspace);
+    if(new_workspace < 0 || new_workspace >= desktop->priv->nworkspaces)
+        return;
 
-    /* special case for the spanning screen option */
-    if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[new_workspace])) {
-        current_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], 0);
-        new_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[new_workspace], 0);
+    desktop->priv->current_workspace = new_workspace;
 
-        if(!xfce_backdrop_compare_backdrops(current_backdrop, new_backdrop)) {
-            backdrop_changed_cb(new_backdrop, user_data);
-            return;
-        }
-    }
+    DBG("current_workspace %d, new_workspace %d",
+        current_workspace, new_workspace);
 
-    /* We want to compare the current workspace backdrops with the new one
-     * and see if we can avoid changing them if they are the same image/style */
     for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
-        current_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i);
-        new_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[new_workspace], i);
+        /* We want to compare the current workspace backdrop with the new one
+         * and see if we can avoid changing them if they are the same image/style */
+        if(current_workspace < desktop->priv->nworkspaces) {
+            current_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i);
+            new_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[new_workspace], i);
 
-        if(!xfce_backdrop_compare_backdrops(current_backdrop, new_backdrop)) {
-            /* only update monitors that require it */
+            if(!xfce_backdrop_compare_backdrops(current_backdrop, new_backdrop)) {
+                /* only update monitors that require it */
+                backdrop_changed_cb(new_backdrop, user_data);
+            }
+        } else {
+            /* If current_workspace was removed, get the new backdrop and apply it */
+            new_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[new_workspace], i);
             backdrop_changed_cb(new_backdrop, user_data);
         }
+
+        /* When we're spanning screens we only care about the first monitor */
+        if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[new_workspace]))
+            break;
     }
 }
 
@@ -638,6 +644,10 @@ workspace_destroyed_cb(WnckScreen *wnck_screen,
     /* deallocate it */
     desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
                                           desktop->priv->nworkspaces * sizeof(XfceWorkspace *));
+
+    /* Make sure we stay within bounds now that we removed a workspace */
+    if(desktop->priv->current_workspace > desktop->priv->nworkspaces)
+        desktop->priv->current_workspace = desktop->priv->nworkspaces;
 }
 
 static void
@@ -787,7 +797,7 @@ xfce_desktop_class_init(XfceDesktopClass *klass)
                                     g_param_spec_int("single-workspace-number",
                                                      "single-workspace-number",
                                                      "single-workspace-number",
-                                                     0, 31, 0,
+                                                     0, G_MAXINT16, 0,
                                                      XFDESKTOP_PARAM_FLAGS));
 #endif
 #undef XFDESKTOP_PARAM_FLAGS
@@ -1232,18 +1242,25 @@ xfce_desktop_get_current_workspace(XfceDesktop *desktop)
     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), -1);
 
     wnck_workspace = wnck_screen_get_active_workspace(desktop->priv->wnck_screen);
-    workspace_num = wnck_workspace_get_number(wnck_workspace);
+
+    if(wnck_workspace != NULL) {
+        workspace_num = wnck_workspace_get_number(wnck_workspace);
+    } else {
+        workspace_num = desktop->priv->nworkspaces;
+    }
 
     /* If we're in single_workspace mode we need to return the workspace that
-     * it was set to, otherwise return the current workspace */
-    if(xfce_desktop_get_single_workspace_mode(desktop)) {
+     * it was set to, if possible, otherwise return the current workspace */
+    if(xfce_desktop_get_single_workspace_mode(desktop) &&
+       desktop->priv->single_workspace_num < desktop->priv->nworkspaces) {
         current_workspace = desktop->priv->single_workspace_num;
     } else {
         current_workspace = workspace_num;
     }
 
-    DBG("workspace_num %d, single_workspace_num %d, current_workspace %d",
-        workspace_num, desktop->priv->single_workspace_num, current_workspace);
+    DBG("workspace_num %d, single_workspace_num %d, current_workspace %d, max workspaces %d",
+        workspace_num, desktop->priv->single_workspace_num, current_workspace,
+        desktop->priv->nworkspaces);
 
     return current_workspace;
 }
diff --git a/src/xfce-workspace.c b/src/xfce-workspace.c
index cdcae08..4d49400 100644
--- a/src/xfce-workspace.c
+++ b/src/xfce-workspace.c
@@ -84,6 +84,9 @@ struct _XfceWorkspacePriv
     guint nbackdrops;
     gboolean xinerama_stretch;
     XfceBackdrop **backdrops;
+
+    gulong *first_color_id;
+    gulong *second_color_id;
 };
 
 enum
@@ -107,6 +110,11 @@ static void xfce_workspace_get_property(GObject *object,
 static void xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
                                                    XfceBackdrop *backdrop,
                                                    guint monitor);
+static void xfce_workspace_disconnect_backdrop_settings(XfceWorkspace *workspace,
+                                                        XfceBackdrop *backdrop,
+                                                        guint monitor);
+
+static void xfce_workspace_remove_backdrops(XfceWorkspace *workspace);
 
 G_DEFINE_TYPE(XfceWorkspace, xfce_workspace, G_TYPE_OBJECT)
 
@@ -186,71 +194,52 @@ xfce_workspace_monitors_changed(XfceWorkspace *workspace,
                                 GdkScreen *gscreen)
 {
     guint i;
+    guint n_monitors;
+    GdkVisual *vis = NULL;
 
     TRACE("entering");
 
-    if(workspace->priv->nbackdrops > 1
-       && xfce_workspace_get_xinerama_stretch(workspace)) {
-        /* for xinerama stretch we only need one backdrop */
-        if(workspace->priv->nbackdrops > 1) {
-            for(i = 1; i < workspace->priv->nbackdrops; ++i)
-                g_object_unref(G_OBJECT(workspace->priv->backdrops[i]));
-        }
+    vis = gdk_screen_get_rgba_visual(gscreen);
+    if(vis == NULL)
+        vis = gdk_screen_get_system_visual(gscreen);
 
-        if(workspace->priv->nbackdrops != 1) {
-            workspace->priv->backdrops = g_realloc(workspace->priv->backdrops,
-                                                 sizeof(XfceBackdrop *));
-            if(!workspace->priv->nbackdrops) {
-                GdkVisual *vis = gdk_screen_get_rgba_visual(gscreen);
-                if(vis == NULL)
-                    vis = gdk_screen_get_system_visual(gscreen);
-
-                workspace->priv->backdrops[0] = xfce_backdrop_new(vis);
-                xfce_workspace_connect_backdrop_settings(workspace,
-                                                       workspace->priv->backdrops[0],
-                                                       0);
-                g_signal_connect(G_OBJECT(workspace->priv->backdrops[0]),
-                                 "changed",
-                                 G_CALLBACK(backdrop_changed_cb), workspace);
-                g_signal_connect(G_OBJECT(workspace->priv->backdrops[0]),
-                                 "cycle",
-                                 G_CALLBACK(backdrop_cycle_cb), workspace);
-            }
-            workspace->priv->nbackdrops = 1;
-        }
+    if(workspace->priv->nbackdrops > 0 &&
+       xfce_workspace_get_xinerama_stretch(workspace)) {
+        /* When spanning screens we only need one backdrop */
+        n_monitors = 1;
     } else {
-        /* We need one backdrop per monitor */
-        guint n_monitors = gdk_screen_get_n_monitors(gscreen);
-        GdkVisual *vis = gdk_screen_get_rgba_visual(gscreen);
-
-        if(vis == NULL)
-            vis = gdk_screen_get_system_visual(gscreen);
-
-        /* Remove all backdrops so that the correct montior is added/removed and
-         * things stay in the correct order */
-        for(i = 0; i < workspace->priv->nbackdrops; ++i)
-            g_object_unref(G_OBJECT(workspace->priv->backdrops[i]));
-
-        workspace->priv->backdrops = g_realloc(workspace->priv->backdrops,
-                                               sizeof(XfceBackdrop *) * n_monitors);
-
-        for(i = 0; i < n_monitors; ++i) {
-            DBG("Adding workspace %d backdrop %d", workspace->priv->workspace_num, i);
-
-            workspace->priv->backdrops[i] = xfce_backdrop_new(vis);
-            xfce_workspace_connect_backdrop_settings(workspace,
-                                                   workspace->priv->backdrops[i],
-                                                   i);
-            g_signal_connect(G_OBJECT(workspace->priv->backdrops[i]),
-                             "changed",
-                             G_CALLBACK(backdrop_changed_cb), workspace);
-            g_signal_connect(G_OBJECT(workspace->priv->backdrops[i]),
-                             "cycle",
-                             G_CALLBACK(backdrop_cycle_cb),
-                             workspace);
-        }
-        workspace->priv->nbackdrops = n_monitors;
+        n_monitors = gdk_screen_get_n_monitors(gscreen);
+    }
+
+    /* Remove all backdrops so that the correct monitor is added/removed and
+     * things stay in the correct order */
+    xfce_workspace_remove_backdrops(workspace);
+
+    /* Allocate space for the backdrops and their color properties so they
+     * can correctly be removed */
+    workspace->priv->backdrops = g_realloc(workspace->priv->backdrops,
+                                           sizeof(XfceBackdrop *) * n_monitors);
+    workspace->priv->first_color_id = g_realloc(workspace->priv->first_color_id,
+                                                sizeof(gulong) * n_monitors);
+    workspace->priv->second_color_id = g_realloc(workspace->priv->second_color_id,
+                                                 sizeof(gulong) * n_monitors);
+
+    for(i = 0; i < n_monitors; ++i) {
+        DBG("Adding workspace %d backdrop %d", workspace->priv->workspace_num, i);
+
+        workspace->priv->backdrops[i] = xfce_backdrop_new(vis);
+        xfce_workspace_connect_backdrop_settings(workspace,
+                                               workspace->priv->backdrops[i],
+                                               i);
+        g_signal_connect(G_OBJECT(workspace->priv->backdrops[i]),
+                         "changed",
+                         G_CALLBACK(backdrop_changed_cb), workspace);
+        g_signal_connect(G_OBJECT(workspace->priv->backdrops[i]),
+                         "cycle",
+                         G_CALLBACK(backdrop_cycle_cb),
+                         workspace);
     }
+    workspace->priv->nbackdrops = n_monitors;
 }
 
 static void
@@ -287,9 +276,13 @@ xfce_workspace_finalize(GObject *object)
 {
     XfceWorkspace *workspace = XFCE_WORKSPACE(object);
 
+    xfce_workspace_remove_backdrops(workspace);
+
     g_object_unref(G_OBJECT(workspace->priv->channel));
     g_free(workspace->priv->property_prefix);
-
+    g_free(workspace->priv->backdrops);
+    g_free(workspace->priv->first_color_id);
+    g_free(workspace->priv->second_color_id);
 }
 
 static void
@@ -349,13 +342,13 @@ xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
 
     buf[pp_len] = 0;
     g_strlcat(buf, "color1", sizeof(buf));
-    xfconf_g_property_bind_gdkcolor(channel, buf,
-                                    G_OBJECT(backdrop), "first-color");
+    workspace->priv->first_color_id[monitor] = xfconf_g_property_bind_gdkcolor(channel, buf,
+                                                            G_OBJECT(backdrop), "first-color");
 
     buf[pp_len] = 0;
     g_strlcat(buf, "color2", sizeof(buf));
-    xfconf_g_property_bind_gdkcolor(channel, buf,
-                                    G_OBJECT(backdrop), "second-color");
+    workspace->priv->second_color_id[monitor] = xfconf_g_property_bind_gdkcolor(channel, buf,
+                                                            G_OBJECT(backdrop), "second-color");
 
     buf[pp_len] = 0;
     g_strlcat(buf, "image-style", sizeof(buf));
@@ -385,7 +378,85 @@ xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
     g_free(monitor_name);
 }
 
+static void
+xfce_workspace_disconnect_backdrop_settings(XfceWorkspace *workspace,
+                                            XfceBackdrop *backdrop,
+                                            guint monitor)
+{
+    XfconfChannel *channel = workspace->priv->channel;
+    char buf[1024];
+    gint pp_len;
+    gchar *monitor_name = NULL;
+
+    TRACE("entering");
+
+    monitor_name = gdk_screen_get_monitor_plug_name(workspace->priv->gscreen, monitor);
+
+    if(monitor_name == NULL) {
+        g_snprintf(buf, sizeof(buf), "%smonitor%d/workspace%d/",
+                   workspace->priv->property_prefix, monitor, workspace->priv->workspace_num);
+    } else {
+        g_snprintf(buf, sizeof(buf), "%smonitor%s/workspace%d/",
+                   workspace->priv->property_prefix, monitor_name, workspace->priv->workspace_num);
+    }
+    pp_len = strlen(buf);
+
+    DBG("prefix string: %s", buf);
 
+    g_strlcat(buf, "color-style", sizeof(buf));
+    xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(backdrop), "color-style");
+
+    xfconf_g_property_unbind(workspace->priv->first_color_id[monitor]);
+    xfconf_g_property_unbind(workspace->priv->second_color_id[monitor]);
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "image-style", sizeof(buf));
+    xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(backdrop), "image-style");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "backdrop-cycle-enable", sizeof(buf));
+    xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(backdrop), "backdrop-cycle-enable");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "backdrop-cycle-timer", sizeof(buf));
+    xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(backdrop), "backdrop-cycle-timer");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "backdrop-cycle-random-order", sizeof(buf));
+    xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(backdrop), "backdrop-cycle-random-order");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "last-image", sizeof(buf));
+    xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(backdrop), "image-filename");
+
+    g_free(monitor_name);
+}
+
+static void
+xfce_workspace_remove_backdrops(XfceWorkspace *workspace)
+{
+    guint i;
+    guint n_monitors;
+
+    g_return_if_fail(XFCE_IS_WORKSPACE(workspace));
+
+    n_monitors = gdk_screen_get_n_monitors(workspace->priv->gscreen);
+
+    for(i = 0; i < n_monitors && i < workspace->priv->nbackdrops; ++i) {
+        xfce_workspace_disconnect_backdrop_settings(workspace,
+                                                    workspace->priv->backdrops[i],
+                                                    i);
+        g_object_unref(G_OBJECT(workspace->priv->backdrops[i]));
+        workspace->priv->backdrops[i] = NULL;
+    }
+    workspace->priv->nbackdrops = 0;
+}
 
 /* public api */
 


More information about the Xfce4-commits mailing list