Allow multiple marks on windows.

This patch allows multiple marks to be set on a single window. The restriction that a mark may
only be on one window at a time is still upheld as this is necessary for commands like
"move window to mark" to make sense.

relates to #2014
This commit is contained in:
Ingo Bürk
2015-10-19 18:10:20 +02:00
parent 0425f48835
commit 9bb2f038ab
12 changed files with 238 additions and 70 deletions

View File

@ -398,7 +398,7 @@ EOT
my @nodes = @{get_ws($tmp)->{floating_nodes}};
cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'branded' ], "mark set (window_type = $atom)");
exit_gracefully($pid);
@ -431,7 +431,7 @@ EOT
my @nodes = @{get_ws($tmp)->{floating_nodes}};
cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'branded' ], "mark set (window_type = $atom)");
exit_gracefully($pid);
@ -454,7 +454,7 @@ $window = open_window;
@nodes = @{get_ws('trigger')->{floating_nodes}};
cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
is($nodes[0]->{nodes}[0]->{mark}, 'triggered', "mark set for workspace criterion");
is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'triggered' ], "mark set for workspace criterion");
exit_gracefully($pid);

View File

@ -28,7 +28,7 @@ sub get_mark_for_window_on_workspace {
my ($ws, $con) = @_;
my $current = first { $_->{window} == $con->{id} } @{get_ws_content($ws)};
return $current->{mark};
return $current->{marks};
}
##############################################################
@ -41,7 +41,6 @@ cmd 'split h';
is_deeply(get_marks(), [], 'no marks set yet');
##############################################################
# 2: mark a con, check that it's marked, unmark it, check that
##############################################################
@ -98,7 +97,7 @@ cmd 'mark important';
cmd 'focus left';
cmd 'mark important';
is(get_mark_for_window_on_workspace($tmp, $first), 'important', 'first container now has the mark');
is_deeply(get_mark_for_window_on_workspace($tmp, $first), [ 'important' ], 'first container now has the mark');
ok(!get_mark_for_window_on_workspace($tmp, $second), 'second container lost the mark');
##############################################################
@ -116,20 +115,10 @@ ok(!get_mark_for_window_on_workspace($tmp, $con), 'container no longer has the m
$con = open_window;
cmd 'mark --toggle important';
is(get_mark_for_window_on_workspace($tmp, $con), 'important', 'container now has the mark');
is_deeply(get_mark_for_window_on_workspace($tmp, $con), [ 'important' ], 'container now has the mark');
##############################################################
# 7: mark a con, toggle a different mark, check it is marked
# with the new mark
##############################################################
$con = open_window;
cmd 'mark boring';
cmd 'mark --toggle important';
is(get_mark_for_window_on_workspace($tmp, $con), 'important', 'container has the most recent mark');
##############################################################
# 8: mark a con, toggle the mark on another con,
# 7: mark a con, toggle the mark on another con,
# check only the latter has the mark
##############################################################
@ -140,11 +129,11 @@ cmd 'mark important';
cmd 'focus left';
cmd 'mark --toggle important';
is(get_mark_for_window_on_workspace($tmp, $first), 'important', 'left container has the mark now');
is_deeply(get_mark_for_window_on_workspace($tmp, $first), [ 'important' ], 'left container has the mark now');
ok(!get_mark_for_window_on_workspace($tmp, $second), 'second containr no longer has the mark');
##############################################################
# 9: try to mark two cons with the same mark and check that
# 8: try to mark two cons with the same mark and check that
# it fails
##############################################################

View File

@ -63,7 +63,7 @@ is($con->{window_properties}->{instance}, 'special',
# The mark `special_class_mark` is added in a `for_window` assignment in the
# config for testing purposes
is($con->{mark}, 'special_class_mark',
is_deeply($con->{marks}, [ 'special_class_mark' ],
'A `for_window` assignment should run for a match when the window changes class');
change_window_class($win, "abcdefghijklmnopqrstuv\0abcd", 24);

View File

@ -0,0 +1,96 @@
#!perl
# vim:ts=4:sw=4:expandtab
#
# Please read the following documents before working on tests:
# • http://build.i3wm.org/docs/testsuite.html
# (or docs/testsuite)
#
# • http://build.i3wm.org/docs/lib-i3test.html
# (alternatively: perldoc ./testcases/lib/i3test.pm)
#
# • http://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Tests for mark/unmark with multiple marks on a single window.
# Ticket: #2014
use i3test;
use List::Util qw(first);
my ($ws, $con, $first, $second);
sub get_marks {
return i3(get_socket_path())->get_marks->recv;
}
sub get_mark_for_window_on_workspace {
my ($ws, $con) = @_;
my $current = first { $_->{window} == $con->{id} } @{get_ws_content($ws)};
return $current->{marks};
}
###############################################################################
# Verify that multiple marks can be set on a window.
###############################################################################
$ws = fresh_workspace;
$con = open_window;
cmd 'mark A';
cmd 'mark B';
is_deeply(sort(get_marks()), [ 'A', 'B' ], 'both marks exist');
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
cmd 'unmark';
###############################################################################
# Verify that toggling a mark can affect only the specified mark.
###############################################################################
$ws = fresh_workspace;
$con = open_window;
cmd 'mark A';
cmd 'mark --toggle B';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
cmd 'mark --toggle B';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A' ], 'only mark B has been removed');
cmd 'unmark';
###############################################################################
# Verify that unmarking a mark leaves other marks on the same window intact.
###############################################################################
$ws = fresh_workspace;
$con = open_window;
cmd 'mark A';
cmd 'mark B';
cmd 'mark C';
cmd 'unmark B';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'C' ], 'only mark B has been removed');
cmd 'unmark';
###############################################################################
# Verify that matching via mark works on windows with multiple marks.
###############################################################################
$ws = fresh_workspace;
$con = open_window;
cmd 'mark A';
cmd 'mark B';
open_window;
cmd '[con_mark=B] mark C';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B', 'C' ], 'matching on a mark works with multiple marks');
cmd 'unmark';
###############################################################################
done_testing;