Example #1
0
void reorder_monitor(monitor_t *m)
{
	if (m == NULL) {
		return;
	}
	monitor_t *prev = m->prev;
	while (prev != NULL && rect_cmp(m->rectangle, prev->rectangle) < 0) {
		swap_monitors(m, prev);
		prev = m->prev;
	}
	monitor_t *next = m->next;
	while (next != NULL && rect_cmp(m->rectangle, next->rectangle) > 0) {
		swap_monitors(m, next);
		next = m->next;
	}
}
Example #2
0
bool update_monitors(void)
{
	PUTS("update 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_monitors && 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 */
	if (merge_overlapping_monitors) {
		m = mon_head;
		while (m != NULL) {
			monitor_t *next = m->next;
			if (m->wired) {
				monitor_t *mb = mon_head;
				while (mb != NULL) {
					monitor_t *mb_next = mb->next;
					if (m != mb && mb->wired && contains(m->rectangle, mb->rectangle)) {
						if (mm == mb) {
							mm = m;
						}
						if (next == mb) {
							next = mb_next;
						}
						merge_monitors(mb, m);
						remove_monitor(mb);
					}
					mb = mb_next;
				}
			}
			m = next;
		}
	}

	/* merge and remove disconnected monitors */
	if (remove_unplugged_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));

	if (!running && pri_mon != NULL && mon_head != pri_mon)
		swap_monitors(mon_head, pri_mon);

	free(sres);
	update_motion_recorder();
	return (num_monitors > 0);
}