]> icculus.org git repositories - dana/openbox.git/blob - openbox/client_set.c
Add ObClientSet data type. It holds a set of clients !
[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 void client_destroyed(ObClient *client, ObClientSet *set);
26
27 struct _ObClientSet {
28     GHashTable *h;
29 };
30
31 static ObClientSet* empty_set(void)
32 {
33     ObClientSet *set;
34
35     set = g_slice_new(ObClientSet);
36     set->h = g_hash_table_new(g_int_hash, g_int_equal);
37     client_add_destroy_notify((ObClientCallback)client_destroyed, set);
38     return set;
39 }
40
41 ObClientSet* client_set_single(void)
42 {
43     struct _ObClient *c;
44     ObClientSet *set;
45
46     c = event_current_target();
47     if (!c) return NULL;
48     set = empty_set();
49     g_hash_table_insert(set->h, &c->window, c);
50     return set;
51 }
52
53 /*! Returns a new set of clients with all possible client in it.*/
54 ObClientSet* client_set_all(void)
55 {
56     ObClientSet *set;
57     GList *it;
58
59     if (!client_list) return NULL;
60     set = g_slice_new(ObClientSet);
61     set->h = g_hash_table_new(g_int_hash, g_int_equal);
62     for (it = client_list; it; it = g_list_next(it)) {
63         ObClient *c = it->data;
64         g_hash_table_insert(set->h, &c->window, c);
65     }
66     client_add_destroy_notify((ObClientCallback)client_destroyed, set);
67     return set;
68 }
69
70 void client_destroyed(ObClient *client, ObClientSet *set)
71 {
72     g_hash_table_remove(set->h, &client->window);
73 }
74
75 void client_set_destroy(ObClientSet *set)
76 {
77     client_remove_destroy_notify_data((ObClientCallback)client_destroyed, set);
78     g_hash_table_destroy(set->h);
79     g_slice_free(ObClientSet, set);
80 }
81
82 static void foreach_union(gpointer k, gpointer v, gpointer u)
83 {
84     GHashTable *set = u;
85     g_hash_table_insert(set, k, v); /* add everything in the other set */
86 }
87
88 /* Returns a new set which contains all clients in either @a or @b.  The sets
89    @a and @b are considered freed once passed to this function.
90 */
91 ObClientSet* client_set_union(ObClientSet *a, ObClientSet *b)
92 {
93     g_hash_table_foreach(b->h, foreach_union, a->h);
94     client_set_destroy(b);
95     return a;
96 }
97
98 static gboolean foreach_intersection(gpointer k, gpointer v, gpointer u)
99 {
100     GHashTable *set = u;
101     return !g_hash_table_lookup(set, k); /* remove if not in the other set */
102 }
103
104 /* Returns a new set which contains all clients in both @a and @b.  The sets
105    @a and @b are considered freed once passed to this function.
106 */
107 ObClientSet* client_set_intersection(ObClientSet *a, ObClientSet *b)
108 {
109     g_hash_table_foreach_remove(a->h, foreach_intersection, b->h);
110     client_set_destroy(b);
111     return a;
112 }
113
114 static gboolean foreach_reduce(gpointer k, gpointer v, gpointer u)
115 {
116     ObClient *c = v;
117     ObClientSetReduceFunc f = u;
118     return f(c);
119 }
120
121 ObClientSet* client_set_reduce(ObClientSet *set, ObClientSetReduceFunc f)
122 {
123     g_hash_table_foreach_remove(set->h, foreach_reduce, f);
124     if (g_hash_table_size(set->h) > 0)
125         return set;
126     client_set_destroy(set);
127     return NULL;
128 }
129
130 ObClientSet* client_set_expand(ObClientSet *set, ObClientSetExpandFunc f)
131 {
132     GList *it;
133
134     for (it = client_list; it; it = g_list_next(it)) {
135         ObClient *c = it->data;
136         if (!set || !g_hash_table_lookup(set->h, &c->window)) {
137             if (f(c)) {
138                 if (!set) set = empty_set();
139                 g_hash_table_insert(set->h, &c->window, c);
140             }
141         }
142     }
143     return set;
144 }