]> git.sur5r.net Git - i3/i3/blobdiff - src/randr.c
Merge pull request #1816 from tcreech/tcreech-for-illumos
[i3/i3] / src / randr.c
index a4a0f6fd6d36fe7c626d836e7bc23d8c34573cdb..96f2f23368d7423415ff0904bfaa52dd8d5607b9 100644 (file)
@@ -4,7 +4,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * For more information on RandR, please see the X.org RandR specification at
  * http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt
@@ -69,7 +69,7 @@ Output *get_first_output(void) {
     if (output->active)
         return output;
 
-    die("No usable outputs available.\n");
+    return NULL;
 }
 
 /*
@@ -227,7 +227,7 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far
 void disable_randr(xcb_connection_t *conn) {
     DLOG("RandR extension unusable, disabling.\n");
 
-    Output *s = scalloc(sizeof(Output));
+    Output *s = scalloc(1, sizeof(Output));
 
     s->active = true;
     s->rect.x = 0;
@@ -292,7 +292,7 @@ void output_init_con(Output *output) {
     topdock->type = CT_DOCKAREA;
     topdock->layout = L_DOCKAREA;
     /* this container swallows dock clients */
-    Match *match = scalloc(sizeof(Match));
+    Match *match = scalloc(1, sizeof(Match));
     match_init(match);
     match->dock = M_DOCK_TOP;
     match->insert_where = M_BELOW;
@@ -326,7 +326,7 @@ void output_init_con(Output *output) {
     bottomdock->type = CT_DOCKAREA;
     bottomdock->layout = L_DOCKAREA;
     /* this container swallows dock clients */
-    match = scalloc(sizeof(Match));
+    match = scalloc(1, sizeof(Match));
     match_init(match);
     match->dock = M_DOCK_BOTTOM;
     match->insert_where = M_BELOW;
@@ -522,7 +522,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
     Output *new = get_output_by_id(id);
     bool existing = (new != NULL);
     if (!existing)
-        new = scalloc(sizeof(Output));
+        new = scalloc(1, sizeof(Output));
     new->id = id;
     new->primary = (primary && primary->output == id);
     FREE(new->name);
@@ -555,6 +555,12 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
         return;
     }
 
+    if (output->connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
+        DLOG("Disabling output %s: it is disconnected\n", new->name);
+        new->to_be_disabled = true;
+        return;
+    }
+
     bool updated = update_if_necessary(&(new->rect.x), crtc->x) |
                    update_if_necessary(&(new->rect.y), crtc->y) |
                    update_if_necessary(&(new->rect.width), crtc->width) |
@@ -564,6 +570,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
     if (!new->active) {
         DLOG("width/height 0/0, disabling output\n");
         return;
+    } else {
+        new->to_be_disabled = false;
     }
 
     DLOG("mode: %dx%d+%d+%d\n", new->rect.width, new->rect.height,
@@ -585,11 +593,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
     new->changed = true;
 }
 
-/*
- * (Re-)queries the outputs via RandR and stores them in the list of outputs.
- *
- */
-void randr_query_outputs(void) {
+static bool __randr_query_outputs(void) {
     Output *output, *other, *first;
     xcb_randr_get_output_primary_cookie_t pcookie;
     xcb_randr_get_screen_resources_current_cookie_t rcookie;
@@ -603,7 +607,7 @@ void randr_query_outputs(void) {
     xcb_randr_output_t *randr_outputs;
 
     if (randr_disabled)
-        return;
+        return true;
 
     /* Get screen resources (primary output, crtcs, outputs, modes) */
     rcookie = xcb_randr_get_screen_resources_current(conn, root);
@@ -615,7 +619,7 @@ void randr_query_outputs(void) {
         DLOG("primary output is %08x\n", primary->output);
     if ((res = xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL)) == NULL) {
         disable_randr(conn);
-        return;
+        return true;
     }
     cts = res->config_timestamp;
 
@@ -697,6 +701,11 @@ void randr_query_outputs(void) {
             DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name);
 
             first = get_first_output();
+            if (!first) {
+                FREE(res);
+                FREE(primary);
+                return false;
+            }
 
             /* TODO: refactor the following code into a nice function. maybe
              * use an on_destroy callback which is implement differently for
@@ -812,6 +821,32 @@ void randr_query_outputs(void) {
 
     FREE(res);
     FREE(primary);
+
+    return true;
+}
+
+/*
+ * (Re-)queries the outputs via RandR and stores them in the list of outputs.
+ *
+ */
+void randr_query_outputs(void) {
+    static bool first_query = true;
+
+    if (first_query) {
+        /* find monitors at least once via RandR */
+        if (!__randr_query_outputs())
+            die("No usable outputs available.\n");
+        first_query = false;
+    } else {
+        /* requery */
+        if (!__randr_query_outputs()) {
+            DLOG("sleep %f ms due to zero displays\n", config.zero_disp_exit_timer_ms);
+            usleep(config.zero_disp_exit_timer_ms * 1000);
+
+            if (!__randr_query_outputs())
+                die("No usable outputs available.\n");
+        }
+    }
 }
 
 /*