]> git.lizzy.rs Git - bspwm.git/blobdiff - monitor.c
Don't needlessly ungrab/grab the buttons
[bspwm.git] / monitor.c
index f11dbb470fce9b5b9ebaa46ea7b36ae6c4a432c1..5365dcc50cc5a93a669664b3bbe2047a69860efa 100644 (file)
--- a/monitor.c
+++ b/monitor.c
 #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 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);
+       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 %s %s\n", m->name, 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);
 
@@ -68,122 +105,141 @@ void rename_monitor(monitor_t *m, const char *name)
 
 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 r = m->rectangle;
-       window_move_resize(m->root, r.x, r.y, r.width, r.height);
-       put_status(SBSC_MASK_MONITOR_GEOMETRY, "monitor_geometry %s %ux%u+%i+%i\n", m->name, r.width, r.height, r.x, r.y);
+       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;
-
-       put_status(SBSC_MASK_MONITOR_FOCUS, "monitor_focus %s\n", m->name);
+       }
 
        mon = m;
 
        if (pointer_follows_monitor) {
-               center_pointer(m->rectangle);
+               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(SBSC_MASK_REPORT);
+       put_status(SBSC_MASK_MONITOR_FOCUS, "monitor_focus 0x%08X\n", m->id);
 }
 
 void add_monitor(monitor_t *m)
 {
        xcb_rectangle_t r = m->rectangle;
 
-       put_status(SBSC_MASK_MONITOR_ADD, "monitor_add %s 0x%X %ux%u+%i+%i\n", m->name, m->id, r.width, r.height, r.x, r.y);
-
        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++;
+       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)
 {
-       put_status(SBSC_MASK_MONITOR_REMOVE, "monitor_remove %s\n", m->name);
-
        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);
+       monitor_t *last_mon = history_last_monitor(m);
 
        if (prev != NULL) {
                prev->next = next;
@@ -208,13 +264,15 @@ void remove_monitor(monitor_t *m)
        if (mon == m) {
                mon = (last_mon == NULL ? (prev == NULL ? next : prev) : last_mon);
                if (mon != NULL && mon->desk != NULL) {
-                       update_current();
+                       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(SBSC_MASK_REPORT);
 }
 
@@ -227,39 +285,49 @@ void merge_monitors(monitor_t *ms, monitor_t *md)
        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;
+       }
 
-       if (mon_head == m1)
+       put_status(SBSC_MASK_MONITOR_SWAP, "monitor_swap 0x%08X 0x%08X\n", m1->id, m2->id);
+
+       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;
@@ -269,22 +337,28 @@ void swap_monitors(monitor_t *m1, monitor_t *m2)
        ewmh_update_wm_desktops();
        ewmh_update_desktop_names();
        ewmh_update_current_desktop();
+
        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;
@@ -292,9 +366,7 @@ monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, desktop_select_t sel)
 
 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)
@@ -309,15 +381,15 @@ monitor_t *monitor_from_point(xcb_point_t pt)
 
 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;
@@ -327,22 +399,24 @@ monitor_t *monitor_from_client(client_t *c)
        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) {
@@ -356,21 +430,24 @@ monitor_t *nearest_monitor(monitor_t *m, direction_t dir, desktop_select_t sel)
 
 bool update_monitors(void)
 {
-       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);
@@ -379,46 +456,34 @@ bool update_monitors(void)
                                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;
                                        } else {
-                                               mm = make_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];
+                                               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_monitors && info->connection != XCB_RANDR_CONNECTION_DISCONNECTED) {
-                               m = get_monitor_by_id(outputs[i]);
-                               if (m != NULL)
+                               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);
 
@@ -462,14 +527,22 @@ bool update_monitors(void)
        }
 
        /* 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);
 }