Exemple #1
0
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();
}
Exemple #2
0
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);
	}
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
0
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();
}
Exemple #6
0
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);
	}
}
Exemple #7
0
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);
}
Exemple #8
0
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);
        }
}
Exemple #9
0
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);
	}
}
Exemple #10
0
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);
			}
		}
	}
}
Exemple #11
0
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;
	}
}
Exemple #12
0
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);
}
Exemple #13
0
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;
}
Exemple #14
0
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);
}
Exemple #15
0
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);
    }
}
Exemple #16
0
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);
		}
	}
}
Exemple #17
0
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);
				}
			}
		}
	}
}
Exemple #18
0
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;
}
Exemple #19
0
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));
    }
}
Exemple #20
0
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);
}
Exemple #21
0
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);
}
Exemple #22
0
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;
}
Exemple #23
0
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);
}
Exemple #24
0
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();
}
Exemple #25
0
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);
}
Exemple #26
0
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;
	}
}
Exemple #27
0
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);
}
Exemple #28
0
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();
}
Exemple #29
0
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);
		}
	}
}
Exemple #30
0
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);
}