]> icculus.org git repositories - dana/openbox.git/blob - openbox/client_set.c
make empty sets still a ObClientSet* structure and not a NULL.
[dana/openbox.git] / openbox / client_set.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    client_set.c for the Openbox window manager
4    Copyright (c) 2011        Dana Jansens
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "client_set.h"
20 #include "client.h"
21 #include "event.h"
22
23 #include <glib.h>
24
25 struct _ObClientSet {
26     GHashTable *h;
27 };
28
29 static void client_destroyed(ObClient *client, ObClientSet *set)
30 {
31     g_hash_table_remove(set->h, &client->window);
32 }
33
34 ObClientSet* client_set_empty(void)
35 {
36     ObClientSet *set;
37
38     set = g_slice_new(ObClientSet);
39     set->h = g_hash_table_new(g_int_hash, g_int_equal);
40     client_add_destroy_notify((ObClientCallback)client_destroyed, set);
41     return set;
42 }
43
44 ObClientSet* client_set_single(void)
45 {
46     struct _ObClient *c;
47     ObClientSet *set;
48
49     c = event_current_target();
50     if (!c) return NULL;
51     set = client_set_empty();
52     g_hash_table_insert(set->h, &c->window, c);
53     return set;
54 }
55
56 /*! Returns a new set of clients with all possible client in it.*/
57 ObClientSet* client_set_all(void)
58 {
59     ObClientSet *set;
60     GList *it;
61
62     if (!client_list) return NULL;
63     set = client_set_empty();
64     for (it = client_list; it; it = g_list_next(it)) {
65         ObClient *c = it->data;
66         g_hash_table_insert(set->h, &c->window, c);
67     }
68     return set;
69 }
70
71 void client_set_destroy(ObClientSet *set)
72 {
73     client_remove_destroy_notify_data((ObClientCallback)client_destroyed, set);
74     g_hash_table_destroy(set->h);
75     g_slice_free(ObClientSet, set);
76 }
77
78 static void foreach_union(gpointer k, gpointer v, gpointer u)
79 {
80     GHashTable *set = u;
81     g_hash_table_insert(set, k, v); /* add everything in the other set */
82 }
83
84 /* Returns a new set which contains all clients in either @a or @b.  The sets
85    @a and @b are considered freed once passed to this function.
86 */
87 ObClientSet* client_set_union(ObClientSet *a, ObClientSet *b)
88 {
89     g_return_val_if_fail(a != NULL, NULL);
90     g_return_val_if_fail(b != NULL, NULL);
91
92     g_hash_table_foreach(b->h, foreach_union, a->h);
93     client_set_destroy(b);
94     return a;
95 }
96
97 static gboolean foreach_intersection(gpointer k, gpointer v, gpointer u)
98 {
99     GHashTable *set = u;
100     return !g_hash_table_lookup(set, k); /* remove if not in the other set */
101 }
102
103 /* Returns a new set which contains all clients in both @a and @b.  The sets
104    @a and @b are considered freed once passed to this function.
105 */
106 ObClientSet* client_set_intersection(ObClientSet *a, ObClientSet *b)
107 {
108     g_return_val_if_fail(a != NULL, NULL);
109     g_return_val_if_fail(b != NULL, NULL);
110
111     g_hash_table_foreach_remove(a->h, foreach_intersection, b->h);
112     client_set_destroy(b);
113     return a;
114 }
115
116 static gboolean foreach_reduce(gpointer k, gpointer v, gpointer u)
117 {
118     ObClient *c = v;
119     ObClientSetReduceFunc f = u;
120     return f(c);
121 }
122
123 ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f)
124 {
125     g_return_val_if_fail(set != NULL, NULL);
126     g_return_val_if_fail(f != NULL, NULL);
127
128     g_hash_table_foreach_remove(set->h, foreach_reduce, f);
129     return set;
130 }
131
132 ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f)
133 {
134     GList *it;
135
136     g_return_val_if_fail(set != NULL, NULL);
137     g_return_val_if_fail(f != NULL, NULL);
138
139     for (it = client_list; it; it = g_list_next(it)) {
140         ObClient *c = it->data;
141         if (!g_hash_table_lookup(set->h, &c->window) && f(c))
142             g_hash_table_insert(set->h, &c->window, c);
143     }
144     return set;
145 }