예제 #1
0
파일: desktop.c 프로젝트: Iroxxar/bspwm
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();
}
예제 #2
0
파일: monitor.c 프로젝트: shellkr/bspwm
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);
}
예제 #3
0
파일: desktop.c 프로젝트: Iroxxar/bspwm
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();
}
예제 #4
0
파일: events.c 프로젝트: sg3des/bspwm
void configure_request(xcb_generic_event_t *evt)
{
	xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt;

	PRINTF("configure request %X\n", e->window);

	coordinates_t loc;
	bool is_managed = locate_window(e->window, &loc);
	client_t *c = (is_managed ? loc.node->client : NULL);
	int w = 0, h = 0;

	if (is_managed && !is_floating(c)) {
		if (e->value_mask & XCB_CONFIG_WINDOW_X)
			c->floating_rectangle.x = e->x;
		if (e->value_mask & XCB_CONFIG_WINDOW_Y)
			c->floating_rectangle.y = e->y;
		if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH)
			w = e->width;
		if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
			h = e->height;

		if (w != 0) {
			restrain_floating_width(c, &w);
			c->floating_rectangle.width = w;
		}

		if (h != 0) {
			restrain_floating_height(c, &h);
			c->floating_rectangle.height = h;
		}

		xcb_configure_notify_event_t evt;
		xcb_rectangle_t rect;
		xcb_window_t win = c->window;
		unsigned int bw = c->border_width;

		if (c->fullscreen)
			rect = loc.monitor->rectangle;
		else
			rect = c->tiled_rectangle;

		evt.response_type = XCB_CONFIGURE_NOTIFY;
		evt.event = win;
		evt.window = win;
		evt.above_sibling = XCB_NONE;
		evt.x = rect.x;
		evt.y = rect.y;
		evt.width = rect.width;
		evt.height = rect.height;
		evt.border_width = bw;
		evt.override_redirect = false;

		xcb_send_event(dpy, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt);

		if (c->pseudo_tiled)
			arrange(loc.monitor, loc.desktop);
	} else {
		uint16_t mask = 0;
		uint32_t values[7];
		unsigned short i = 0;

		if (e->value_mask & XCB_CONFIG_WINDOW_X) {
			mask |= XCB_CONFIG_WINDOW_X;
			values[i++] = e->x;
			if (is_managed)
				c->floating_rectangle.x = e->x;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
			mask |= XCB_CONFIG_WINDOW_Y;
			values[i++] = e->y;
			if (is_managed)
				c->floating_rectangle.y = e->y;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
			mask |= XCB_CONFIG_WINDOW_WIDTH;
			w = e->width;
			if (is_managed) {
				restrain_floating_width(c, &w);
				c->floating_rectangle.width = w;
			}
			values[i++] = w;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
			mask |= XCB_CONFIG_WINDOW_HEIGHT;
			h = e->height;
			if (is_managed) {
				restrain_floating_height(c, &h);
				c->floating_rectangle.height = h;
			}
			values[i++] = h;
		}

		if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) {
			mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
			values[i++] = e->border_width;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
			mask |= XCB_CONFIG_WINDOW_SIBLING;
			values[i++] = e->sibling;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
			mask |= XCB_CONFIG_WINDOW_STACK_MODE;
			values[i++] = e->stack_mode;
		}

		xcb_configure_window(dpy, e->window, mask, values);
	}

	if (is_managed)
		translate_client(monitor_from_client(c), loc.monitor, c);
}