4 #include <xcb/xcb_event.h>
13 node_t *make_node(void)
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_mode = MODE_AUTOMATIC;
19 n->split_type = TYPE_VERTICAL;
20 n->birth_rotation = 0;
26 monitor_t *make_monitor(xcb_rectangle_t *rect)
28 monitor_t *m = malloc(sizeof(monitor_t));
29 snprintf(m->name, sizeof(m->name), "%s%02d", DEFAULT_MON_NAME, ++monitor_uid);
30 m->prev = m->next = NULL;
31 m->desk = m->last_desk = NULL;
35 warn("no rectangle was given for monitor '%s'\n", m->name);
36 m->top_padding = m->right_padding = m->bottom_padding = m->left_padding = 0;
41 monitor_t *find_monitor(char *name)
43 for (monitor_t *m = mon_head; m != NULL; m = m->next)
44 if (streq(m->name, name))
49 monitor_t *get_monitor_by_id(xcb_randr_output_t id)
51 for (monitor_t *m = mon_head; m != NULL; m = m->next)
57 monitor_t *add_monitor(xcb_rectangle_t *rect)
59 monitor_t *m = make_monitor(rect);
73 void remove_monitor(monitor_t *m)
75 while (m->desk_head != NULL)
76 remove_desktop(m, m->desk_head);
77 monitor_t *prev = m->prev;
78 monitor_t *next = m->next;
90 monitor_t *mm = (last_mon == NULL ? (prev == NULL ? next : prev) : last_mon);
92 focus_node(mm, mm->desk, mm->desk->focus);
103 void transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d)
107 desktop_t *dd = ms->desk;
108 unlink_desktop(ms, d);
109 insert_desktop(md, d);
111 if (ms->desk != NULL)
112 desktop_show(ms->desk);
116 for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
117 fit_monitor(md, n->client);
119 if (d != dd && md->desk == d) {
123 ewmh_update_desktop_names();
126 void merge_monitors(monitor_t *ms, monitor_t *md)
128 PRINTF("merge %s into %s\n", ms->name, md->name);
130 desktop_t *d = ms->desk_head;
132 desktop_t *next = d->next;
133 transfer_desktop(ms, md, d);
138 desktop_t *make_desktop(const char *name)
140 desktop_t *d = malloc(sizeof(desktop_t));
142 snprintf(d->name, sizeof(d->name), "%s%02d", DEFAULT_DESK_NAME, ++desktop_uid);
144 strncpy(d->name, name, sizeof(d->name));
145 d->layout = LAYOUT_TILED;
146 d->prev = d->next = NULL;
147 d->root = d->focus = NULL;
148 d->history = make_focus_history();
152 void insert_desktop(monitor_t *m, desktop_t *d)
154 if (m->desk == NULL) {
159 m->desk_tail->next = d;
160 d->prev = m->desk_tail;
165 void add_desktop(monitor_t *m, desktop_t *d)
167 PRINTF("add desktop %s\n", d->name);
169 insert_desktop(m, d);
171 ewmh_update_number_of_desktops();
172 ewmh_update_desktop_names();
176 void empty_desktop(desktop_t *d)
178 destroy_tree(d->root);
179 d->root = d->focus = NULL;
180 empty_history(d->history);
183 void unlink_desktop(monitor_t *m, desktop_t *d)
185 desktop_t *prev = d->prev;
186 desktop_t *next = d->next;
191 if (m->desk_head == d)
193 if (m->desk_tail == d)
195 if (m->last_desk == d)
198 m->desk = (m->last_desk == NULL ? (prev == NULL ? next : prev) : m->last_desk);
199 d->prev = d->next = NULL;
202 void remove_desktop(monitor_t *m, desktop_t *d)
204 PRINTF("remove desktop %s\n", d->name);
206 unlink_desktop(m, d);
210 ewmh_update_number_of_desktops();
211 ewmh_update_desktop_names();
215 client_t *make_client(xcb_window_t win)
217 client_t *c = malloc(sizeof(client_t));
218 strncpy(c->class_name, MISSING_VALUE, sizeof(c->class_name));
219 c->border_width = border_width;
221 c->floating = c->transient = c->fullscreen = c->locked = c->urgent = false;
222 c->icccm_focus = false;
223 xcb_icccm_get_wm_protocols_reply_t protocols;
224 if (xcb_icccm_get_wm_protocols_reply(dpy, xcb_icccm_get_wm_protocols(dpy, win, ewmh->WM_PROTOCOLS), &protocols, NULL) == 1) {
225 if (has_proto(WM_TAKE_FOCUS, &protocols))
226 c->icccm_focus = true;
227 xcb_icccm_get_wm_protocols_reply_wipe(&protocols);
232 rule_t *make_rule(void)
234 rule_t *r = malloc(sizeof(rule_t));
236 r->effect.floating = false;
237 r->effect.follow = false;
238 r->effect.focus = false;
239 r->effect.desc[0] = '\0';
245 pointer_state_t *make_pointer_state(void)
247 pointer_state_t *p = malloc(sizeof(pointer_state_t));
250 p->node = p->vertical_fence = p->horizontal_fence = NULL;
252 p->window = XCB_NONE;
256 focus_history_t *make_focus_history(void)
258 focus_history_t *f = malloc(sizeof(focus_history_t));
259 f->head = f->tail = NULL;
263 node_list_t *make_node_list(void)
265 node_list_t *n = malloc(sizeof(node_list_t));
267 n->prev = n->next = NULL;
272 void history_add(focus_history_t *f, node_t *n)
274 node_list_t *a = make_node_list();
276 if (f->head == NULL) {
277 f->head = f->tail = a;
278 } else if (f->head->node != n) {
279 for (node_list_t *b = f->head; b != NULL; b = b->next)
290 void history_remove(focus_history_t *f, node_t *n)
292 /* in order to maintain the `latest` node list state,
293 we remove node lists from head to tail */
294 node_list_t *b = f->head;
297 node_list_t *a = b->prev;
298 node_list_t *c = b->next;
300 /* remove duplicate entries */
301 while (c != NULL && c->node == a->node) {
302 node_list_t *d = c->next;
324 void empty_history(focus_history_t *f)
326 node_list_t *a = f->head;
328 node_list_t *b = a->next;
332 f->head = f->tail = NULL;
335 node_t *history_get(focus_history_t *f, int i)
337 node_list_t *a = f->head;
338 while (a != NULL && i > 0) {
348 node_t *history_last(focus_history_t *f, node_t *n, client_select_t sel)
350 for (node_list_t *a = f->head; a != NULL; a = a->next) {
351 if (!a->latest || a->node == n || !node_matches(n, a->node, sel))
358 int history_rank(focus_history_t *f, node_t *n)
361 node_list_t *a = f->head;
362 while (a != NULL && (!a->latest || a->node != n)) {