diff --git a/include/con.h b/include/con.h index 8b9ae9c7..5c104ebd 100644 --- a/include/con.h +++ b/include/con.h @@ -39,6 +39,12 @@ bool con_is_leaf(Con *con); */ bool con_is_split(Con *con); +/** + * Returns true if this node has regular or floating children. + * + */ +bool con_has_children(Con *con); + /** * Returns true if this node accepts a window (if the node swallows windows, * it might already have swallowed enough and cannot hold any more). diff --git a/src/commands.c b/src/commands.c index 2b429cb3..dfb4e236 100644 --- a/src/commands.c +++ b/src/commands.c @@ -402,7 +402,7 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) { * when criteria wasn't specified and we don't have any window focused. */ if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) || (match_is_empty(current_match) && focused->type == CT_WORKSPACE && - con_is_leaf(focused))) { + !con_has_children(focused))) { ysuccess(false); return; } @@ -491,7 +491,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) { return; } else if (match_is_empty(current_match) && focused->type == CT_WORKSPACE && - con_is_leaf(focused)) { + !con_has_children(focused)) { ysuccess(false); return; } @@ -526,7 +526,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) { * when criteria wasn't specified and we don't have any window focused. */ if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) || (match_is_empty(current_match) && focused->type == CT_WORKSPACE && - con_is_leaf(focused))) { + !con_has_children(focused))) { ysuccess(false); return; } diff --git a/src/con.c b/src/con.c index 493707d6..609a0d36 100644 --- a/src/con.c +++ b/src/con.c @@ -232,6 +232,14 @@ bool con_is_leaf(Con *con) { return TAILQ_EMPTY(&(con->nodes_head)); } +/** + * Returns true if this node has regular or floating children. + * + */ +bool con_has_children(Con *con) { + return (!con_is_leaf(con) || !TAILQ_EMPTY(&(con->floating_head))); +} + /* * Returns true if a container should be considered split. * @@ -643,18 +651,22 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool } if (con->type == CT_WORKSPACE) { - con = workspace_encapsulate(con); - if (con == NULL) { - ELOG("Workspace failed to move its contents into a container!\n"); - return; - } - /* Re-parent all of the old workspace's floating windows. */ Con *child; while (!TAILQ_EMPTY(&(source_ws->floating_head))) { child = TAILQ_FIRST(&(source_ws->floating_head)); con_move_to_workspace(child, workspace, true, true); } + + /* If there are no non-floating children, ignore the workspace. */ + if (con_is_leaf(con)) + return; + + con = workspace_encapsulate(con); + if (con == NULL) { + ELOG("Workspace failed to move its contents into a container!\n"); + return; + } } /* Save the current workspace. So we can call workspace_show() by the end diff --git a/testcases/t/132-move-workspace.t b/testcases/t/132-move-workspace.t index 730041a6..d0991039 100644 --- a/testcases/t/132-move-workspace.t +++ b/testcases/t/132-move-workspace.t @@ -318,4 +318,23 @@ $ws = get_ws($tmp2); is_num_children($tmp2, 1, 'one container on second workspace'); is(@{$ws->{floating_nodes}}, 2, 'two floating nodes on second workspace'); +################################################################### +# same as the above, but with only floating children +################################################################### +$tmp2 = get_unused_workspace(); +$tmp = fresh_workspace(); +cmd 'open'; +cmd 'floating toggle'; + +$ws = get_ws($tmp); +is_num_children($tmp, 0, 'no regular nodes on first workspace'); +is(@{$ws->{floating_nodes}}, 1, 'one floating node on first workspace'); + +cmd 'focus parent'; +cmd "move workspace $tmp2"; + +$ws = get_ws($tmp2); +is_num_children($tmp2, 0, 'no regular nodes on second workspace'); +is(@{$ws->{floating_nodes}}, 1, 'one floating node on second workspace'); + done_testing;