]> git.sur5r.net Git - i3/i3/blobdiff - src/tree.c
Default to a file in /tmp for the restart state.
[i3/i3] / src / tree.c
index 947a8daaba91c3520089fa69136a2732823012f7..1edbf73528881db73cd011d0ca9efeb2e0a28b8e 100644 (file)
@@ -13,8 +13,8 @@ struct all_cons_head all_cons = TAILQ_HEAD_INITIALIZER(all_cons);
  * Loads tree from ~/.i3/_restart.json (used for in-place restarts).
  *
  */
-bool tree_restore() {
-    char *globbed = resolve_tilde(config.restart_state_path);
+bool tree_restore(const char *path) {
+    char *globbed = resolve_tilde(path);
 
     if (!path_exists(globbed)) {
         LOG("%s does not exist, not restoring tree\n", globbed);
@@ -28,15 +28,6 @@ bool tree_restore() {
 
     tree_append_json(globbed);
 
-    size_t path_len = strlen(config.restart_state_path);
-    char *old_restart = malloc(path_len + 5);
-    strncpy(old_restart, config.restart_state_path, path_len + 5);
-    strncat(old_restart, ".old", path_len + 5);
-    unlink(old_restart);
-    rename(globbed, old_restart);
-    free(globbed);
-    free(old_restart);
-
     printf("appended tree, using new root\n");
     croot = TAILQ_FIRST(&(croot->nodes_head));
     printf("new root = %p\n", croot);
@@ -44,7 +35,6 @@ bool tree_restore() {
     printf("out = %p\n", out);
     Con *ws = TAILQ_FIRST(&(out->nodes_head));
     printf("ws = %p\n", ws);
-    con_focus(ws);
 
     return true;
 }
@@ -86,7 +76,7 @@ void tree_init() {
         ws->num = c;
         asprintf(&(ws->name), "%d", c);
         c++;
-        con_attach(ws, oc);
+        con_attach(ws, oc, false);
 
         asprintf(&name, "[i3 con] workspace %s", ws->name);
         x_set_name(ws, name);
@@ -268,8 +258,12 @@ void tree_split(Con *con, orientation_t orientation) {
     new->parent = parent;
     new->orientation = orientation;
 
-    /* 3: add it as a child to the new Con */
-    con_attach(con, new);
+    /* 3: swap 'percent' (resize factor) */
+    new->percent = con->percent;
+    con->percent = 0.0;
+
+    /* 4: add it as a child to the new Con */
+    con_attach(con, new, false);
 }
 
 /*
@@ -397,11 +391,47 @@ void tree_move(char way, orientation_t orientation) {
         return;
     bool level_changed = false;
     while (con_orientation(parent) != orientation) {
-        LOG("need to go one level further up\n");
-        /* if the current parent is an output, we are at a workspace
-         * and the orientation still does not match */
-        if (parent->type == CT_WORKSPACE)
-            return;
+        DLOG("need to go one level further up\n");
+        /* If the current parent is an output, we are at a workspace
+         * and the orientation still does not match. In this case, we split the
+         * workspace to have the same look & feel as in older i3 releases. */
+        if (parent->type == CT_WORKSPACE) {
+            DLOG("Arrived at workspace, splitting...\n");
+            /* 1: create a new split container */
+            Con *new = con_new(NULL);
+            new->parent = parent;
+
+            /* 2: copy layout and orientation from workspace */
+            new->layout = parent->layout;
+            new->orientation = parent->orientation;
+
+            Con *old_focused = TAILQ_FIRST(&(parent->focus_head));
+            if (old_focused == TAILQ_END(&(parent->focus_head)))
+                old_focused = NULL;
+
+            /* 3: move the existing cons of this workspace below the new con */
+            DLOG("Moving cons\n");
+            Con *child;
+            while (!TAILQ_EMPTY(&(parent->nodes_head))) {
+                child = TAILQ_FIRST(&(parent->nodes_head));
+                con_detach(child);
+                con_attach(child, new, true);
+            }
+
+            /* 4: switch workspace orientation */
+            parent->orientation = orientation;
+
+            /* 4: attach the new split container to the workspace */
+            DLOG("Attaching new split to ws\n");
+            con_attach(new, parent, false);
+
+            if (old_focused)
+                con_focus(old_focused);
+
+            level_changed = true;
+
+            break;
+        }
         parent = parent->parent;
         level_changed = true;
     }
@@ -412,16 +442,23 @@ void tree_move(char way, orientation_t orientation) {
     Con *next = current;
     if (way == 'n') {
         LOG("i would insert it after %p / %s\n", next, next->name);
-        if (!level_changed) {
-            next = TAILQ_NEXT(next, nodes);
-            if (next == TAILQ_END(&(next->parent->nodes_head))) {
-                LOG("cannot move further to the right\n");
+
+        /* Have a look at the next container: If there is no next container or
+         * if it is a leaf node, we move the focused one left to it. However,
+         * for split containers, we descend into it. */
+        next = TAILQ_NEXT(next, nodes);
+        if (next == TAILQ_END(&(next->parent->nodes_head))) {
+            if (focused == current)
                 return;
+            next = current;
+        } else {
+            if (level_changed && con_is_leaf(next)) {
+                next = current;
+            } else {
+                /* if this is a split container, we need to go down */
+                while (!TAILQ_EMPTY(&(next->focus_head)))
+                    next = TAILQ_FIRST(&(next->focus_head));
             }
-
-            /* if this is a split container, we need to go down */
-            while (!TAILQ_EMPTY(&(next->focus_head)))
-                next = TAILQ_FIRST(&(next->focus_head));
         }
 
         con_detach(focused);
@@ -433,17 +470,20 @@ void tree_move(char way, orientation_t orientation) {
     } else {
         LOG("i would insert it before %p / %s\n", current, current->name);
         bool gone_down = false;
-        if (!level_changed) {
-            next = TAILQ_PREV(next, nodes_head, nodes);
-            if (next == TAILQ_END(&(next->parent->nodes_head))) {
-                LOG("cannot move further\n");
+        next = TAILQ_PREV(next, nodes_head, nodes);
+        if (next == TAILQ_END(&(next->parent->nodes_head))) {
+            if (focused == current)
                 return;
-            }
-
-            /* if this is a split container, we need to go down */
-            while (!TAILQ_EMPTY(&(next->focus_head))) {
-                gone_down = true;
-                next = TAILQ_FIRST(&(next->focus_head));
+            next = current;
+        } else {
+            if (level_changed && con_is_leaf(next)) {
+                next = current;
+            } else {
+                /* if this is a split container, we need to go down */
+                while (!TAILQ_EMPTY(&(next->focus_head))) {
+                    gone_down = true;
+                    next = TAILQ_FIRST(&(next->focus_head));
+                }
             }
         }
 
@@ -461,6 +501,11 @@ void tree_move(char way, orientation_t orientation) {
         /* TODO: don’t influence focus handling? */
     }
 
+    /* We need to call con_focus() to fix the focus stack "above" the container
+     * we just inserted the focused container into (otherwise, the parent
+     * container(s) would still point to the old container(s)). */
+    con_focus(focused);
+
     if (con_num_children(old_parent) == 0) {
         DLOG("Old container empty after moving. Let's close it\n");
         tree_close(old_parent, false, false);