]> git.sur5r.net Git - i3/i3/commitdiff
Re-Implement support for RandR changes
authorMichael Stapelberg <michael@stapelberg.de>
Tue, 4 Jan 2011 23:16:10 +0000 (00:16 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Tue, 4 Jan 2011 23:16:10 +0000 (00:16 +0100)
include/data.h
include/handlers.h
include/randr.h
src/handlers.c
src/main.c
src/randr.c
src/tree.c
src/xinerama.c

index 6f4a47385c5f438de38f17c594369e0279f5a9a9..6174e4e427b90d82470be62cbec23464af06fbf5 100644 (file)
@@ -202,6 +202,7 @@ struct xoutput {
     /** x, y, width, height */
     Rect rect;
 
+#if 0
     /** The bar window */
     xcb_window_t bar;
     xcb_gcontext_t bargc;
@@ -209,6 +210,7 @@ struct xoutput {
     /** Contains all clients with _NET_WM_WINDOW_TYPE ==
      * _NET_WM_WINDOW_TYPE_DOCK */
     SLIST_HEAD(dock_clients_head, Client) dock_clients;
+#endif
 
     TAILQ_ENTRY(xoutput) outputs;
 };
index 1f2e4b18d7ed35ae174f66ecb12af5e360f15e21..2d592e64c9b15e7a85457243e249ec29ccc9c026 100644 (file)
@@ -71,6 +71,7 @@ int handle_map_request(void *prophs, xcb_connection_t *conn,
  *
  */
 int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event);
+#endif
 
 /**
  * Gets triggered upon a RandR screen change event, that is when the user
@@ -79,7 +80,6 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n
  */
 int handle_screen_change(void *prophs, xcb_connection_t *conn,
                          xcb_generic_event_t *e);
-#endif
 
 /**
  * Configure requests are received when the application wants to resize
index 7a501b8e276da2122b846157fca1229051ed4094..779a131630bff56d870b141ad8bc346e0c1bb064 100644 (file)
@@ -31,6 +31,16 @@ void randr_init(int *event_base);
  */
 void disable_randr(xcb_connection_t *conn);
 
+/**
+ * Initializes a CT_OUTPUT Con (searches existing ones from inplace restart
+ * before) to use for the given Output.
+ *
+ * XXX: for assignments, we probably need to move workspace creation from here
+ * to after the loop in randr_query_outputs().
+ *
+ */
+void output_init_con(Output *output);
+
 /**
  * Initializes the specified output, assigning the specified workspace to it.
  *
index ed59f528d11c396d6cabdfe3a955708d542bfcfc..21ca4e3b9d53d7181dae96358714c3e94d76477f 100644 (file)
@@ -428,6 +428,7 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n
 
         return 1;
 }
+#endif
 
 /*
  * Gets triggered upon a RandR screen change event, that is when the user
@@ -436,15 +437,14 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n
  */
 int handle_screen_change(void *prophs, xcb_connection_t *conn,
                          xcb_generic_event_t *e) {
-        DLOG("RandR screen change\n");
+    DLOG("RandR screen change\n");
 
-        randr_query_outputs(conn);
+    randr_query_outputs();
 
-        ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}");
+    ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}");
 
-        return 1;
+    return 1;
 }
-#endif
 
 /*
  * Our window decorations were unmapped. That means, the window will be killed
index e30887c9560f27b090e8b781fd4d81ca38d66ff3..ea7f82f23b63b29553331d8ec0d58b6f14d7bc72 100644 (file)
@@ -325,6 +325,17 @@ int main(int argc, char *argv[]) {
     translate_keysyms();
     grab_all_keys(conn, false);
 
+    bool needs_tree_init = true;
+    if (layout_path) {
+        LOG("Trying to restore the layout from %s...", layout_path);
+        needs_tree_init = !tree_restore(layout_path);
+        if (delete_layout_path)
+            unlink(layout_path);
+        free(layout_path);
+    }
+    if (needs_tree_init)
+        tree_init();
+
     int randr_base;
     if (force_xinerama) {
         xinerama_init();
@@ -332,24 +343,12 @@ int main(int argc, char *argv[]) {
         DLOG("Checking for XRandR...\n");
         randr_init(&randr_base);
 
-#if 0
         xcb_event_set_handler(&evenths,
                               randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY,
                               handle_screen_change,
                               NULL);
-#endif
     }
 
-    bool needs_tree_init = true;
-    if (layout_path) {
-        LOG("Trying to restore the layout from %s...", layout_path);
-        needs_tree_init = !tree_restore(layout_path);
-        if (delete_layout_path)
-            unlink(layout_path);
-        free(layout_path);
-    }
-    if (needs_tree_init)
-        tree_init();
     tree_render();
 
     struct ev_loop *loop = ev_loop_new(0);
index e0ad4eb2d4dd5d43bbe3ff22a60976ce43bfa9a4..999181efdde75816714a8855d9ddf7d4fe962206 100644 (file)
@@ -3,7 +3,7 @@
  *
  * i3 - an improved dynamic tiling window manager
  *
- * © 2009-2010 Michael Stapelberg and contributors
+ * © 2009-2011 Michael Stapelberg and contributors
  *
  * See file LICENSE for license information.
  *
@@ -215,6 +215,74 @@ void disable_randr(xcb_connection_t *conn) {
     randr_disabled = true;
 }
 
+/*
+ * Initializes a CT_OUTPUT Con (searches existing ones from inplace restart
+ * before) to use for the given Output.
+ *
+ * XXX: for assignments, we probably need to move workspace creation from here
+ * to after the loop in randr_query_outputs().
+ *
+ */
+void output_init_con(Output *output) {
+    Con *con = NULL, *current;
+    bool reused = false;
+    static int c = 1;
+
+    DLOG("init_con for output %s\n", output->name);
+
+    /* Search for a Con with that name directly below the root node. There
+     * might be one from a restored layout. */
+    TAILQ_FOREACH(current, &(croot->nodes_head), nodes) {
+        if (strcmp(current->name, output->name) != 0)
+            continue;
+
+        con = current;
+        reused = true;
+        DLOG("Using existing con %p / %s\n", con, con->name);
+        break;
+    }
+
+    if (con == NULL) {
+        con = con_new(croot);
+        FREE(con->name);
+        con->name = sstrdup(output->name);
+        con->type = CT_OUTPUT;
+    }
+    con->rect = output->rect;
+    output->con = con;
+
+    char *name;
+    asprintf(&name, "[i3 con] output %s", con->name);
+    x_set_name(con, name);
+    free(name);
+
+    if (reused) {
+        DLOG("Not adding workspace, this was a reused con\n");
+        return;
+    }
+    DLOG("Now adding a workspace\n");
+
+    /* add a workspace to this output */
+    Con *ws = con_new(NULL);
+    ws->type = CT_WORKSPACE;
+    /* TODO: don't just number workspaces, but get the next assigned one / unused one */
+    ws->num = c;
+    FREE(ws->name);
+    asprintf(&(ws->name), "%d", c);
+    c++;
+    con_attach(ws, con, false);
+
+    asprintf(&name, "[i3 con] workspace %s", ws->name);
+    x_set_name(ws, name);
+    free(name);
+
+    ws->fullscreen_mode = CF_OUTPUT;
+    ws->orientation = HORIZ;
+
+    /* TODO: Set focus in main.c */
+    con_focus(ws);
+}
+
 /*
  * This function needs to be called when changing the mode of an output when
  * it already has some workspaces (or a bar window) assigned.
@@ -227,9 +295,12 @@ void disable_randr(xcb_connection_t *conn) {
  *
  */
 static void output_change_mode(xcb_connection_t *conn, Output *output) {
-    i3Font *font = load_font(conn, config.font);
+    //i3Font *font = load_font(conn, config.font);
 
-    DLOG("Output mode changed, reconfiguring bar, updating workspaces\n");
+    DLOG("Output mode changed, updating rect\n");
+    assert(output->con != NULL);
+    output->con->rect = output->rect;
+#if 0
     Rect bar_rect = {output->rect.x,
                      output->rect.y + output->rect.height - (font->height + 6),
                      output->rect.x + output->rect.width,
@@ -237,7 +308,6 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) {
 
     xcb_set_window_rect(conn, output->bar, bar_rect);
 
-#if 0
         /* go through all workspaces and set force_reconfigure */
         TAILQ_FOREACH(ws, workspaces, workspaces) {
                 if (ws->output != output)
@@ -442,31 +512,47 @@ void randr_query_outputs() {
             if ((first = get_first_output()) == NULL)
                     die("No usable outputs available\n");
 
-            //bool needs_init = (first->current_workspace == NULL);
+            /* We need to move the workspaces from the disappearing output to the first output */
+            /* 1: Get the con to focus next, if the disappearing ws is focused */
+            Con *next = NULL;
+            if (TAILQ_FIRST(&(croot->focus_head)) == output->con) {
+                DLOG("This output (%p) was focused! Getting next\n", output->con);
+                next = con_next_focused(output->con);
+                DLOG("next = %p\n", next);
+            }
 
-#if 0
-            TAILQ_FOREACH(ws, workspaces, workspaces) {
-                    if (ws->output != output)
-                            continue;
-
-                    workspace_assign_to(ws, first, true);
-                    if (!needs_init)
-                            continue;
-                    //initialize_output(conn, first, ws);
-                    needs_init = false;
+            /* 2: iterate through workspaces and re-assign them */
+            Con *current;
+            while (!TAILQ_EMPTY(&(output->con->nodes_head))) {
+                current = TAILQ_FIRST(&(output->con->nodes_head));
+                DLOG("Detaching current = %p / %s\n", current, current->name);
+                con_detach(current);
+                DLOG("Re-attaching current = %p / %s\n", current, current->name);
+                con_attach(current, first->con, false);
+                DLOG("Done, next\n");
             }
+            DLOG("re-attached all workspaces\n");
 
-            Client *dock;
-            while (!SLIST_EMPTY(&(output->dock_clients))) {
-                    dock = SLIST_FIRST(&(output->dock_clients));
-                    SLIST_REMOVE_HEAD(&(output->dock_clients), dock_clients);
-                    SLIST_INSERT_HEAD(&(first->dock_clients), dock, dock_clients);
+            if (next) {
+                DLOG("now focusing next = %p\n", next);
+                con_focus(next);
             }
 
-#endif
-            //output->current_workspace = NULL;
+            DLOG("destroying disappearing con %p\n", output->con);
+            tree_close(output->con, false, true);
+            DLOG("Done. Should be fine now\n");
+            output->con = NULL;
+
             output->to_be_disabled = false;
-        } else if (output->changed) {
+        }
+
+        if (output->active && output->con == NULL) {
+            DLOG("Need to initialize a Con for output %s\n", output->name);
+            output_init_con(output);
+            output->changed = false;
+        }
+
+        if (output->changed) {
             output_change_mode(conn, output);
             output->changed = false;
         }
@@ -504,7 +590,7 @@ void randr_init(int *event_base) {
     extreply = xcb_get_extension_data(conn, &xcb_randr_id);
     if (!extreply->present)
         disable_randr(conn);
-    else randr_query_outputs(conn);
+    else randr_query_outputs();
 
     if (event_base != NULL)
         *event_base = extreply->first_event;
index 0233a12588c9c508396e69d8efa0ea610ddd840b..dfe5f7beb18cc1ba5f4fd516a2c7c2c5160dbee9 100644 (file)
@@ -40,56 +40,15 @@ bool tree_restore(const char *path) {
 }
 
 /*
- * Initializes the tree by creating the root node, adding all RandR outputs
- * to the tree (that means randr_init() has to be called before) and
- * assigning a workspace to each RandR output.
+ * Initializes the tree by creating the root node. The CT_OUTPUT Cons below the
+ * root node are created in randr.c for each Output.
  *
  */
 void tree_init() {
-    Output *output;
-
     croot = con_new(NULL);
     FREE(croot->name);
     croot->name = "root";
     croot->type = CT_ROOT;
-
-    Con *ws;
-    int c = 1;
-    /* add the outputs */
-    TAILQ_FOREACH(output, &outputs, outputs) {
-        if (!output->active)
-            continue;
-
-        Con *oc = con_new(croot);
-        FREE(oc->name);
-        oc->name = strdup(output->name);
-        oc->type = CT_OUTPUT;
-        oc->rect = output->rect;
-        output->con = oc;
-
-        char *name;
-        asprintf(&name, "[i3 con] output %s", oc->name);
-        x_set_name(oc, name);
-        free(name);
-
-        /* add a workspace to this output */
-        ws = con_new(NULL);
-        ws->type = CT_WORKSPACE;
-        ws->num = c;
-        FREE(ws->name);
-        asprintf(&(ws->name), "%d", c);
-        c++;
-        con_attach(ws, oc, false);
-
-        asprintf(&name, "[i3 con] workspace %s", ws->name);
-        x_set_name(ws, name);
-        free(name);
-
-        ws->fullscreen_mode = CF_OUTPUT;
-        ws->orientation = HORIZ;
-    }
-
-    con_focus(ws);
 }
 
 /*
index 369e8ab7311f31066165727fa1d0cb31f5f7ac62..8bb1b43f117fa08b67029b940f9661432fd3149f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * i3 - an improved dynamic tiling window manager
  *
- * © 2009-2010 Michael Stapelberg and contributors
+ * © 2009-2011 Michael Stapelberg and contributors
  *
  * See file LICENSE for license information.
  *
@@ -70,6 +70,7 @@ static void query_screens(xcb_connection_t *conn) {
             if (s->rect.x == 0 && s->rect.y == 0)
                     TAILQ_INSERT_HEAD(&outputs, s, outputs);
             else TAILQ_INSERT_TAIL(&outputs, s, outputs);
+            output_init_con(s);
             num_screens++;
         }