]> git.sur5r.net Git - i3/i3/blob - testcases/t/166-assign.t
tests: t/166-assign.t: use wait_for_window
[i3/i3] / testcases / t / 166-assign.t
1 #!perl
2 # vim:ts=4:sw=4:expandtab
3 #
4 # Tests if assignments work
5 #
6 use i3test i3_autostart => 0;
7 use X11::XCB qw(PROP_MODE_REPLACE);
8
9 # TODO: move to X11::XCB
10 sub set_wm_class {
11     my ($id, $class, $instance) = @_;
12
13     # Add a _NET_WM_STRUT_PARTIAL hint
14     my $atomname = $x->atom(name => 'WM_CLASS');
15     my $atomtype = $x->atom(name => 'STRING');
16
17     $x->change_property(
18         PROP_MODE_REPLACE,
19         $id,
20         $atomname->id,
21         $atomtype->id,
22         8,
23         length($class) + length($instance) + 2,
24         "$instance\x00$class\x00"
25     );
26 }
27
28 sub open_special {
29     my %args = @_;
30     my $wm_class = delete($args{wm_class}) || 'special';
31     $args{name} //= 'special window';
32
33     # We use dont_map because i3 will not map the window on the current
34     # workspace. Thus, open_window would time out in wait_for_map (2 seconds).
35     my $window = open_window(
36         %args,
37         before_map => sub { set_wm_class($_->id, $wm_class, $wm_class) },
38         dont_map => 1,
39     );
40     $window->map;
41     return $window;
42 }
43
44 #####################################################################
45 # start a window and see that it does not get assigned with an empty config
46 #####################################################################
47
48 my $config = <<EOT;
49 # i3 config file (v4)
50 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
51 EOT
52
53 my $pid = launch_with_config($config);
54
55 my $tmp = fresh_workspace;
56
57 ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
58
59 my $window = open_special;
60 wait_for_map($window);
61
62 ok(@{get_ws_content($tmp)} == 1, 'special window got managed to current (random) workspace');
63
64 exit_gracefully($pid);
65
66 $window->destroy;
67
68 #####################################################################
69 # start a window and see that it gets assigned to a formerly unused
70 # workspace
71 #####################################################################
72
73 $config = <<EOT;
74 # i3 config file (v4)
75 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
76 assign "special" → targetws
77 EOT
78
79 $pid = launch_with_config($config);
80
81 $tmp = fresh_workspace;
82
83 ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
84 my $workspaces = get_workspace_names;
85 ok(!("targetws" ~~ @{$workspaces}), 'targetws does not exist yet');
86
87 $window = open_special;
88
89 ok(@{get_ws_content($tmp)} == 0, 'still no containers');
90 ok("targetws" ~~ @{get_workspace_names()}, 'targetws exists');
91
92 $window->destroy;
93
94 exit_gracefully($pid);
95
96 #####################################################################
97 # start a window and see that it gets assigned to a workspace which has content
98 # already, next to the existing node.
99 #####################################################################
100
101 $pid = launch_with_config($config);
102
103 # initialize the target workspace, then go to a fresh one
104 ok(!("targetws" ~~ @{get_workspace_names()}), 'targetws does not exist yet');
105 cmd 'workspace targetws';
106 cmp_ok(@{get_ws_content('targetws')}, '==', 0, 'no containers on targetws yet');
107 cmd 'open';
108 cmp_ok(@{get_ws_content('targetws')}, '==', 1, 'one container on targetws');
109 $tmp = fresh_workspace;
110
111 ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
112 ok("targetws" ~~ @{get_workspace_names()}, 'targetws does not exist yet');
113
114
115 # We use sync_with_i3 instead of wait_for_map here because i3 will not actually
116 # map the window -- it will be assigned to a different workspace and will only
117 # be mapped once you switch to that workspace
118 $window = open_special(dont_map => 1);
119 $window->map;
120 sync_with_i3;
121
122 ok(@{get_ws_content($tmp)} == 0, 'still no containers');
123 ok(@{get_ws_content('targetws')} == 2, 'two containers on targetws');
124
125 exit_gracefully($pid);
126
127 #####################################################################
128 # start a window and see that it gets assigned to a workspace which has content
129 # already, next to the existing node.
130 #####################################################################
131
132 $config = <<EOT;
133 # i3 config file (v4)
134 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
135 assign "special" → ~
136 EOT
137
138 $pid = launch_with_config($config);
139
140 $tmp = fresh_workspace;
141
142 ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
143 $workspaces = get_workspace_names;
144 ok(!("targetws" ~~ @{$workspaces}), 'targetws does not exist yet');
145
146 $window = open_special;
147
148 my $content = get_ws($tmp);
149 ok(@{$content->{nodes}} == 0, 'no tiling cons');
150 ok(@{$content->{floating_nodes}} == 1, 'one floating con');
151
152 $window->destroy;
153
154 exit_gracefully($pid);
155
156 #####################################################################
157 # make sure that assignments are case-insensitive in the old syntax.
158 #####################################################################
159
160 $config = <<EOT;
161 # i3 config file (v4)
162 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
163 assign "special" → ~
164 EOT
165
166 $pid = launch_with_config($config);
167
168 $tmp = fresh_workspace;
169
170 ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
171 $workspaces = get_workspace_names;
172 ok(!("targetws" ~~ @{$workspaces}), 'targetws does not exist yet');
173
174 $window = open_special(wm_class => 'SPEcial');
175 wait_for_map $window;
176
177 $content = get_ws($tmp);
178 ok(@{$content->{nodes}} == 0, 'no tiling cons');
179 ok(@{$content->{floating_nodes}} == 1, 'one floating con');
180
181 $window->destroy;
182
183 exit_gracefully($pid);
184
185 #####################################################################
186 # regression test: dock clients with floating assignments should not crash
187 # (instead, nothing should happen - dock clients can’t float)
188 # ticket #501
189 #####################################################################
190
191 # Walks /proc to figure out whether a child process of $i3pid with the name
192 # 'i3-nagbar' exists.
193 sub i3nagbar_running {
194     my ($i3pid) = @_;
195
196     my @procfiles = grep { m,^/proc/[0-9]+$, } </proc/*>;
197     for my $path (@procfiles) {
198         open(my $fh, '<', "$path/stat") or next;
199         my $line = <$fh>;
200         close($fh);
201         my ($comm, $ppid) = ($line =~ /^[0-9]+ \(([^)]+)\) . ([0-9]+)/);
202         return 1 if $ppid == $i3pid && $comm eq 'i3-nagbar';
203     }
204     return 0;
205 }
206
207 $config = <<EOT;
208 # i3 config file (v4)
209 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
210 for_window [title="special"] floating enable
211 EOT
212
213 $pid = launch_with_config($config);
214
215 $tmp = fresh_workspace;
216
217 ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
218 my @docked = get_dock_clients;
219 is(@docked, 0, 'one dock client yet');
220
221 $window = open_special(
222     window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'),
223 );
224
225 $content = get_ws($tmp);
226 ok(@{$content->{nodes}} == 0, 'no tiling cons');
227 ok(@{$content->{floating_nodes}} == 0, 'one floating con');
228 @docked = get_dock_clients;
229 is(@docked, 1, 'one dock client now');
230
231 $window->destroy;
232
233 does_i3_live;
234
235 exit_gracefully($pid);
236
237 done_testing;