i3 - improved tiling WM


Send IPC workspace empty event after last window closed

Patch status: superseded

Patch by Marco Hunsicker

Long description:

This patch sends the workspace empty after the last container in
a workspace has been closed and the workspace becomes empty again.

To apply this patch, use:
curl http://cr.i3wm.org/patch/485/raw.patch | git am

b/src/tree.c

17
@@ -229,6 +229,9 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
18
         return false;
19
     }
20
 
21
+    Con *ws = con_get_workspace(con);
22
+    bool ws_empty = !ws || con_is_leaf(ws);
23
+
24
     if (con->window != NULL) {
25
         if (kill_window != DONT_KILL_WINDOW) {
26
             x_window_kill(con->window->id, kill_window);
27
@@ -264,8 +267,6 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
28
         FREE(con->window);
29
     }
30
 
31
-    Con *ws = con_get_workspace(con);
32
-
33
     /* Figure out which container to focus next before detaching 'con'. */
34
     if (con_is_floating(con)) {
35
         if (con == focused) {
36
@@ -321,6 +322,11 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
37
     TAILQ_REMOVE(&all_cons, con, all_cons);
38
     free(con);
39
 
40
+    /* if the workspace is now empty, notify any interested parties. */
41
+    if (ws && !ws_empty && con_is_leaf(ws)) {
42
+        ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
43
+    }
44
+
45
     /* in the case of floating windows, we already focused another container
46
      * when closing the parent, so we can exit now. */
47
     if (!next) {

b/testcases/t/223-ipc-empty-workspace.t

53
@@ -0,0 +1,87 @@
54
+#!perl
55
+# vim:ts=4:sw=4:expandtab
56
+#
57
+# Please read the following documents before working on tests:
58
+# • http://build.i3wm.org/docs/testsuite.html
59
+#   (or docs/testsuite)
60
+#
61
+# • http://build.i3wm.org/docs/lib-i3test.html
62
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
63
+#
64
+# • http://build.i3wm.org/docs/ipc.html
65
+#   (or docs/ipc)
66
+#
67
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
68
+#   (unless you are already familiar with Perl)
69
+#
70
+# Check if the workspace empty event is correctly send after window close.
71
+#
72
+use i3test;
73
+use List::Util qw(first);
74
+
75
+SKIP: {
76
+
77
+    skip "AnyEvent::I3 too old (need >= 0.15)", 1 if $AnyEvent::I3::VERSION < 0.15;
78
+
79
+my $i3 = i3(get_socket_path());
80
+$i3->connect()->recv;
81
+
82
+##############################################################
83
+# check that the empty event is send when last window closes
84
+##############################################################
85
+
86
+my $tmp = fresh_workspace;
87
+
88
+my $cond = AnyEvent->condvar;
89
+
90
+$i3->subscribe({
91
+    workspace => sub {
92
+        my ($event) = @_;
93
+        $cond->send($event);
94
+    }
95
+})->recv;
96
+
97
+my $w1 = open_window();
98
+
99
+cmd '[id="' . $w1->id . '"] kill';
100
+sync_with_i3;
101
+
102
+my $event = $cond->recv;
103
+is($event->{change}, 'empty', 'Empty workspace event received after last window close');
104
+
105
+
106
+##############################################################
107
+# check that no empty event is send when workspace is not
108
+# empty after window close
109
+##############################################################
110
+
111
+$tmp = fresh_workspace;
112
+
113
+$cond = AnyEvent->condvar;
114
+
115
+$i3->subscribe({
116
+    workspace => sub {
117
+        my ($event) = @_;
118
+        ok($event->{change} ne 'empty', 'No empty workspace event received');
119
+        $cond->send($event);
120
+    },
121
+    window => sub {
122
+        my ($event) = @_;
123
+        $cond->send($event);
124
+    }
125
+})->recv;
126
+
127
+$w1 = open_window(name => 'Window 1');
128
+my $w2 = open_window(name => 'Window 2');
129
+
130
+cmd '[id="' . $w2->id . '"] kill';
131
+sync_with_i3;
132
+
133
+$event = $cond->recv;
134
+
135
+is($event->{change}, 'focus', 'Window focus event received');
136
+is($event->{container}->{name}, 'Window 1', 'Window 1 focused');
137
+
138
+}
139
+
140
+done_testing;