-/* Copyright (c) 2012-2014, Bastien Dejean
+/* Copyright (c) 2012, Bastien Dejean
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies,
- * either expressed or implied, of the FreeBSD Project.
*/
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
#include "bspwm.h"
#include "desktop.h"
#include "ewmh.h"
#include "history.h"
#include "query.h"
#include "settings.h"
+#include "geometry.h"
#include "tree.h"
+#include "subscribe.h"
#include "window.h"
#include "monitor.h"
-monitor_t *make_monitor(xcb_rectangle_t rect)
+monitor_t *make_monitor(xcb_rectangle_t *rect, uint32_t id)
{
monitor_t *m = malloc(sizeof(monitor_t));
- snprintf(m->name, sizeof(m->name), "%s%02d", DEFAULT_MON_NAME, ++monitor_uid);
+ if (id == XCB_NONE) {
+ m->id = xcb_generate_id(dpy);
+ }
+ m->randr_id = XCB_NONE;
+ snprintf(m->name, sizeof(m->name), "%s", DEFAULT_MON_NAME);
+ m->padding = padding;
+ m->border_width = border_width;
+ m->window_gap = window_gap;
+ m->root = XCB_NONE;
m->prev = m->next = NULL;
m->desk = m->desk_head = m->desk_tail = NULL;
- m->rectangle = rect;
- m->top_padding = m->right_padding = m->bottom_padding = m->left_padding = 0;
m->wired = true;
- m->num_sticky = 0;
- uint32_t mask = XCB_CW_EVENT_MASK;
- 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, mask, values);
- window_lower(m->root);
- if (focus_follows_pointer)
- window_show(m->root);
+ m->sticky_count = 0;
+ if (rect != NULL) {
+ update_root(m, rect);
+ } else {
+ m->rectangle = (xcb_rectangle_t) {0, 0, screen_width, screen_height};
+ }
return m;
}
+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 rename_monitor(monitor_t *m, const char *name)
+{
+ put_status(SBSC_MASK_MONITOR_RENAME, "monitor_rename 0x%08X %s %s\n", m->id, m->name, name);
+
+ snprintf(m->name, sizeof(m->name), "%s", name);
+
+ put_status(SBSC_MASK_REPORT);
+}
+
monitor_t *find_monitor(char *name)
{
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- if (streq(m->name, name))
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ if (streq(m->name, name)) {
return m;
+ }
+ }
return NULL;
}
-monitor_t *get_monitor_by_id(xcb_randr_output_t id)
+monitor_t *get_monitor_by_randr_id(xcb_randr_output_t id)
{
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- if (m->id == id)
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ if (m->randr_id == id) {
return m;
+ }
+ }
return NULL;
}
void embrace_client(monitor_t *m, client_t *c)
{
- if ((c->floating_rectangle.x + c->floating_rectangle.width) <= m->rectangle.x)
+ if ((c->floating_rectangle.x + c->floating_rectangle.width) <= m->rectangle.x) {
c->floating_rectangle.x = m->rectangle.x;
- else if (c->floating_rectangle.x >= (m->rectangle.x + m->rectangle.width))
+ } else if (c->floating_rectangle.x >= (m->rectangle.x + m->rectangle.width)) {
c->floating_rectangle.x = (m->rectangle.x + m->rectangle.width) - c->floating_rectangle.width;
- if ((c->floating_rectangle.y + c->floating_rectangle.height) <= m->rectangle.y)
+ }
+ if ((c->floating_rectangle.y + c->floating_rectangle.height) <= m->rectangle.y) {
c->floating_rectangle.y = m->rectangle.y;
- else if (c->floating_rectangle.y >= (m->rectangle.y + m->rectangle.height))
+ } else if (c->floating_rectangle.y >= (m->rectangle.y + m->rectangle.height)) {
c->floating_rectangle.y = (m->rectangle.y + m->rectangle.height) - c->floating_rectangle.height;
+ }
}
-void translate_client(monitor_t *ms, monitor_t *md, client_t *c)
-{
- if (frozen_pointer->action != ACTION_NONE || ms == md)
- return;
-
- /* 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((ms->rectangle.x - c->floating_rectangle.x), 0);
- int top_adjust = MAX((ms->rectangle.y - c->floating_rectangle.y), 0);
- int right_adjust = MAX((c->floating_rectangle.x + c->floating_rectangle.width) - (ms->rectangle.x + ms->rectangle.width), 0);
- int bottom_adjust = MAX((c->floating_rectangle.y + c->floating_rectangle.height) - (ms->rectangle.y + ms->rectangle.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 - ms->rectangle.x;
- int dy_s = c->floating_rectangle.y - ms->rectangle.y;
-
- int nume_x = dx_s * (md->rectangle.width - c->floating_rectangle.width);
- int nume_y = dy_s * (md->rectangle.height - c->floating_rectangle.height);
-
- int deno_x = ms->rectangle.width - c->floating_rectangle.width;
- int deno_y = ms->rectangle.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 = md->rectangle.x + dx_d - left_adjust;
- c->floating_rectangle.y = md->rectangle.y + dy_d - top_adjust;
-}
-
-void update_root(monitor_t *m)
+void adapt_geometry(xcb_rectangle_t *rs, xcb_rectangle_t *rd, node_t *n)
{
- xcb_rectangle_t rect = m->rectangle;
- window_move_resize(m->root, rect.x, rect.y, rect.width, rect.height);
+ for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) {
+ if (f->client == NULL) {
+ continue;
+ }
+ 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 focus_monitor(monitor_t *m)
{
- if (mon == m)
+ if (mon == m) {
return;
-
- PRINTF("focus monitor %s\n", m->name);
+ }
mon = m;
- if (pointer_follows_monitor)
- center_pointer(m);
+ if (pointer_follows_monitor) {
+ xcb_point_t pt;
+ query_pointer(NULL, &pt);
+ monitor_t *mp = monitor_from_point(pt);
+ if (mp != m) {
+ center_pointer(m->rectangle);
+ }
+ }
- ewmh_update_current_desktop();
- put_status();
+ put_status(SBSC_MASK_MONITOR_FOCUS, "monitor_focus 0x%08X\n", m->id);
}
-monitor_t *add_monitor(xcb_rectangle_t rect)
+void add_monitor(monitor_t *m)
{
- monitor_t *m = make_monitor(rect);
+ xcb_rectangle_t r = m->rectangle;
+
if (mon == NULL) {
mon = m;
mon_head = m;
mon_tail = m;
} else {
- mon_tail->next = m;
- m->prev = mon_tail;
- mon_tail = m;
+ monitor_t *a = mon_head;
+ while (a != NULL && rect_cmp(m->rectangle, a->rectangle) > 0) {
+ a = a->next;
+ }
+ if (a != NULL) {
+ monitor_t *b = a->prev;
+ if (b != NULL) {
+ b->next = m;
+ } else {
+ mon_head = m;
+ }
+ m->prev = b;
+ m->next = a;
+ a->prev = m;
+ } else {
+ mon_tail->next = m;
+ m->prev = mon_tail;
+ mon_tail = m;
+ }
}
- num_monitors++;
- return m;
+
+ put_status(SBSC_MASK_MONITOR_ADD, "monitor_add 0x%08X %s %ux%u+%i+%i\n", m->id, m->name, r.width, r.height, r.x, r.y);
+
+ put_status(SBSC_MASK_REPORT);
}
void remove_monitor(monitor_t *m)
{
- PRINTF("remove monitor %s (0x%X)\n", m->name, m->id);
-
- while (m->desk_head != NULL)
+ while (m->desk_head != NULL) {
remove_desktop(m, m->desk_head);
+ }
+
monitor_t *prev = m->prev;
monitor_t *next = m->next;
- monitor_t *last_mon = history_get_monitor(m);
- if (prev != NULL)
+ monitor_t *last_mon = history_last_monitor(m);
+
+ if (prev != NULL) {
prev->next = next;
- if (next != NULL)
+ }
+
+ if (next != NULL) {
next->prev = prev;
- if (mon_head == m)
+ }
+
+ if (mon_head == m) {
mon_head = next;
- if (mon_tail == m)
+ }
+
+ if (mon_tail == m) {
mon_tail = prev;
- if (pri_mon == m)
+ }
+
+ if (pri_mon == m) {
pri_mon = NULL;
+ }
+
if (mon == m) {
mon = (last_mon == NULL ? (prev == NULL ? next : prev) : last_mon);
- if (mon != NULL && mon->desk != NULL)
- update_current();
+ if (mon != NULL && mon->desk != NULL) {
+ update_focused();
+ }
}
+
+ put_status(SBSC_MASK_MONITOR_REMOVE, "monitor_remove 0x%08X\n", m->id);
+
xcb_destroy_window(dpy, m->root);
free(m);
- num_monitors--;
- put_status();
+
+ put_status(SBSC_MASK_REPORT);
}
void merge_monitors(monitor_t *ms, monitor_t *md)
{
- PRINTF("merge %s into %s\n", ms->name, md->name);
+ if (ms == NULL || md == NULL || ms == md) {
+ return;
+ }
desktop_t *d = ms->desk_head;
while (d != NULL) {
desktop_t *next = d->next;
- if (d->root != NULL || strstr(d->name, DEFAULT_DESK_NAME) == NULL)
+ if (d->root != NULL || strstr(d->name, DEFAULT_DESK_NAME) == NULL) {
transfer_desktop(ms, md, d);
+ }
d = next;
}
}
-void swap_monitors(monitor_t *m1, monitor_t *m2)
+bool swap_monitors(monitor_t *m1, monitor_t *m2)
{
- if (m1 == NULL || m2 == NULL || m1 == m2)
- return;
+ if (m1 == NULL || m2 == NULL || m1 == m2) {
+ return false;
+ }
+
+ put_status(SBSC_MASK_MONITOR_SWAP, "monitor_swap 0x%08X 0x%08X\n", m1->id, m2->id);
- if (mon_head == m1)
+ if (mon_head == m1) {
mon_head = m2;
- else if (mon_head == m2)
+ } else if (mon_head == m2) {
mon_head = m1;
- if (mon_tail == m1)
+ }
+ if (mon_tail == m1) {
mon_tail = m2;
- else if (mon_tail == m2)
+ } else if (mon_tail == m2) {
mon_tail = m1;
+ }
monitor_t *p1 = m1->prev;
monitor_t *n1 = m1->next;
monitor_t *p2 = m2->prev;
monitor_t *n2 = m2->next;
- if (p1 != NULL && p1 != m2)
+ if (p1 != NULL && p1 != m2) {
p1->next = m2;
- if (n1 != NULL && n1 != m2)
+ }
+ if (n1 != NULL && n1 != m2) {
n1->prev = m2;
- if (p2 != NULL && p2 != m1)
+ }
+ if (p2 != NULL && p2 != m1) {
p2->next = m1;
- if (n2 != NULL && n2 != m1)
+ }
+ if (n2 != NULL && n2 != m1) {
n2->prev = m1;
+ }
m1->prev = p2 == m1 ? m2 : p2;
m1->next = n2 == m1 ? m2 : n2;
ewmh_update_wm_desktops();
ewmh_update_desktop_names();
ewmh_update_current_desktop();
- put_status();
+
+ put_status(SBSC_MASK_REPORT);
+ return true;
}
-monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, desktop_select_t sel)
+monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, monitor_select_t sel)
{
monitor_t *f = (dir == CYCLE_PREV ? m->prev : m->next);
- if (f == NULL)
+
+ if (f == NULL) {
f = (dir == CYCLE_PREV ? mon_tail : mon_head);
+ }
while (f != m) {
- coordinates_t loc = {m, m->desk, NULL};
- if (desktop_matches(&loc, &loc, sel))
+ coordinates_t loc = {m, NULL, NULL};
+ if (monitor_matches(&loc, &loc, sel)) {
return f;
+ }
f = (dir == CYCLE_PREV ? m->prev : m->next);
- if (f == NULL)
+ if (f == NULL) {
f = (dir == CYCLE_PREV ? mon_tail : mon_head);
+ }
}
return NULL;
bool is_inside_monitor(monitor_t *m, xcb_point_t pt)
{
- xcb_rectangle_t r = m->rectangle;
- return (r.x <= pt.x && pt.x < (r.x + r.width)
- && r.y <= pt.y && pt.y < (r.y + r.height));
+ return is_inside(pt, m->rectangle);
}
monitor_t *monitor_from_point(xcb_point_t pt)
{
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- if (is_inside_monitor(m, pt))
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ if (is_inside_monitor(m, pt)) {
return m;
+ }
+ }
return NULL;
}
monitor_t *monitor_from_client(client_t *c)
{
- xcb_point_t pt = {c->floating_rectangle.x, c->floating_rectangle.y};
+ int16_t xc = c->floating_rectangle.x + c->floating_rectangle.width/2;
+ int16_t yc = c->floating_rectangle.y + c->floating_rectangle.height/2;
+ xcb_point_t pt = {xc, yc};
monitor_t *nearest = monitor_from_point(pt);
if (nearest == NULL) {
- int x = (c->floating_rectangle.x + c->floating_rectangle.width) / 2;
- int y = (c->floating_rectangle.y + c->floating_rectangle.height) / 2;
int dmin = INT_MAX;
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
xcb_rectangle_t r = m->rectangle;
- int d = abs((r.x + r.width / 2) - x) + abs((r.y + r.height / 2) - y);
+ int d = abs((r.x + r.width / 2) - xc) + abs((r.y + r.height / 2) - yc);
if (d < dmin) {
dmin = d;
nearest = m;
return nearest;
}
-monitor_t *nearest_monitor(monitor_t *m, direction_t dir, desktop_select_t sel)
+monitor_t *nearest_monitor(monitor_t *m, direction_t dir, monitor_select_t sel)
{
int dmin = INT_MAX;
monitor_t *nearest = NULL;
xcb_rectangle_t rect = m->rectangle;
for (monitor_t *f = mon_head; f != NULL; f = f->next) {
- if (f == m)
+ if (f == m) {
continue;
- coordinates_t loc = {f, f->desk, NULL};
- if (!desktop_matches(&loc, &loc, sel))
+ }
+ coordinates_t loc = {f, NULL, NULL};
+ if (!monitor_matches(&loc, &loc, sel)) {
continue;
+ }
xcb_rectangle_t r = f->rectangle;
- if ((dir == DIR_LEFT && r.x < rect.x) ||
- (dir == DIR_RIGHT && r.x >= (rect.x + rect.width)) ||
- (dir == DIR_UP && r.y < rect.y) ||
- (dir == DIR_DOWN && r.y >= (rect.y + rect.height))) {
+ if ((dir == DIR_WEST && r.x < rect.x) ||
+ (dir == DIR_EAST && r.x >= (rect.x + rect.width)) ||
+ (dir == DIR_NORTH && r.y < rect.y) ||
+ (dir == DIR_SOUTH && r.y >= (rect.y + rect.height))) {
int d = abs((r.x + r.width / 2) - (rect.x + rect.width / 2)) +
abs((r.y + r.height / 2) - (rect.y + rect.height / 2));
if (d < dmin) {
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)
+ xcb_randr_get_screen_resources_reply_t *sres = xcb_randr_get_screen_resources_reply(dpy, xcb_randr_get_screen_resources(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);
+ int len = xcb_randr_get_screen_resources_outputs_length(sres);
+ xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(sres);
xcb_randr_get_output_info_cookie_t cookies[len];
- for (int i = 0; i < len; i++)
+ 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)
+ 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);
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]);
+ mm = get_monitor_by_randr_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);
+ update_root(mm, &rect);
mm->wired = true;
- PRINTF("update monitor %s (0x%X)\n", mm->name, mm->id);
} else {
- mm = add_monitor(rect);
+ mm = make_monitor(&rect, XCB_NONE);
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);
+ int len = xcb_randr_get_output_info_name_length(info);
+ size_t name_size = MIN(sizeof(mm->name), (size_t) len + 1);
+ snprintf(mm->name, name_size, "%s", name);
+ mm->randr_id = outputs[i];
+ add_monitor(mm);
}
}
free(cir);
- } else if (!remove_disabled_monitor && info->connection != XCB_RANDR_CONNECTION_DISCONNECTED) {
- m = get_monitor_by_id(outputs[i]);
- if (m != NULL)
+ } else if (!remove_disabled_monitors && info->connection != XCB_RANDR_CONNECTION_DISCONNECTED) {
+ m = get_monitor_by_randr_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();
- }
+ pri_mon = get_monitor_by_randr_id(gpo->output);
}
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;
+ 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;
}
- m = next;
}
/* merge and remove disconnected monitors */
}
/* 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));
+ for (m = mon_head; m != NULL; m = m->next) {
+ if (m->desk == NULL) {
+ add_desktop(m, make_desktop(NULL, XCB_NONE));
+ }
+ }
- if (!running && pri_mon != NULL && mon_head != pri_mon)
- swap_monitors(mon_head, pri_mon);
+ if (!running && mon != NULL) {
+ if (pri_mon != NULL) {
+ mon = pri_mon;
+ }
+ center_pointer(mon->rectangle);
+ ewmh_update_current_desktop();
+ }
free(sres);
update_motion_recorder();
- return (num_monitors > 0);
+
+ return (mon != NULL);
}