Add the minus and contains() operations to ObClientSet, and allow creating a set...
authorDana Jansens <danakj@orodu.net>
Tue, 2 Aug 2011 18:20:14 +0000 (14:20 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Oct 2011 22:55:15 +0000 (18:55 -0400)
openbox/client_set.c
openbox/client_set.h

index ab6085646b6ec4e15647a3ae58f1fbac02deb852..a949ed997006edd75b71366892ebce0dcdd8f821 100644 (file)
@@ -23,6 +23,7 @@
 #include <glib.h>
 
 struct _ObClientSet {
+    guint ref;
     gboolean all;
     GHashTable *h;
 };
@@ -43,12 +44,10 @@ ObClientSet* client_set_empty(void)
     return set;
 }
 
-ObClientSet* client_set_single(void)
+ObClientSet* client_set_single(ObClient *c)
 {
-    struct _ObClient *c;
     ObClientSet *set;
 
-    c = event_current_target();
     if (!c) return NULL;
     set = g_slice_new(ObClientSet);
     set->all = FALSE;
@@ -71,12 +70,14 @@ ObClientSet* client_set_all(void)
 
 void client_set_destroy(ObClientSet *set)
 {
-    if (!set->all) {
-        client_remove_destroy_notify_data((ObClientCallback)client_destroyed,
-                                          set);
-        if (set->h) g_hash_table_destroy(set->h);
+    if (set) {
+        if (!set->all) {
+            client_remove_destroy_notify_data(
+                (ObClientCallback)client_destroyed, set);
+            if (set->h) g_hash_table_destroy(set->h);
+        }
+        g_slice_free(ObClientSet, set);
     }
-    g_slice_free(ObClientSet, set);
 }
 
 static void foreach_union(gpointer k, gpointer v, gpointer u)
@@ -93,6 +94,8 @@ ObClientSet* client_set_union(ObClientSet *a, ObClientSet *b)
     g_return_val_if_fail(a != NULL, NULL);
     g_return_val_if_fail(b != NULL, NULL);
 
+    if (a == b)
+        return a;
     if (a->all) {
         client_set_destroy(b);
         return a;
@@ -129,6 +132,8 @@ ObClientSet* client_set_intersection(ObClientSet *a, ObClientSet *b)
     g_return_val_if_fail(a != NULL, NULL);
     g_return_val_if_fail(b != NULL, NULL);
 
+    if (a == b)
+        return a;
     if (a->all) {
         client_set_destroy(a);
         return b;
@@ -151,6 +156,39 @@ ObClientSet* client_set_intersection(ObClientSet *a, ObClientSet *b)
     return a;
 }
 
+static gboolean reduce_minus(struct _ObClient *c, gpointer data)
+{
+    ObClientSet *b = data;
+    return client_set_contains(b, c);
+}
+
+ObClientSet* client_set_minus(ObClientSet *a, ObClientSet *b)
+{
+    g_return_val_if_fail(a != NULL, NULL);
+    g_return_val_if_fail(b != NULL, NULL);
+
+    if (a == b) {
+        if (a->h) g_hash_table_unref(a->h);
+        a->all = FALSE;
+        return a;
+    }
+    if (b->all) {
+        client_set_destroy(a);
+        b->all = FALSE; /* make empty */
+        return b;
+    }
+    if (!b->h) {
+        client_set_destroy(b);
+        return a;
+    }
+    if (!a->h) {
+        client_set_destroy(b);
+        return a;
+    }
+
+    return client_set_reduce(a, reduce_minus, b);
+}
+
 struct ObClientSetForeachReduce {
     ObClientSetReduceFunc f;
     gpointer data;
@@ -178,7 +216,7 @@ ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f,
     g_return_val_if_fail(f != NULL, NULL);
 
     if (set->all) {
-        struct ObClientSetForeachReduce *d;
+        struct ObClientSetForeachReduce d;
 
         /* use set expansion on an empty set rather than building a full set
            and then removing stuff.  but we're given a reduce function.
@@ -197,7 +235,7 @@ ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc 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_destroy(set->h);
+        g_hash_table_unref(set->h);
         set->h = NULL;
     }
     return set;
@@ -207,7 +245,7 @@ ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f,
                                gpointer data)
 {
     GList *it;
-    gint avail;
+    guint avail;
 
     g_return_val_if_fail(set != NULL, NULL);
     g_return_val_if_fail(f != NULL, NULL);
@@ -226,7 +264,7 @@ ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f,
         ++avail;
     }
     if (g_hash_table_size(set->h) == avail) {
-        g_hash_table_destroy(set->h);
+        g_hash_table_unref(set->h);
         set->h = NULL;
         set->all = TRUE;
     }
@@ -245,3 +283,9 @@ gboolean client_set_test_boolean(ObClientSet *set)
     else return set->h != NULL;
 }
 
+gboolean client_set_contains(ObClientSet *set, struct _ObClient *c)
+{
+    if (set->all) return TRUE;
+    if (!set->h) return FALSE;
+    return g_hash_table_lookup(set->h, &c->window) != NULL;
+}
index 8d35ab3a615ca5550df16ee72c2458320c566627..2ec50716c37471c55b694b6c662d67caa3009b1d 100644 (file)
@@ -27,9 +27,8 @@ typedef gboolean (*ObClientSetExpandFunc)(struct _ObClient *c, gpointer data);
 
 /*! Returns a new set of clients without anything in it. */
 ObClientSet* client_set_empty(void);
-/*! Returns a new set of clients with a single client in it.
-  The client is the currently targeted window. */
-ObClientSet* client_set_single(void);
+/*! Returns a new set of clients with a single client in it. */
+ObClientSet* client_set_single(struct _ObClient *c);
 /*! Returns a new set of clients with all possible clients in it. */
 ObClientSet* client_set_all(void);
 
@@ -45,6 +44,11 @@ ObClientSet* client_set_union(ObClientSet *a, ObClientSet *b);
 */
 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.
+*/
+ObClientSet* client_set_minus(ObClientSet *a, ObClientSet *b);
+
 /*! Reduce a set of clients.  The function @f is called for each client
   currently in the set. For each client that it returns TRUE, the client will
   be removed from the set. */
@@ -64,3 +68,6 @@ gboolean client_set_is_empty(ObClientSet *set);
   "ALL" set, which contains all clients.  Even when there are no clients
   present, this set returns TRUE. */
 gboolean client_set_test_boolean(ObClientSet *set);
+
+/*! Returns TRUE if @set contains @c. */
+gboolean client_set_contains(ObClientSet *set, struct _ObClient *c);