From cf00fd0ddc5e259186c15e8bd09deefddbcafd52 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 2 Aug 2011 13:31:23 -0400 Subject: [PATCH] Fix expand/reduce in the full or empty set cases. --- openbox/client_set.c | 32 ++++++++++++++++++++++++++++++++ openbox/client_set.h | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/openbox/client_set.c b/openbox/client_set.c index 6b86b979..ab608564 100644 --- a/openbox/client_set.c +++ b/openbox/client_set.c @@ -163,6 +163,12 @@ static gboolean foreach_reduce(gpointer k, gpointer v, gpointer u) return d->f(c, d->data); } +static gboolean func_invert(struct _ObClient *c, gpointer data) +{ + struct ObClientSetForeachReduce *d = data; + return !d->f(c, d->data); +} + ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f, gpointer data) { @@ -171,6 +177,22 @@ ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f, g_return_val_if_fail(set != NULL, NULL); g_return_val_if_fail(f != NULL, NULL); + if (set->all) { + 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. + so when reduce says TRUE, we want to add (expand) it. + we use func_invert() to do this. + */ + set->all = FALSE; /* make it empty */ + d.f = f; + d.data = data; + return client_set_expand(set, func_invert, &d); + } + + if (!set->h) return set; /* already empty */ + d.f = f; d.data = data; g_hash_table_foreach_remove(set->h, foreach_reduce, &d); @@ -185,10 +207,14 @@ ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f, gpointer data) { GList *it; + gint avail; g_return_val_if_fail(set != NULL, NULL); g_return_val_if_fail(f != NULL, NULL); + if (set->all) return set; /* already full */ + + avail = 0; for (it = client_list; it; it = g_list_next(it)) { ObClient *c = it->data; if (!set->h || !g_hash_table_lookup(set->h, &c->window)) @@ -197,6 +223,12 @@ ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f, set->h = g_hash_table_new(g_int_hash, g_int_equal); g_hash_table_insert(set->h, &c->window, c); } + ++avail; + } + if (g_hash_table_size(set->h) == avail) { + g_hash_table_destroy(set->h); + set->h = NULL; + set->all = TRUE; } return set; } diff --git a/openbox/client_set.h b/openbox/client_set.h index 6e930019..8d35ab3a 100644 --- a/openbox/client_set.h +++ b/openbox/client_set.h @@ -30,7 +30,7 @@ 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 all possible client in it.*/ +/*! Returns a new set of clients with all possible clients in it. */ ObClientSet* client_set_all(void); void client_set_destroy(ObClientSet *set); -- 2.34.1