]> git.sur5r.net Git - i3/i3/commitdiff
Fix crash when trying to split and float a dock container. 2040/head
authorIngo Bürk <ingo.buerk@tngtech.com>
Mon, 26 Oct 2015 17:16:21 +0000 (18:16 +0100)
committerIngo Bürk <ingo.buerk@tngtech.com>
Mon, 26 Oct 2015 21:14:14 +0000 (22:14 +0100)
Since splitting a docking container was allowed and successful, the check
to prevent floating it fails to work. This causes a crash because the
workspace of the container cannot be determined as the dockarea is higher
up in the tree than the workspace it belongs to.

This patch extends to sanity check to nested dock containers when trying to
float a container and also disallows manually splitting a docked container
or changing its layout.

fixes #2034

include/con.h
src/commands.c
src/con.c
src/floating.c

index 1c8e341bc29dd17b9398188e2694938b872eccad..9ed9508a6ef93a658fe1177cd1030d5f52bf1868 100644 (file)
@@ -112,6 +112,12 @@ bool con_is_internal(Con *con);
  */
 bool con_is_floating(Con *con);
 
+/**
+ * Returns true if the container is a docked container.
+ *
+ */
+bool con_is_docked(Con *con);
+
 /**
  * Checks if the given container is either floating or inside some floating
  * container. It returns the FLOATING_CON container.
index 7aab6422522833eb3a889678f956bfeb01ce2a04..7f196bdc9da966eabb6233cd52133345192f17e3 100644 (file)
@@ -1188,16 +1188,18 @@ void cmd_move_workspace_to_output(I3_CMD, const char *name) {
  *
  */
 void cmd_split(I3_CMD, const char *direction) {
+    HANDLE_EMPTY_MATCH;
+
     owindow *current;
-    /* TODO: use matches */
     LOG("splitting in direction %c\n", direction[0]);
-    if (match_is_empty(current_match))
-        tree_split(focused, (direction[0] == 'v' ? VERT : HORIZ));
-    else {
-        TAILQ_FOREACH(current, &owindows, owindows) {
-            DLOG("matching: %p / %s\n", current->con, current->con->name);
-            tree_split(current->con, (direction[0] == 'v' ? VERT : HORIZ));
+    TAILQ_FOREACH(current, &owindows, owindows) {
+        if (con_is_docked(current->con)) {
+            ELOG("Cannot split a docked container, skipping.\n");
+            continue;
         }
+
+        DLOG("matching: %p / %s\n", current->con, current->con->name);
+        tree_split(current->con, (direction[0] == 'v' ? VERT : HORIZ));
     }
 
     cmd_output->needs_tree_render = true;
@@ -1524,9 +1526,10 @@ void cmd_move_direction(I3_CMD, const char *direction, long move_px) {
  *
  */
 void cmd_layout(I3_CMD, const char *layout_str) {
+    HANDLE_EMPTY_MATCH;
+
     if (strcmp(layout_str, "stacking") == 0)
         layout_str = "stacked";
-    owindow *current;
     layout_t layout;
     /* default is a special case which will be handled in con_set_layout(). */
     if (strcmp(layout_str, "default") == 0)
@@ -1546,14 +1549,15 @@ void cmd_layout(I3_CMD, const char *layout_str) {
 
     DLOG("changing layout to %s (%d)\n", layout_str, layout);
 
-    /* check if the match is empty, not if the result is empty */
-    if (match_is_empty(current_match))
-        con_set_layout(focused, layout);
-    else {
-        TAILQ_FOREACH(current, &owindows, owindows) {
-            DLOG("matching: %p / %s\n", current->con, current->con->name);
-            con_set_layout(current->con, layout);
+    owindow *current;
+    TAILQ_FOREACH(current, &owindows, owindows) {
+        if (con_is_docked(current->con)) {
+            ELOG("cannot change layout of a docked container, skipping it.\n");
+            continue;
         }
+
+        DLOG("matching: %p / %s\n", current->con, current->con->name);
+        con_set_layout(current->con, layout);
     }
 
     cmd_output->needs_tree_render = true;
index cebe0a7e7a473a49054cc14c1db468d5b3920399..bd002d35ca245517372ef7f5f38ec1c7973a60ef 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -448,6 +448,20 @@ bool con_is_floating(Con *con) {
     return (con->floating >= FLOATING_AUTO_ON);
 }
 
+/*
+ * Returns true if the container is a docked container.
+ *
+ */
+bool con_is_docked(Con *con) {
+    if (con->parent == NULL)
+        return false;
+
+    if (con->parent->type == CT_DOCKAREA)
+        return true;
+
+    return con_is_docked(con->parent);
+}
+
 /*
  * Checks if the given container is either floating or inside some floating
  * container. It returns the FLOATING_CON container.
index d7a330678d1d2d8227e3037c9a690c3d30bbb861..77bc9e17989b37a3a6ade3e4685dca65d30e801b 100644 (file)
@@ -108,7 +108,7 @@ void floating_check_size(Con *floating_con) {
 void floating_enable(Con *con, bool automatic) {
     bool set_focus = (con == focused);
 
-    if (con->parent && con->parent->type == CT_DOCKAREA) {
+    if (con_is_docked(con)) {
         LOG("Container is a dock window, not enabling floating mode.\n");
         return;
     }