#include <glib.h>
struct _ObClientSet {
+ guint ref;
gboolean all;
GHashTable *h;
};
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;
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)
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;
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;
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;
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.
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;
gpointer data)
{
GList *it;
- gint avail;
+ guint avail;
g_return_val_if_fail(set != NULL, NULL);
g_return_val_if_fail(f != NULL, NULL);
++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;
}
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;
+}
/*! 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);
*/
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. */
"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);