2 # vim:ts=4:sw=4:expandtab
4 # Please read the following documents before working on tests:
5 # • http://build.i3wm.org/docs/testsuite.html
8 # • http://build.i3wm.org/docs/lib-i3test.html
9 # (alternatively: perldoc ./testcases/lib/i3test.pm)
11 # • http://build.i3wm.org/docs/ipc.html
14 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
15 # (unless you are already familiar with Perl)
17 # Test for the startup notification protocol.
22 use File::Temp qw(:POSIX);
26 skip "X11::XCB too old (need >= 0.07)", 24 if $X11::XCB::VERSION < 0.07;
28 use ExtUtils::PkgConfig;
30 # setup dependency on libstartup-notification using pkg-config
33 %sn_config = ExtUtils::PkgConfig->find('libstartup-notification-1.0');
36 use Inline C => Config => LIBS => $sn_config{libs}, CCFLAGS => $sn_config{cflags};
37 use Inline C => <<'END_OF_C_CODE';
41 #define SN_API_NOT_YET_FROZEN 1
42 #include <libsn/sn-common.h>
43 #include <libsn/sn-launchee.h>
45 static SnDisplay *sndisplay;
46 static SnLauncheeContext *ctx;
47 static xcb_connection_t *conn;
49 void init_ctx(void *connptr) {
50 conn = (xcb_connection_t*)connptr;
51 sndisplay = sn_xcb_display_new(conn, NULL, NULL);
52 ctx = sn_launchee_context_new_from_environment(sndisplay, 0);
55 const char *get_startup_id() {
56 return sn_launchee_context_get_startup_id(ctx);
59 void mark_window(int window) {
60 sn_launchee_context_setup_window(ctx, (Window)window);
64 void complete_startup() {
65 /* mark the startup process complete */
66 sn_launchee_context_complete(ctx);
70 my $first_ws = fresh_workspace;
72 is_num_children($first_ws, 0, 'no containers on this workspace yet');
74 ######################################################################
75 # 1) initiate startup, switch workspace, create window
76 # (should be placed on the original workspace)
77 ######################################################################
79 # Start a new process via i3 (to initialize a new startup notification
80 # context), then steal its DESKTOP_STARTUP_ID variable. We handle the startup
81 # notification in the testcase from there on.
83 # This works by setting up a FIFO in which the process (started by i3) will
84 # echo its $DESKTOP_STARTUP_ID. We (blockingly) read the variable into
85 # $startup_id in the testcase.
87 mkfifo($tmp, 0600) or BAIL_OUT "Could not create FIFO in $tmp: $!";
89 cmd qq|exec echo \$DESKTOP_STARTUP_ID >$tmp|;
91 open(my $fh, '<', $tmp);
92 chomp(my $startup_id = <$fh>);
97 isnt($startup_id, '', 'startup_id not empty');
99 $ENV{DESKTOP_STARTUP_ID} = $startup_id;
101 # Create a new libstartup-notification launchee context
102 init_ctx($x->get_xcb_conn());
104 # Make sure the context was set up successfully
105 is(get_startup_id(), $startup_id, 'libstartup-notification returns the same id');
107 my $second_ws = fresh_workspace;
109 is_num_children($second_ws, 0, 'no containers on the second workspace yet');
111 my $win = open_window({ dont_map => 1 });
112 mark_window($win->id);
114 # We don’t use wait_for_map because the window will not get mapped -- it is on
115 # a different workspace.
116 # We sync with i3 here to make sure $x->input_focus is updated.
119 is_num_children($second_ws, 0, 'still no containers on the second workspace');
120 is_num_children($first_ws, 1, 'one container on the first workspace');
122 ######################################################################
123 # same thing, but with _NET_STARTUP_ID set on the leader
124 ######################################################################
126 my $leader = open_window({ dont_map => 1 });
127 mark_window($leader->id);
129 $win = open_window({ dont_map => 1, client_leader => $leader });
133 is_num_children($second_ws, 0, 'still no containers on the second workspace');
134 is_num_children($first_ws, 2, 'two containers on the first workspace');
136 ######################################################################
137 # verifies that finishing startup doesn't immediately stop windows
138 # from being placed on the sequence's workspace, but that moving
139 # the leader actually deletes the startup sequence mapping
140 ######################################################################
145 # even when renaming the workspace, windows should end up on the correct one
146 cmd "rename workspace $first_ws to temp";
148 # Startup has completed but the 30-second deletion time hasn't elapsed,
149 # so this window should still go on the leader's initial workspace.
150 $win = open_window({ dont_map => 1, client_leader => $leader });
154 cmd "rename workspace temp to $first_ws";
156 is_num_children($first_ws, 3, 'three containers on the first workspace');
158 # empty 'from' workspaces should not crash the renaming of startup sequences
159 cmd "workspace $first_ws";
160 cmd "rename workspace to temp";
161 cmd "rename workspace to $first_ws";
163 # Switch to the first workspace and move the focused window to the
165 cmd "workspace $first_ws";
166 cmd "move workspace $second_ws";
168 is_num_children($second_ws, 1, 'one container on the second workspace');
170 # Create and switch to a new workspace, just to be safe.
171 my $third_ws = fresh_workspace;
173 # Moving the window between workspaces should have immediately
174 # removed the startup workspace mapping. New windows with that
175 # leader should be created on the current workspace.
176 $win = open_window({ dont_map => 1, client_leader => $leader });
180 is_num_children($third_ws, 1, 'one container on the third workspace');
182 ######################################################################
183 # 2) open another window after the startup process is completed
184 # (should be placed on the current workspace)
185 ######################################################################
187 my $otherwin = open_window;
188 is_num_children($third_ws, 2, 'two containers on the third workspace');
190 ######################################################################
191 # 3) test that the --no-startup-id flag for exec leads to no DESKTOP_STARTUP_ID
192 # environment variable.
193 ######################################################################
195 mkfifo($tmp, 0600) or BAIL_OUT "Could not create FIFO in $tmp";
197 cmd qq|exec --no-startup-id echo \$DESKTOP_STARTUP_ID >$tmp|;
199 open($fh, '<', $tmp);
200 chomp($startup_id = <$fh>);
205 is($startup_id, '', 'startup_id empty');
207 ######################################################################
208 # 4) same thing, but with double quotes in exec
209 ######################################################################
211 mkfifo($tmp, 0600) or BAIL_OUT "Could not create FIFO in $tmp";
213 cmd qq|exec --no-startup-id "echo \$DESKTOP_STARTUP_ID >$tmp"|;
215 open($fh, '<', $tmp);
216 chomp($startup_id = <$fh>);
221 is($startup_id, '', 'startup_id empty');