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