4976fa3350
Previously, in case 'layout stacked' (for example) had been called interactively, con_set_layout would be called with focused->parent, while with for_window, it’d be called on the actual matching container. This difference in behavior was the cause for the inability to use 'for_window [class="XTerm"] layout tabbed', which now works \o/, but more on that below. The change also allows us to handle the case of the user selecting a CT_WORKSPACE container properly, that is, by using the special case and creating a new split container on the workspace which gets all the contents, but a new layout. Now, before you are enthusiastic about the change and try to use for_window magic in your config file, keep in mind: The 'layout' command acts on the parent split container. That is, when using a line such as this one: for_window [class="XTerm"] layout tabbed …and opening an XTerm when on a workspace with one single other window, the whole workspace will be set tabbed (just as previously when you opened an XTerm and sent 'layout tabbed' manually). Therefore, to open XTerm in its own tabbed split container, you need to split before: for_window [class="XTerm"] split v, layout tabbed The comma here is important! It says that the second command should not be treated as an entirely unrelated command, but it should also relate the matching window (while it does work with a ';', that is prone to race-conditions and should be avoided). fixes #358
149 lines
4.5 KiB
Perl
149 lines
4.5 KiB
Perl
#!perl
|
||
# vim:ts=4:sw=4:expandtab
|
||
#
|
||
# Tests splitting
|
||
#
|
||
use i3test;
|
||
use List::Util qw(first);
|
||
|
||
my $tmp;
|
||
my $ws;
|
||
|
||
################################################################################
|
||
# Open two containers, split, open another container. Then verify
|
||
# the layout is like we expect it to be
|
||
################################################################################
|
||
|
||
sub verify_split_layout {
|
||
my (%args) = @_;
|
||
|
||
$tmp = fresh_workspace;
|
||
|
||
$ws = get_ws($tmp);
|
||
is($ws->{layout}, 'splith', 'orientation horizontal by default');
|
||
cmd 'split v';
|
||
$ws = get_ws($tmp);
|
||
is($ws->{layout}, 'splitv', 'split v changes workspace orientation');
|
||
|
||
cmd 'open';
|
||
cmd 'open';
|
||
my $content = get_ws_content($tmp);
|
||
|
||
is(@{$content}, 2, 'two containers on workspace level');
|
||
my $first = $content->[0];
|
||
my $second = $content->[1];
|
||
|
||
is(@{$first->{nodes}}, 0, 'first container has no children');
|
||
is(@{$second->{nodes}}, 0, 'second container has no children (yet)');
|
||
my $old_name = $second->{name};
|
||
|
||
cmd $args{split_command};
|
||
cmd 'open';
|
||
|
||
$content = get_ws_content($tmp);
|
||
|
||
is(@{$content}, 2, 'two containers on workspace level');
|
||
$first = $content->[0];
|
||
$second = $content->[1];
|
||
|
||
is(@{$first->{nodes}}, 0, 'first container has no children');
|
||
isnt($second->{name}, $old_name, 'second container was replaced');
|
||
is($second->{layout}, 'splith', 'orientation is horizontal');
|
||
is(@{$second->{nodes}}, 2, 'second container has 2 children');
|
||
is($second->{nodes}->[0]->{name}, $old_name, 'found old second container');
|
||
}
|
||
|
||
verify_split_layout(split_command => 'split h');
|
||
verify_split_layout(split_command => 'split horizontal');
|
||
|
||
# TODO: extend this test-case (test next/prev)
|
||
# - wrapping (no horizontal switch possible, goes level-up)
|
||
# - going level-up "manually"
|
||
|
||
######################################################################
|
||
# Test splitting multiple times without actually creating windows
|
||
######################################################################
|
||
|
||
$tmp = fresh_workspace;
|
||
|
||
$ws = get_ws($tmp);
|
||
is($ws->{layout}, 'splith', 'orientation horizontal by default');
|
||
cmd 'split v';
|
||
$ws = get_ws($tmp);
|
||
is($ws->{layout}, 'splitv', 'split v changes workspace orientation');
|
||
|
||
cmd 'open';
|
||
my @content = @{get_ws_content($tmp)};
|
||
|
||
# recursively sums up all nodes and their children
|
||
sub sum_nodes {
|
||
my ($nodes) = @_;
|
||
|
||
return 0 if !@{$nodes};
|
||
|
||
my @children = (map { @{$_->{nodes}} } @{$nodes},
|
||
map { @{$_->{'floating_nodes'}} } @{$nodes});
|
||
|
||
return @{$nodes} + sum_nodes(\@children);
|
||
}
|
||
|
||
my $old_count = sum_nodes(\@content);
|
||
cmd 'split v';
|
||
|
||
@content = @{get_ws_content($tmp)};
|
||
$old_count = sum_nodes(\@content);
|
||
|
||
cmd 'split v';
|
||
|
||
@content = @{get_ws_content($tmp)};
|
||
my $count = sum_nodes(\@content);
|
||
is($count, $old_count, 'not more windows after splitting again');
|
||
|
||
######################################################################
|
||
# In the special case of being inside a stacked or tabbed container, we don’t
|
||
# want this to happen.
|
||
######################################################################
|
||
|
||
$tmp = fresh_workspace;
|
||
|
||
cmd 'open';
|
||
@content = @{get_ws_content($tmp)};
|
||
is(scalar @content, 1, 'Precisely one container on this ws');
|
||
cmd 'layout stacked';
|
||
@content = @{get_ws_content($tmp)};
|
||
is(scalar @content, 1, 'Still one container on this ws');
|
||
is(scalar @{$content[0]->{nodes}}, 1, 'Stacked con has one child node');
|
||
|
||
cmd 'split h';
|
||
cmd 'open';
|
||
@content = @{get_ws_content($tmp)};
|
||
is(scalar @content, 1, 'Still one container on this ws');
|
||
is(scalar @{$content[0]->{nodes}}, 1, 'Stacked con still has one child node');
|
||
|
||
################################################################################
|
||
# When focusing the workspace, changing the layout should have an effect on the
|
||
# workspace, not on the parent (CT_CONTENT) container.
|
||
################################################################################
|
||
|
||
sub get_output_content {
|
||
my $tree = i3(get_socket_path())->get_tree->recv;
|
||
|
||
my @outputs = grep { $_->{name} !~ /^__/ } @{$tree->{nodes}};
|
||
is(scalar @outputs, 1, 'exactly one output (testcase not multi-monitor capable)');
|
||
my $output = $outputs[0];
|
||
# get the first (and only) CT_CON
|
||
return first { $_->{type} == 2 } @{$output->{nodes}};
|
||
}
|
||
|
||
$tmp = fresh_workspace;
|
||
|
||
cmd 'open';
|
||
cmd 'split v';
|
||
cmd 'open';
|
||
cmd 'focus parent';
|
||
is(get_output_content()->{layout}, 'splith', 'content container layout ok');
|
||
cmd 'layout stacked';
|
||
is(get_output_content()->{layout}, 'splith', 'content container layout still ok');
|
||
|
||
done_testing;
|