Add a means to duplicate ObClientSet
authorDana Jansens <danakj@orodu.net>
Tue, 2 Aug 2011 18:45:21 +0000 (14:45 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Oct 2011 22:55:15 +0000 (18:55 -0400)
and fix destroy notifications.
- set the destroy notification when making a set with a single window, not
  when making an empty set.
- always add/remove the destroy notification when creating/destroying the hash
  table

openbox/client_set.c
openbox/client_set.h

index a949ed997006edd75b71366892ebce0dcdd8f821..f29709392e16c8f076c452f08efc92354a14efa9 100644 (file)
@@ -33,6 +33,20 @@ static void client_destroyed(ObClient *client, ObClientSet *set)
     g_hash_table_remove(set->h, &client->window);
 }
 
+static void client_set_create_hash(ObClientSet *set)
+{
+    set->h = g_hash_table_new(g_int_hash, g_int_equal);
+    client_add_destroy_notify((ObClientCallback)client_destroyed, set);
+}
+
+static void client_set_destroy_hash(ObClientSet *set)
+{
+    g_hash_table_unref(set->h);
+    client_remove_destroy_notify_data(
+        (ObClientCallback)client_destroyed, set);
+    set->h = NULL;
+}
+
 ObClientSet* client_set_empty(void)
 {
     ObClientSet *set;
@@ -40,7 +54,6 @@ ObClientSet* client_set_empty(void)
     set = g_slice_new(ObClientSet);
     set->all = FALSE;
     set->h = NULL;
-    client_add_destroy_notify((ObClientCallback)client_destroyed, set);
     return set;
 }
 
@@ -51,7 +64,7 @@ ObClientSet* client_set_single(ObClient *c)
     if (!c) return NULL;
     set = g_slice_new(ObClientSet);
     set->all = FALSE;
-    set->h = g_hash_table_new(g_int_hash, g_int_equal);
+    client_set_create_hash(set);
     g_hash_table_insert(set->h, &c->window, c);
     return set;
 }
@@ -68,13 +81,37 @@ ObClientSet* client_set_all(void)
     return set;
 }
 
+static void foreach_clone(gpointer k, gpointer v, gpointer u)
+{
+    ObClient *c = v;
+    GHashTable *seth = u;
+    g_hash_table_insert(seth, &c->window, c);
+}
+
+ObClientSet* client_set_clone(ObClientSet *a)
+{
+    ObClientSet *set;
+
+    if (!a) return NULL;
+    set = g_slice_new(ObClientSet);
+    set->all = a->all;
+    if (!a->h) set->h = NULL;
+    else {
+        client_set_create_hash(set);
+        g_hash_table_foreach(a->h, foreach_clone, set->h);
+    }
+    return set;
+}
+
 void client_set_destroy(ObClientSet *set)
 {
     if (set) {
         if (!set->all) {
-            client_remove_destroy_notify_data(
-                (ObClientCallback)client_destroyed, set);
-            if (set->h) g_hash_table_destroy(set->h);
+            if (set->h) {
+                client_remove_destroy_notify_data(
+                    (ObClientCallback)client_destroyed, set);
+                g_hash_table_destroy(set->h);
+            }
         }
         g_slice_free(ObClientSet, set);
     }
@@ -168,7 +205,8 @@ ObClientSet* client_set_minus(ObClientSet *a, ObClientSet *b)
     g_return_val_if_fail(b != NULL, NULL);
 
     if (a == b) {
-        if (a->h) g_hash_table_unref(a->h);
+        if (a->h)
+            client_set_destroy_hash(a);
         a->all = FALSE;
         return a;
     }
@@ -234,10 +272,8 @@ ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f,
     d.f = f;
     d.data = data;
     g_hash_table_foreach_remove(set->h, foreach_reduce, &d);
-    if (g_hash_table_size(set->h) == 0) {
-        g_hash_table_unref(set->h);
-        set->h = NULL;
-    }
+    if (g_hash_table_size(set->h) == 0)
+        client_set_destroy_hash(set);
     return set;
 }
 
@@ -258,14 +294,13 @@ ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f,
         if (!set->h || !g_hash_table_lookup(set->h, &c->window))
             if (f(c, data)) {
                 if (!set->h)
-                    set->h = g_hash_table_new(g_int_hash, g_int_equal);
+                    client_set_create_hash(set);
                 g_hash_table_insert(set->h, &c->window, c);
             }
         ++avail;
     }
     if (g_hash_table_size(set->h) == avail) {
-        g_hash_table_unref(set->h);
-        set->h = NULL;
+        client_set_destroy_hash(set);
         set->all = TRUE;
     }
     return set;
index 2ec50716c37471c55b694b6c662d67caa3009b1d..33474493d143ea9badda46ab0bf90139dfd74543 100644 (file)
@@ -32,20 +32,23 @@ ObClientSet* client_set_single(struct _ObClient *c);
 /*! Returns a new set of clients with all possible clients in it. */
 ObClientSet* client_set_all(void);
 
+/*! Returns an identical set to @a. */
+ObClientSet* client_set_clone(ObClientSet *a);
+
 void client_set_destroy(ObClientSet *set);
 
-/* Returns a new set which contains all clients in either @a or @b.  The sets
-   @a and @b are considered freed once passed to this function.
+/*! Returns a new set which contains all clients in either @a or @b.  The sets
+  @a and @b are considered freed once passed to this function.
 */
 ObClientSet* client_set_union(ObClientSet *a, ObClientSet *b);
 
-/* Returns a new set which contains all clients in both @a and @b.  The sets
-   @a and @b are considered freed once passed to this function.
+/*! Returns a new set which contains all clients in both @a and @b.  The sets
+  @a and @b are considered freed once passed to this function.
 */
 ObClientSet* client_set_intersection(ObClientSet *a, ObClientSet *b);
 
-/* Returns a new set which contains all clients in @a but not in @b.  The sets
-   @a and @b are considered freed once passed to this function.
+/*! Returns a new set which contains all clients in @a but not in @b.  The sets
+  @a and @b are considered freed once passed to this function.
 */
 ObClientSet* client_set_minus(ObClientSet *a, ObClientSet *b);