Add ObClientSet data type. It holds a set of clients !
authorDana Jansens <danakj@orodu.net>
Fri, 29 Jul 2011 20:00:02 +0000 (16:00 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Oct 2011 22:55:14 +0000 (18:55 -0400)
The sets can be modified by union and intersection, and can have clients
added or removed with a test callback function.
They use a GHashTable underneath.

Makefile.am
openbox/client_set.c [new file with mode: 0644]
openbox/client_set.h [new file with mode: 0644]

index d92253f9326b8f40c96cbe468ffea01111b9a6f5..3ca51665a844d14725a237f0fbd39249acb8daef 100644 (file)
@@ -256,6 +256,8 @@ openbox_openbox_SOURCES = \
        openbox/client_list_combined_menu.h \
        openbox/client_menu.c \
        openbox/client_menu.h \
+       openbox/client_set.c \
+       openbox/client_set.h \
        openbox/config.c \
        openbox/config.h \
        openbox/debug.c \
diff --git a/openbox/client_set.c b/openbox/client_set.c
new file mode 100644 (file)
index 0000000..9f70e7c
--- /dev/null
@@ -0,0 +1,144 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   client_set.c for the Openbox window manager
+   Copyright (c) 2011        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "client_set.h"
+#include "client.h"
+#include "event.h"
+
+#include <glib.h>
+
+void client_destroyed(ObClient *client, ObClientSet *set);
+
+struct _ObClientSet {
+    GHashTable *h;
+};
+
+static ObClientSet* empty_set(void)
+{
+    ObClientSet *set;
+
+    set = g_slice_new(ObClientSet);
+    set->h = g_hash_table_new(g_int_hash, g_int_equal);
+    client_add_destroy_notify((ObClientCallback)client_destroyed, set);
+    return set;
+}
+
+ObClientSet* client_set_single(void)
+{
+    struct _ObClient *c;
+    ObClientSet *set;
+
+    c = event_current_target();
+    if (!c) return NULL;
+    set = empty_set();
+    g_hash_table_insert(set->h, &c->window, c);
+    return set;
+}
+
+/*! Returns a new set of clients with all possible client in it.*/
+ObClientSet* client_set_all(void)
+{
+    ObClientSet *set;
+    GList *it;
+
+    if (!client_list) return NULL;
+    set = g_slice_new(ObClientSet);
+    set->h = g_hash_table_new(g_int_hash, g_int_equal);
+    for (it = client_list; it; it = g_list_next(it)) {
+        ObClient *c = it->data;
+        g_hash_table_insert(set->h, &c->window, c);
+    }
+    client_add_destroy_notify((ObClientCallback)client_destroyed, set);
+    return set;
+}
+
+void client_destroyed(ObClient *client, ObClientSet *set)
+{
+    g_hash_table_remove(set->h, &client->window);
+}
+
+void client_set_destroy(ObClientSet *set)
+{
+    client_remove_destroy_notify_data((ObClientCallback)client_destroyed, set);
+    g_hash_table_destroy(set->h);
+    g_slice_free(ObClientSet, set);
+}
+
+static void foreach_union(gpointer k, gpointer v, gpointer u)
+{
+    GHashTable *set = u;
+    g_hash_table_insert(set, k, v); /* add everything in the other 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.
+*/
+ObClientSet* client_set_union(ObClientSet *a, ObClientSet *b)
+{
+    g_hash_table_foreach(b->h, foreach_union, a->h);
+    client_set_destroy(b);
+    return a;
+}
+
+static gboolean foreach_intersection(gpointer k, gpointer v, gpointer u)
+{
+    GHashTable *set = u;
+    return !g_hash_table_lookup(set, k); /* remove if not in the other set */
+}
+
+/* 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)
+{
+    g_hash_table_foreach_remove(a->h, foreach_intersection, b->h);
+    client_set_destroy(b);
+    return a;
+}
+
+static gboolean foreach_reduce(gpointer k, gpointer v, gpointer u)
+{
+    ObClient *c = v;
+    ObClientSetReduceFunc f = u;
+    return f(c);
+}
+
+ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f)
+{
+    g_hash_table_foreach_remove(set->h, foreach_reduce, f);
+    if (g_hash_table_size(set->h) > 0)
+        return set;
+    client_set_destroy(set);
+    return NULL;
+}
+
+ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f)
+{
+    GList *it;
+
+    for (it = client_list; it; it = g_list_next(it)) {
+        ObClient *c = it->data;
+        if (!set || !g_hash_table_lookup(set->h, &c->window)) {
+            if (f(c)) {
+                if (!set) set = empty_set();
+                g_hash_table_insert(set->h, &c->window, c);
+            }
+        }
+    }
+    return set;
+}
diff --git a/openbox/client_set.h b/openbox/client_set.h
new file mode 100644 (file)
index 0000000..efdf200
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   client_set.h for the Openbox window manager
+   Copyright (c) 2011        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include <glib.h>
+
+struct _ObClient;
+
+/*! A set of ObClients. An empty set is always a NULL pointer. */
+typedef struct _ObClientSet ObClientSet;
+
+typedef gboolean (*ObClientSetReduceFunc)(struct _ObClient *c);
+typedef gboolean (*ObClientSetExpandFunc)(struct _ObClient *c);
+
+/*! 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.*/
+ObClientSet* client_set_all(void);
+
+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.
+*/
+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.
+*/
+ObClientSet* client_set_intersection(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. */
+ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f);
+
+/*! Expand a set of clients.  The function @f is called for each client
+  not currently in the set. For each client that it returns TRUE, the client
+  will be added to the set. */
+ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f);