void select_desktop(desktop_t *d) { if (d == NULL || d == mon->desk) return; PRINTF("select desktop %s\n", d->name); if (visible) { node_t *n = first_extrema(d->root); while (n != NULL) { window_show(n->client->window); n = next_leaf(n); } n = first_extrema(mon->desk->root); while (n != NULL) { window_hide(n->client->window); n = next_leaf(n); } } mon->last_desk = mon->desk; mon->desk = d; update_current(); ewmh_update_current_desktop(); put_status(); }
void update_root(monitor_t *m, xcb_rectangle_t *rect) { xcb_rectangle_t last_rect = m->rectangle; m->rectangle = *rect; if (m->root == XCB_NONE) { uint32_t values[] = {XCB_EVENT_MASK_ENTER_WINDOW}; m->root = xcb_generate_id(dpy); xcb_create_window(dpy, XCB_COPY_FROM_PARENT, m->root, root, rect->x, rect->y, rect->width, rect->height, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, XCB_CW_EVENT_MASK, values); xcb_icccm_set_wm_class(dpy, m->root, sizeof(ROOT_WINDOW_IC), ROOT_WINDOW_IC); window_lower(m->root); if (focus_follows_pointer) { window_show(m->root); } } else { window_move_resize(m->root, rect->x, rect->y, rect->width, rect->height); put_status(SBSC_MASK_MONITOR_GEOMETRY, "monitor_geometry 0x%08X %ux%u+%i+%i\n", m->id, rect->width, rect->height, rect->x, rect->y); } for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) { if (n->client == NULL) { continue; } adapt_geometry(&last_rect, rect, n); } arrange(m, d); } }
void hide_desktop(desktop_t *d) { if (!visible) return; for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) window_hide(n->client->window); }
bool is_urgent(desktop_t *d) { for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) if (n->client->urgent) return true; return false; }
void transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d) { if (ms == md) return; desktop_t *dd = ms->desk; unlink_desktop(ms, d); insert_desktop(md, d); if (d == dd) { if (ms->desk != NULL) show_desktop(ms->desk); if (md->desk != d) hide_desktop(d); } for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) translate_client(ms, md, n->client); arrange(md, d); if (d != dd && md->desk == d) show_desktop(d); history_transfer_desktop(md, d); ewmh_update_wm_desktops(); ewmh_update_desktop_names(); ewmh_update_current_desktop(); put_status(); }
void ewmh_update_client_list(bool stacking) { if (clients_count == 0) { xcb_ewmh_set_client_list(ewmh, default_screen, 0, NULL); xcb_ewmh_set_client_list_stacking(ewmh, default_screen, 0, NULL); return; } xcb_window_t wins[clients_count]; unsigned int i = 0; if (stacking) { for (stacking_list_t *s = stack_head; s != NULL; s = s->next) { wins[i++] = s->node->id; } xcb_ewmh_set_client_list_stacking(ewmh, default_screen, clients_count, wins); } else { for (monitor_t *m = mon_head; m != NULL; m = m->next) { for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) { if (n->client == NULL) { continue; } wins[i++] = n->id; } } } xcb_ewmh_set_client_list(ewmh, default_screen, clients_count, wins); } }
node_t *first_extrema(node_t *n) { if (n == NULL) return NULL; else if (n->first_child == NULL) return n; else return first_extrema(n->first_child); }
void ewmh_update_wm_desktops(void) { for (monitor_t *m = mon_head; m != NULL; m = m->next) for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { uint32_t i = ewmh_get_desktop_index(d); for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) xcb_ewmh_set_wm_desktop(ewmh, n->client->window, i); } }
void ewmh_set_wm_desktop(node_t *n, desktop_t *d) { uint32_t i = ewmh_get_desktop_index(d); for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) { if (f->client == NULL) { continue; } xcb_ewmh_set_wm_desktop(ewmh, f->id, i); } }
void ungrab_buttons(void) { for (monitor_t *m = mon_head; m != NULL; m = m->next) { for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) { xcb_ungrab_button(dpy, XCB_BUTTON_INDEX_ANY, n->id, XCB_MOD_MASK_ANY); } } } }
void merge_desktops(monitor_t *ms, desktop_t *ds, monitor_t *md, desktop_t *dd) { if (ds == NULL || dd == NULL || ds == dd) return; node_t *n = first_extrema(ds->root); while (n != NULL) { node_t *next = next_leaf(n, ds->root); transfer_node(ms, ds, n, md, dd, dd->focus); n = next; } }
node_t *next_leaf(node_t *n) { if (n == NULL) return NULL; node_t *p = n; while (is_second_child(p)) p = p->parent; if (p->parent == NULL) return NULL; return first_extrema(p->parent->second_child); }
bool is_urgent(desktop_t *d) { for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) { if (n->client == NULL) { continue; } if (n->client->urgent) { return true; } } return false; }
void window_kill(monitor_t *m, desktop_t *d, node_t *n) { if (n == NULL) { return; } for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) { xcb_kill_client(dpy, f->id); } remove_node(m, d, n); }
void unlink_node(desktop_t *d, node_t *n) { if (d == NULL || n == NULL) return; PRINTF("unlink node %X\n", n->client->window); node_t *p = n->parent; if (p == NULL) { d->root = NULL; d->focus = NULL; d->last_focus = NULL; } else { node_t *b; node_t *g = p->parent; bool n_first_child = is_first_child(n); if (n_first_child) { b = p->second_child; if (n->client->born_as == MODE_AUTOMATIC) rotate_tree(b, ROTATE_COUNTER_CLOCKWISE); } else { b = p->first_child; if (n->client->born_as == MODE_AUTOMATIC) rotate_tree(b, ROTATE_CLOCKWISE); } b->parent = g; if (g != NULL) { if (is_first_child(p)) g->first_child = b; else g->second_child = b; } else { d->root = b; } n->parent = NULL; free(p); if (n == d->last_focus) { d->last_focus = NULL; } else if (n == d->focus) { if (d->last_focus != NULL) d->focus = d->last_focus; else d->focus = (n_first_child ? first_extrema(b) : second_extrema(b)); d->last_focus = NULL; } update_vacant_state(b->parent); } }
void draw_border(node_t *n, bool focused_node, bool focused_monitor) { if (n == NULL) { return; } uint32_t border_color_pxl = get_border_color(focused_node, focused_monitor); for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) { if (f->client->border_width > 0) { window_draw_border(f->id, border_color_pxl); } } }
void grab_buttons(void) { for (monitor_t *m = mon_head; m != NULL; m = m->next) { for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) { window_grab_buttons(n->id); if (n->presel != NULL) { window_grab_buttons(n->presel->feedback); } } } } }
node_t *find_neighbor(node_t *n, direction_t dir) { node_t *fence = find_fence(n, dir); if (fence == NULL) return NULL; if (dir == DIR_UP || dir == DIR_LEFT) return second_extrema(fence->first_child); else if (dir == DIR_DOWN || dir == DIR_RIGHT) return first_extrema(fence->second_child); return NULL; }
void cycle_leaf(monitor_t *m, desktop_t *d, node_t *n, cycle_dir_t dir, skip_client_t skip) { if (n == NULL) return; PUTS("cycle leaf"); node_t *f = (dir == CYCLE_PREV ? prev_leaf(n) : next_leaf(n)); if (f == NULL) f = (dir == CYCLE_PREV ? second_extrema(d->root) : first_extrema(d->root)); while (f != n) { bool tiled = is_tiled(f->client); if (skip == CLIENT_SKIP_NONE || (skip == CLIENT_SKIP_TILED && !tiled) || (skip == CLIENT_SKIP_FLOATING && tiled) || (skip == CLIENT_SKIP_CLASS_DIFFER && strcmp(f->client->class_name, n->client->class_name) == 0) || (skip == CLIENT_SKIP_CLASS_EQUAL && strcmp(f->client->class_name, n->client->class_name) != 0)) { focus_node(m, d, f, true); return; } f = (dir == CYCLE_PREV ? prev_leaf(f) : next_leaf(f)); if (f == NULL) f = (dir == CYCLE_PREV ? second_extrema(d->root) : first_extrema(d->root)); } }
void circulate_leaves(monitor_t *m, desktop_t *d, circulate_dir_t dir) { if (d == NULL || d->root == NULL || is_leaf(d->root)) return; node_t *par = d->focus->parent; bool focus_first_child = is_first_child(d->focus); if (dir == CIRCULATE_FORWARD) for (node_t *s = second_extrema(d->root), *f = prev_leaf(s); f != NULL; s = prev_leaf(f), f = prev_leaf(s)) swap_nodes(f, s); else for (node_t *f = first_extrema(d->root), *s = next_leaf(f); s != NULL; f = next_leaf(s), s = next_leaf(f)) swap_nodes(f, s); if (focus_first_child) focus_node(m, d, par->first_child, true); else focus_node(m, d, par->second_child, true); }
void put_status(void) { if (status_fifo == NULL) return; bool urgent = false; for (monitor_t *m = mon_head; m != NULL; m = m->next) { fprintf(status_fifo, "%c%s:", (mon == m ? 'M' : 'm'), m->name); for (desktop_t *d = m->desk_head; d != NULL; d = d->next, urgent = false) { for (node_t *n = first_extrema(d->root); n != NULL && !urgent; n = next_leaf(n)) urgent |= n->client->urgent; fprintf(status_fifo, "%c%c%s:", (m->desk == d ? 'D' : (d->root != NULL ? 'd' : '_')), (urgent ? '!' : '_'), d->name); } } fprintf(status_fifo, "L%s:W%X\n", (mon->desk->layout == LAYOUT_TILED ? "tiled" : "monocle"), (mon->desk->focus == NULL ? 0 : mon->desk->focus->client->window)); fflush(status_fifo); }
bool remove_tag_by_index(int i) { if (i >= num_tags) return false; for (monitor_t *m = mon_head; m != NULL; m = m->next) for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { tag_desktop(m, d, d->tags_field & ~tags[i]->mask); for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) tag_node(m, d, n, d, n->client->tags_field & ~tags[i]->mask); } free(tags[i]); for (int j = i; j < (num_tags - 1); j++) tags[j] = tags[j + 1]; tags[num_tags - 1] = NULL; num_tags--; return true; }
int print_status(FILE *stream) { fprintf(stream, "%s", status_prefix); bool urgent = false; for (monitor_t *m = mon_head; m != NULL; m = m->next) { fprintf(stream, "%c%s:", (mon == m ? 'M' : 'm'), m->name); for (desktop_t *d = m->desk_head; d != NULL; d = d->next, urgent = false) { for (node_t *n = first_extrema(d->root); n != NULL && !urgent; n = next_leaf(n, d->root)) urgent |= n->client->urgent; char c = (urgent ? 'u' : (d->root == NULL ? 'f' : 'o')); if (m->desk == d) c = toupper(c); fprintf(stream, "%c%s:", c, d->name); } if (m->desk != NULL) fprintf(stream, "L%c%s", (m->desk->layout == LAYOUT_TILED ? 'T' : 'M'), (m != mon_tail ? ":" : "")); } fprintf(stream, "%s", "\n"); return fflush(stream); }
void tag_desktop(monitor_t *m, desktop_t *d, unsigned int tags_field) { if (num_tags < 1) return; bool dirty = false; unsigned int old_tags_field = d->tags_field; d->tags_field = tags_field; for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) { bool old_visible = (old_tags_field & n->client->tags_field) != 0; bool visible = (tags_field & n->client->tags_field) != 0; if (old_visible != visible) { set_visibility(m, d, n, visible); dirty = true; } } if (dirty) arrange(m, d); if (d == mon->desk) put_status(); }
void ewmh_update_client_list(void) { if (num_clients == 0) { xcb_ewmh_set_client_list(ewmh, default_screen, 0, NULL); xcb_ewmh_set_client_list_stacking(ewmh, default_screen, 0, NULL); return; } xcb_window_t wins[num_clients]; unsigned int i = 0; for (monitor_t *m = mon_head; m != NULL; m = m->next) for (desktop_t *d = m->desk_head; d != NULL; d = d->next) for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) wins[i++] = n->client->window; if (i != num_clients) return; xcb_ewmh_set_client_list(ewmh, default_screen, num_clients, wins); xcb_ewmh_set_client_list_stacking(ewmh, default_screen, num_clients, wins); }
void adapt_geometry(xcb_rectangle_t *rs, xcb_rectangle_t *rd, node_t *n) { if (frozen_pointer->action != ACTION_NONE) { return; } for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) { client_t *c = f->client; /* Clip the rectangle to fit into the monitor. Without this, the fitting * algorithm doesn't work as expected. This also conserves the * out-of-bounds regions */ int left_adjust = MAX((rs->x - c->floating_rectangle.x), 0); int top_adjust = MAX((rs->y - c->floating_rectangle.y), 0); int right_adjust = MAX((c->floating_rectangle.x + c->floating_rectangle.width) - (rs->x + rs->width), 0); int bottom_adjust = MAX((c->floating_rectangle.y + c->floating_rectangle.height) - (rs->y + rs->height), 0); c->floating_rectangle.x += left_adjust; c->floating_rectangle.y += top_adjust; c->floating_rectangle.width -= (left_adjust + right_adjust); c->floating_rectangle.height -= (top_adjust + bottom_adjust); int dx_s = c->floating_rectangle.x - rs->x; int dy_s = c->floating_rectangle.y - rs->y; int nume_x = dx_s * (rd->width - c->floating_rectangle.width); int nume_y = dy_s * (rd->height - c->floating_rectangle.height); int deno_x = rs->width - c->floating_rectangle.width; int deno_y = rs->height - c->floating_rectangle.height; int dx_d = (deno_x == 0 ? 0 : nume_x / deno_x); int dy_d = (deno_y == 0 ? 0 : nume_y / deno_y); /* Translate and undo clipping */ c->floating_rectangle.width += left_adjust + right_adjust; c->floating_rectangle.height += top_adjust + bottom_adjust; c->floating_rectangle.x = rd->x + dx_d - left_adjust; c->floating_rectangle.y = rd->y + dy_d - top_adjust; } }
void nearest_leaf(monitor_t *m, desktop_t *d, node_t *n, nearest_arg_t dir, skip_client_t skip) { if (n == NULL) return; PUTS("nearest leaf"); node_t *x = NULL; for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f)) if (skip == CLIENT_SKIP_NONE || (skip == CLIENT_SKIP_TILED && !is_tiled(f->client)) || (skip == CLIENT_SKIP_FLOATING && is_tiled(f->client)) || (skip == CLIENT_SKIP_CLASS_DIFFER && strcmp(f->client->class_name, n->client->class_name) == 0) || (skip == CLIENT_SKIP_CLASS_EQUAL && strcmp(f->client->class_name, n->client->class_name) != 0)) if ((dir == NEAREST_OLDER && (f->client->uid < n->client->uid) && (x == NULL || f->client->uid > x->client->uid)) || (dir == NEAREST_NEWER && (f->client->uid > n->client->uid) && (x == NULL || f->client->uid < x->client->uid))) x = f; focus_node(m, d, x, true); }
void swap_desktops(monitor_t *m1, desktop_t *d1, monitor_t *m2, desktop_t *d2) { if (d1 == NULL || d2 == NULL || d1 == d2) return; PRINTF("swap desktops %s %s\n", d1->name, d2->name); bool d1_focused = (m1->desk == d1); bool d2_focused = (m2->desk == d2); if (m1 != m2) { if (m1->desk == d1) m1->desk = d2; if (m1->desk_head == d1) m1->desk_head = d2; if (m1->desk_tail == d1) m1->desk_tail = d2; if (m2->desk == d2) m2->desk = d1; if (m2->desk_head == d2) m2->desk_head = d1; if (m2->desk_tail == d2) m2->desk_tail = d1; } else { if (m1->desk_head == d1) m1->desk_head = d2; else if (m1->desk_head == d2) m1->desk_head = d1; if (m1->desk_tail == d1) m1->desk_tail = d2; else if (m1->desk_tail == d2) m1->desk_tail = d1; } desktop_t *p1 = d1->prev; desktop_t *n1 = d1->next; desktop_t *p2 = d2->prev; desktop_t *n2 = d2->next; if (p1 != NULL && p1 != d2) p1->next = d2; if (n1 != NULL && n1 != d2) n1->prev = d2; if (p2 != NULL && p2 != d1) p2->next = d1; if (n2 != NULL && n2 != d1) n2->prev = d1; d1->prev = p2 == d1 ? d2 : p2; d1->next = n2 == d1 ? d2 : n2; d2->prev = p1 == d2 ? d1 : p1; d2->next = n1 == d2 ? d1 : n1; if (m1 != m2) { for (node_t *n = first_extrema(d1->root); n != NULL; n = next_leaf(n, d1->root)) translate_client(m1, m2, n->client); for (node_t *n = first_extrema(d2->root); n != NULL; n = next_leaf(n, d2->root)) translate_client(m2, m1, n->client); history_swap_desktops(m1, d1, m2, d2); arrange(m1, d2); arrange(m2, d1); if (d1_focused && !d2_focused) { hide_desktop(d1); show_desktop(d2); } else if (!d1_focused && d2_focused) { show_desktop(d1); hide_desktop(d2); } } update_input_focus(); ewmh_update_wm_desktops(); ewmh_update_desktop_names(); ewmh_update_current_desktop(); put_status(); }
void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos) { node_t *n = loc.node; resize_handle_t rh = get_handle(loc.node, pos, pac); uint16_t last_motion_x = pos.x, last_motion_y = pos.y; xcb_timestamp_t last_motion_time = 0; xcb_generic_event_t *evt = NULL; grabbing = true; grabbed_node = n; do { free(evt); while ((evt = xcb_wait_for_event(dpy)) == NULL) { xcb_flush(dpy); } uint8_t resp_type = XCB_EVENT_RESPONSE_TYPE(evt); if (resp_type == XCB_MOTION_NOTIFY) { xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t*) evt; uint32_t dtime = e->time - last_motion_time; if (dtime < pointer_motion_interval) { continue; } last_motion_time = e->time; int16_t dx = e->root_x - last_motion_x; int16_t dy = e->root_y - last_motion_y; if (pac == ACTION_MOVE) { move_client(&loc, dx, dy); } else { resize_client(&loc, rh, e->root_x, e->root_y, false); } last_motion_x = e->root_x; last_motion_y = e->root_y; xcb_flush(dpy); } else if (resp_type == XCB_BUTTON_RELEASE) { grabbing = false; } else { handle_event(evt); } } while (grabbing && grabbed_node != NULL); free(evt); xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); if (grabbed_node == NULL) { grabbing = false; return; } if (pac == ACTION_MOVE) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X move end\n", loc.monitor->id, loc.desktop->id, n->id); } else if (pac == ACTION_RESIZE_CORNER) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_corner end\n", loc.monitor->id, loc.desktop->id, n->id); } else if (pac == ACTION_RESIZE_SIDE) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_side end\n", loc.monitor->id, loc.desktop->id, n->id); } xcb_rectangle_t r = get_rectangle(NULL, NULL, n); put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, loc.node->id, r.width, r.height, r.x, r.y); if ((pac == ACTION_MOVE && IS_TILED(n->client)) || ((pac == ACTION_RESIZE_CORNER || pac == ACTION_RESIZE_SIDE) && n->client->state == STATE_TILED)) { for (node_t *f = first_extrema(loc.desktop->root); f != NULL; f = next_leaf(f, loc.desktop->root)) { if (f == n || f->client == NULL || !IS_TILED(f->client)) { continue; } xcb_rectangle_t r = f->client->tiled_rectangle; put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, f->id, r.width, r.height, r.x, r.y); } } }
bool import_monitors(void) { PUTS("import monitors"); xcb_randr_get_screen_resources_current_reply_t *sres = xcb_randr_get_screen_resources_current_reply(dpy, xcb_randr_get_screen_resources_current(dpy, root), NULL); if (sres == NULL) return false; monitor_t *m, *mm = NULL; int len = xcb_randr_get_screen_resources_current_outputs_length(sres); xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(sres); xcb_randr_get_output_info_cookie_t cookies[len]; for (int i = 0; i < len; i++) cookies[i] = xcb_randr_get_output_info(dpy, outputs[i], XCB_CURRENT_TIME); for (m = mon_head; m != NULL; m = m->next) m->wired = false; for (int i = 0; i < len; i++) { xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(dpy, cookies[i], NULL); if (info != NULL) { if (info->crtc != XCB_NONE) { xcb_randr_get_crtc_info_reply_t *cir = xcb_randr_get_crtc_info_reply(dpy, xcb_randr_get_crtc_info(dpy, info->crtc, XCB_CURRENT_TIME), NULL); if (cir != NULL) { xcb_rectangle_t rect = (xcb_rectangle_t) {cir->x, cir->y, cir->width, cir->height}; mm = get_monitor_by_id(outputs[i]); if (mm != NULL) { mm->rectangle = rect; update_root(mm); for (desktop_t *d = mm->desk_head; d != NULL; d = d->next) for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) translate_client(mm, mm, n->client); arrange(mm, mm->desk); mm->wired = true; PRINTF("update monitor %s (0x%X)\n", mm->name, mm->id); } else { mm = add_monitor(rect); char *name = (char *)xcb_randr_get_output_info_name(info); size_t name_len = MIN(sizeof(mm->name), (size_t)xcb_randr_get_output_info_name_length(info) + 1); snprintf(mm->name, name_len, "%s", name); mm->id = outputs[i]; PRINTF("add monitor %s (0x%X)\n", mm->name, mm->id); } } free(cir); } else if (!remove_disabled_monitor && info->connection != XCB_RANDR_CONNECTION_DISCONNECTED) { m = get_monitor_by_id(outputs[i]); if (m != NULL) m->wired = true; } } free(info); } /* initially focus the primary monitor and add the first desktop to it */ xcb_randr_get_output_primary_reply_t *gpo = xcb_randr_get_output_primary_reply(dpy, xcb_randr_get_output_primary(dpy, root), NULL); if (gpo != NULL) { pri_mon = get_monitor_by_id(gpo->output); if (!running && pri_mon != NULL) { if (mon != pri_mon) mon = pri_mon; add_desktop(pri_mon, make_desktop(NULL)); ewmh_update_current_desktop(); } } free(gpo); /* handle overlapping monitors */ m = mon_head; while (m != NULL) { monitor_t *next = m->next; if (m->wired) { for (monitor_t *mb = mon_head; mb != NULL; mb = mb->next) if (mb != m && mb->wired && (m->desk == NULL || mb->desk == NULL) && contains(mb->rectangle, m->rectangle)) { if (mm == m) mm = mb; merge_monitors(m, mb); remove_monitor(m); break; } } m = next; } /* merge and remove disconnected monitors */ m = mon_head; while (m != NULL) { monitor_t *next = m->next; if (!m->wired) { merge_monitors(m, mm); remove_monitor(m); } m = next; } /* add one desktop to each new monitor */ for (m = mon_head; m != NULL; m = m->next) if (m->desk == NULL && (running || pri_mon == NULL || m != pri_mon)) add_desktop(m, make_desktop(NULL)); free(sres); update_motion_recorder(); return (num_monitors > 0); }