]> git.sur5r.net Git - i3/i3/blob - testcases/t/175-startup-notification.t
Merge branch 'master' into next
[i3/i3] / testcases / t / 175-startup-notification.t
1 #!perl
2 # vim:ts=4:sw=4:expandtab
3 #
4 # Please read the following documents before working on tests:
5 # • http://build.i3wm.org/docs/testsuite.html
6 #   (or docs/testsuite)
7 #
8 # • http://build.i3wm.org/docs/lib-i3test.html
9 #   (alternatively: perldoc ./testcases/lib/i3test.pm)
10 #
11 # • http://build.i3wm.org/docs/ipc.html
12 #   (or docs/ipc)
13 #
14 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
15 #   (unless you are already familiar with Perl)
16 #
17 # Test for the startup notification protocol.
18 #
19
20 use i3test;
21 use POSIX qw(mkfifo);
22 use File::Temp qw(:POSIX);
23
24 use ExtUtils::PkgConfig;
25
26 # setup dependency on libstartup-notification using pkg-config
27 my %sn_config;
28 BEGIN {
29     %sn_config = ExtUtils::PkgConfig->find('libstartup-notification-1.0');
30 }
31
32 use Inline C => Config => LIBS => $sn_config{libs}, CCFLAGS => $sn_config{cflags};
33 use Inline C => <<'END_OF_C_CODE';
34
35 #include <xcb/xcb.h>
36
37 #define SN_API_NOT_YET_FROZEN 1
38 #include <libsn/sn-common.h>
39 #include <libsn/sn-launchee.h>
40
41 static SnDisplay *sndisplay;
42 static SnLauncheeContext *ctx;
43 static xcb_connection_t *conn;
44
45 // TODO: this should use $x
46 void init_ctx() {
47     int screen;
48     if ((conn = xcb_connect(NULL, &screen)) == NULL ||
49         xcb_connection_has_error(conn))
50         errx(1, "x11 conn failed");
51
52     printf("screen = %d\n", screen);
53     sndisplay = sn_xcb_display_new(conn, NULL, NULL);
54     ctx = sn_launchee_context_new_from_environment(sndisplay, screen);
55 }
56
57 const char *get_startup_id() {
58     return sn_launchee_context_get_startup_id(ctx);
59 }
60
61 void mark_window(int window) {
62     sn_launchee_context_setup_window(ctx, (Window)window);
63     xcb_flush(conn);
64 }
65
66 void complete_startup() {
67     /* mark the startup process complete */
68     sn_launchee_context_complete(ctx);
69 }
70 END_OF_C_CODE
71
72 my $first_ws = fresh_workspace;
73
74 is_num_children($first_ws, 0, 'no containers on this workspace yet');
75
76 ######################################################################
77 # 1) initiate startup, switch workspace, create window
78 # (should be placed on the original workspace)
79 ######################################################################
80
81 # Start a new process via i3 (to initialize a new startup notification
82 # context), then steal its DESKTOP_STARTUP_ID variable. We handle the startup
83 # notification in the testcase from there on.
84 #
85 # This works by setting up a FIFO in which the process (started by i3) will
86 # echo its $DESKTOP_STARTUP_ID. We (blockingly) read the variable into
87 # $startup_id in the testcase.
88 my $tmp = tmpnam();
89 mkfifo($tmp, 0600) or die "Could not create FIFO in $tmp";
90
91 cmd qq|exec echo \$DESKTOP_STARTUP_ID >$tmp|;
92
93 open(my $fh, '<', $tmp);
94 chomp(my $startup_id = <$fh>);
95 close($fh);
96
97 unlink($tmp);
98
99 isnt($startup_id, '', 'startup_id not empty');
100
101 $ENV{DESKTOP_STARTUP_ID} = $startup_id;
102
103 # Create a new libstartup-notification launchee context
104 init_ctx();
105
106 # Make sure the context was set up successfully
107 is(get_startup_id(), $startup_id, 'libstartup-notification returns the same id');
108
109 my $second_ws = fresh_workspace;
110
111 is_num_children($second_ws, 0, 'no containers on the second workspace yet');
112
113 my $win = open_window({ dont_map => 1 });
114 mark_window($win->id);
115 $win->map;
116 # We don’t use wait_for_map because the window will not get mapped -- it is on
117 # a different workspace.
118 # We sync with i3 here to make sure $x->input_focus is updated.
119 sync_with_i3;
120
121 is_num_children($second_ws, 0, 'still no containers on the second workspace');
122 is_num_children($first_ws, 1, 'one container on the first workspace');
123
124 ######################################################################
125 # same thing, but with _NET_STARTUP_ID set on the leader
126 ######################################################################
127
128 my $leader = open_window({ dont_map => 1 });
129 mark_window($leader->id);
130
131 $win = open_window({ dont_map => 1, client_leader => $leader });
132 $win->map;
133 sync_with_i3;
134
135 is_num_children($second_ws, 0, 'still no containers on the second workspace');
136 is_num_children($first_ws, 2, 'two containers on the first workspace');
137
138 ######################################################################
139 # verifies that finishing startup doesn't immediately stop windows
140 # from being placed on the sequence's workspace, but that moving
141 # the leader actually deletes the startup sequence mapping
142 ######################################################################
143
144 complete_startup();
145 sync_with_i3;
146
147 # Startup has completed but the 30-second deletion time hasn't elapsed,
148 # so this window should still go on the leader's initial workspace.
149 $win = open_window({ dont_map => 1, client_leader => $leader });
150 $win->map;
151 sync_with_i3;
152
153 is_num_children($first_ws, 3, 'three containers on the first workspace');
154
155 # Switch to the first workspace and move the focused window to the
156 # second workspace.
157 cmd "workspace $first_ws";
158 cmd "move workspace $second_ws";
159
160 is_num_children($second_ws, 1, 'one container on the second workspace');
161
162 # Create and switch to a new workspace, just to be safe.
163 my $third_ws = fresh_workspace;
164
165 # Moving the window between workspaces should have immediately
166 # removed the startup workspace mapping. New windows with that
167 # leader should be created on the current workspace.
168 $win = open_window({ dont_map => 1, client_leader => $leader });
169 $win->map;
170 sync_with_i3;
171
172 is_num_children($third_ws, 1, 'one container on the third workspace');
173
174 ######################################################################
175 # 2) open another window after the startup process is completed
176 # (should be placed on the current workspace)
177 ######################################################################
178
179 my $otherwin = open_window;
180 is_num_children($third_ws, 2, 'two containers on the third workspace');
181
182 ######################################################################
183 # 3) test that the --no-startup-id flag for exec leads to no DESKTOP_STARTUP_ID
184 # environment variable.
185 ######################################################################
186
187 mkfifo($tmp, 0600) or die "Could not create FIFO in $tmp";
188
189 cmd qq|exec --no-startup-id echo \$DESKTOP_STARTUP_ID >$tmp|;
190
191 open($fh, '<', $tmp);
192 chomp($startup_id = <$fh>);
193 close($fh);
194
195 unlink($tmp);
196
197 is($startup_id, '', 'startup_id empty');
198
199 ######################################################################
200 # 4) same thing, but with double quotes in exec
201 ######################################################################
202
203 mkfifo($tmp, 0600) or die "Could not create FIFO in $tmp";
204
205 cmd qq|exec --no-startup-id "echo \$DESKTOP_STARTUP_ID >$tmp"|;
206
207 open($fh, '<', $tmp);
208 chomp($startup_id = <$fh>);
209 close($fh);
210
211 unlink($tmp);
212
213 is($startup_id, '', 'startup_id empty');
214
215 done_testing;