From: Michael Stapelberg Date: Tue, 29 Jun 2010 17:05:31 +0000 (+0200) Subject: Go down the tree when moving windows, add testcase for moving X-Git-Tag: tree-pr1~176 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=4eace6f88653a8c6aed9f0e29f43f7ea876f41aa;p=i3%2Fi3 Go down the tree when moving windows, add testcase for moving --- diff --git a/src/tree.c b/src/tree.c index d3e83875..2bcaeaae 100644 --- a/src/tree.c +++ b/src/tree.c @@ -350,6 +350,10 @@ void tree_move(char way, orientation_t orientation) { LOG("cannot move further to the right\n"); return; } + + /* 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); @@ -360,18 +364,31 @@ void tree_move(char way, orientation_t orientation) { /* TODO: don’t influence focus handling? */ } 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"); 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)); + } } con_detach(focused); focused->parent = next->parent; - TAILQ_INSERT_BEFORE(next, focused, nodes); + /* After going down in the tree, we insert the container *after* + * the currently focused one even though the command used "before". + * This is to keep the user experience clear, since the before/after + * only signifies the direction of the movement on top-level */ + if (gone_down) + TAILQ_INSERT_AFTER(&(next->parent->nodes_head), next, focused, nodes); + else TAILQ_INSERT_BEFORE(next, focused, nodes); TAILQ_INSERT_HEAD(&(next->parent->focus_head), focused, focused); /* TODO: don’t influence focus handling? */ } diff --git a/testcases/t/24-move.t b/testcases/t/24-move.t new file mode 100644 index 00000000..c7ddad4b --- /dev/null +++ b/testcases/t/24-move.t @@ -0,0 +1,113 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests moving. Basically, there are four different code-paths: +# 1) move a container which cannot be moved (single container on a workspace) +# 2) move a container before another single container +# 3) move a container inside another container +# 4) move a container in a different direction so that we need to go up in tree +# +use i3test tests => 16; +use X11::XCB qw(:all); +use v5.10; + +my $i3 = i3("/tmp/nestedcons"); + +my $tmp = get_unused_workspace(); +$i3->command("workspace $tmp")->recv; + +###################################################################### +# 1) move a container which cannot be moved +###################################################################### + +$i3->command('open')->recv; + +my $old_content = get_ws_content($tmp); +is(@{$old_content}, 1, 'one container on this workspace'); + +my $first = $old_content->[0]->{id}; + +$i3->command('move before h')->recv; +$i3->command('move before v')->recv; +$i3->command('move after v')->recv; +$i3->command('move after h')->recv; + +my $content = get_ws_content($tmp); +is_deeply($old_content, $content, 'workspace unmodified after useless moves'); + +###################################################################### +# 2) move a container before another single container +###################################################################### + +$i3->command('open')->recv; +$content = get_ws_content($tmp); +is(@{$content}, 2, 'two containers on this workspace'); +my $second = $content->[1]->{id}; + +is($content->[0]->{id}, $first, 'first container unmodified'); + +# Move the second container before the first one (→ swap them) +$i3->command('move before h')->recv; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $second, 'first container modified'); + +# We should not be able to move any further +$i3->command('move before h')->recv; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $second, 'first container unmodified'); + +# Now move in the other direction +$i3->command('move after h')->recv; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $first, 'first container modified'); + +# We should not be able to move any further +$i3->command('move after h')->recv; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $first, 'first container unmodified'); + +###################################################################### +# 3) move a container inside another container +###################################################################### + +# Split the current (second) container and create a new container on workspace +# level. Our layout looks like this now: +# -------------------------- +# | | second | | +# | first | ------ | third | +# | | | | +# -------------------------- +$i3->command('split v')->recv; +$i3->command('level up')->recv; +$i3->command('open')->recv; + +$content = get_ws_content($tmp); +is(@{$content}, 3, 'three containers on this workspace'); +my $third = $content->[2]->{id}; + +$i3->command('move before h')->recv; +$content = get_ws_content($tmp); +is(@{$content}, 2, 'only two containers on this workspace'); +my $nodes = $content->[1]->{nodes}; +is($nodes->[0]->{id}, $second, 'second container on top'); +is($nodes->[1]->{id}, $third, 'third container on bottom'); + +###################################################################### +# move it inside the split container +###################################################################### + +$i3->command('move before v')->recv; +$nodes = get_ws_content($tmp)->[1]->{nodes}; +is($nodes->[0]->{id}, $third, 'third container on top'); +is($nodes->[1]->{id}, $second, 'second container on bottom'); + +# move it outside again +$i3->command('move before h')->recv; +$content = get_ws_content($tmp); +is(@{$content}, 3, 'three nodes on this workspace'); + +$i3->command('move after h')->recv; +$content = get_ws_content($tmp); +is(@{$content}, 2, 'two nodes on this workspace'); + +diag( "Testing i3, Perl $], $^X" );