]> git.lizzy.rs Git - bspwm.git/blob - types.c
202619389d7d01248bda352fa67a57a929d0f76b
[bspwm.git] / types.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <xcb/xcb.h>
4 #include <xcb/xcb_event.h>
5 #include "bspwm.h"
6 #include "window.h"
7 #include "rules.h"
8 #include "ewmh.h"
9 #include "settings.h"
10 #include "types.h"
11 #include "tree.h"
12
13 node_t *make_node(void)
14 {
15     node_t *n = malloc(sizeof(node_t));
16     n->parent = n->first_child = n->second_child = NULL;
17     n->split_ratio = split_ratio;
18     n->split_type = TYPE_VERTICAL;
19     n->birth_rotation = ROTATE_IDENTITY;
20     n->client = NULL;
21     n->vacant = false;
22     return n;
23 }
24
25 monitor_t *make_monitor(xcb_rectangle_t *rect)
26 {
27     monitor_t *m = malloc(sizeof(monitor_t));
28     snprintf(m->name, sizeof(m->name), "%s%02d", DEFAULT_MON_NAME, ++monitor_uid);
29     m->prev = m->next = NULL;
30     m->desk = m->last_desk = NULL;
31     if (rect != NULL)
32         m->rectangle = *rect;
33     else
34         warn("no rectangle was given for monitor '%s'\n", m->name);
35     m->top_padding = m->right_padding = m->bottom_padding = m->left_padding = 0;
36     m->wired = true;
37     return m;
38 }
39
40 monitor_t *find_monitor(char *name)
41 {
42     for (monitor_t *m = mon_head; m != NULL; m = m->next)
43         if (strcmp(m->name, name) == 0)
44             return m;
45     return NULL;
46 }
47
48 monitor_t *get_monitor_by_id(xcb_randr_output_t id)
49 {
50     for (monitor_t *m = mon_head; m != NULL; m = m->next)
51         if (m->id == id)
52             return m;
53     return NULL;
54 }
55
56 monitor_t *add_monitor(xcb_rectangle_t *rect)
57 {
58     monitor_t *m = make_monitor(rect);
59     if (mon == NULL) {
60         mon = m;
61         mon_head = m;
62         mon_tail = m;
63     } else {
64         mon_tail->next = m;
65         m->prev = mon_tail;
66         mon_tail = m;
67     }
68     num_monitors++;
69     return m;
70 }
71
72 void remove_monitor(monitor_t *m)
73 {
74     while (m->desk_head != NULL)
75         remove_desktop(m, m->desk_head);
76     monitor_t *prev = m->prev;
77     monitor_t *next = m->next;
78     if (prev != NULL)
79         prev->next = next;
80     if (next != NULL)
81         next->prev = prev;
82     if (mon_head == m)
83         mon_head = next;
84     if (mon_tail == m)
85         mon_tail = prev;
86     if (last_mon == m)
87         last_mon = NULL;
88     if (mon == m)
89         mon = (last_mon == NULL ? mon_head : last_mon);
90     free(m);
91     num_monitors--;
92 }
93
94 void transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d)
95 {
96     unlink_desktop(ms, d);
97     insert_desktop(md, d);
98 }
99
100 void merge_monitors(monitor_t *ms, monitor_t *md)
101 {
102     PRINTF("merge monitor %s into %s\n", ms->name, md->name);
103
104     if (visible) {
105         for (node_t *n = first_extrema(ms->desk->root); n != NULL; n = next_leaf(n, ms->desk->root))
106             window_hide(n->client->window);
107     }
108     desktop_t *d = ms->desk_head;
109     while (d != NULL) {
110         desktop_t *next = d->next;
111         transfer_desktop(ms, md, d);
112         d = next;
113     }
114 }
115
116 desktop_t *make_desktop(const char *name)
117 {
118     desktop_t *d = malloc(sizeof(desktop_t));
119     if (name == NULL)
120         snprintf(d->name, sizeof(d->name), "%s%02d", DEFAULT_DESK_NAME, ++desktop_uid);
121     else
122         strncpy(d->name, name, sizeof(d->name));
123     d->layout = LAYOUT_TILED;
124     d->prev = d->next = NULL;
125     d->root = d->focus = NULL;
126     d->history = make_focus_history();
127     return d;
128 }
129
130 void insert_desktop(monitor_t *m, desktop_t *d)
131 {
132     if (m->desk == NULL) {
133         m->desk = d;
134         m->desk_head = d;
135         m->desk_tail = d;
136     } else {
137         m->desk_tail->next = d;
138         d->prev = m->desk_tail;
139         m->desk_tail = d;
140     }
141 }
142
143 void add_desktop(monitor_t *m, desktop_t *d)
144 {
145     PRINTF("add desktop %s\n", d->name);
146
147     insert_desktop(m, d);
148     num_desktops++;
149     ewmh_update_number_of_desktops();
150     ewmh_update_desktop_names();
151     put_status();
152 }
153
154 void empty_desktop(desktop_t *d)
155 {
156     destroy_tree(d->root);
157     d->root = d->focus = NULL;
158     empty_history(d->history);
159 }
160
161 void unlink_desktop(monitor_t *m, desktop_t *d)
162 {
163     desktop_t *prev = d->prev;
164     desktop_t *next = d->next;
165     if (prev != NULL)
166         prev->next = next;
167     if (next != NULL)
168         next->prev = prev;
169     if (m->desk_head == d)
170         m->desk_head = next;
171     if (m->desk_tail == d)
172         m->desk_tail = prev;
173     if (m->last_desk == d)
174         m->last_desk = NULL;
175     if (m->desk == d)
176         m->desk = (m->last_desk == NULL ? m->desk_head : m->last_desk);
177     d->prev = d->next = NULL;
178 }
179
180 void remove_desktop(monitor_t *m, desktop_t *d)
181 {
182     PRINTF("remove desktop %s\n", d->name);
183
184     prune_rules(d);
185     unlink_desktop(m, d);
186     empty_desktop(d);
187     free(d);
188     num_desktops--;
189     ewmh_update_number_of_desktops();
190     ewmh_update_desktop_names();
191     put_status();
192 }
193
194 client_t *make_client(xcb_window_t win)
195 {
196     client_t *c = malloc(sizeof(client_t));
197     strncpy(c->class_name, MISSING_VALUE, sizeof(c->class_name));
198     c->uid = ++client_uid;
199     c->border_width = border_width;
200     c->window = win;
201     c->floating = c->transient = c->fullscreen = c->locked = c->urgent = false;
202     return c;
203 }
204
205 rule_t *make_rule(void)
206 {
207     rule_t *r = malloc(sizeof(rule_t));
208     r->uid = ++rule_uid;
209     r->effect.floating = false;
210     r->effect.follow = false;
211     r->effect.monitor = NULL;
212     r->effect.desktop = NULL;
213     r->prev = NULL;
214     r->next = NULL;
215     return r;
216 }
217
218 pointer_state_t *make_pointer_state(void)
219 {
220     pointer_state_t *p = malloc(sizeof(pointer_state_t));
221     p->monitor = NULL;
222     p->desktop = NULL;
223     p->node = p->vertical_fence = p->horizontal_fence = NULL;
224     p->client = NULL;
225     p->window = XCB_NONE;
226     return p;
227 }
228
229 focus_history_t *make_focus_history(void)
230 {
231     focus_history_t *f = malloc(sizeof(focus_history_t));
232     f->head = f->tail = NULL;
233     return f;
234 }
235
236 node_list_t *make_node_list(void)
237 {
238     node_list_t *n = malloc(sizeof(node_list_t));
239     n->node = NULL;
240     n->prev = n->next = NULL;
241     n->latest = true;
242     return n;
243 }
244
245 void history_add(focus_history_t *f, node_t *n)
246 {
247     node_list_t *a = make_node_list();
248     a->node = n;
249     if (f->head == NULL) {
250         f->head = f->tail = a;
251     } else if (f->head->node != n) {
252         for (node_list_t *b = f->head; b != NULL; b = b->next)
253             if (b->node == n)
254                 b->latest = false;
255         f->head->prev = a;
256         a->next = f->head;
257         f->head = a;
258     } else {
259         free(a);
260     }
261 }
262
263 void history_remove(focus_history_t *f, node_t *n)
264 {
265     /* in order to maintain the `latest` node list state,
266        we remove node lists from head to tail */
267     node_list_t *b = f->head;
268     while (b != NULL) {
269         if (b->node == n) {
270             node_list_t *a = b->prev;
271             node_list_t *c = b->next;
272             if (a != NULL) {
273                 /* remove duplicate entries */
274                 while (c != NULL && c->node == a->node) {
275                     node_list_t *d = c->next;
276                     if (f->tail == c)
277                         f->tail = f->head;
278                     free(c);
279                     c = d;
280                 }
281                 a->next = c;
282             }
283             if (c != NULL)
284                 c->prev = a;
285             if (f->head == b)
286                 f->head = c;
287             if (f->tail == b)
288                 f->tail = a;
289             free(b);
290             b = c;
291         } else {
292             b = b->next;
293         }
294     }
295 }
296
297 void empty_history(focus_history_t *f)
298 {
299     node_list_t *a = f->head;
300     while (a != NULL) {
301         node_list_t *b = a->next;
302         free(a);
303         a = b;
304     }
305     f->head = f->tail = NULL;
306 }
307
308 node_t *history_get(focus_history_t *f, int i)
309 {
310     node_list_t *a = f->head;
311     while (a != NULL && i > 0) {
312         a = a->next;
313         i--;
314     }
315     if (a == NULL)
316         return NULL;
317     else
318         return a->node;
319 }