i3 - improved tiling WM


Add a new IPC event for changes on windows.

Patch status: merged

Patch by Piotr S. Staszewski

Long description:

Added new event id (I3_IPC_EVENT_WINDOW) so that a an IPC client can
subscribe to events on windows. Added a basic window event that gets
triggered when a window gets successfully reparented. This new event
also dumps the container data, so that IPC clients can get the initial
window name. IPC clients wishing to see window events should subscribe
to 'window'.

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

b/docs/ipc

23
@@ -621,6 +621,9 @@ output (1)::
24
 	outputs, CRTCs or output properties).
25
 mode (2)::
26
 	Sent whenever i3 changes its binding mode.
27
+window (3)::
28
+	Sent when a client's window is successfully reparented (that is when i3
29
+	has finished fitting it into a container).
30
 
31
 *Example:*
32
 --------------------------------------------------------------------
33
@@ -694,6 +697,30 @@ mode is simply named default.
34
 { "change": "default" }
35
 ---------------------------
36
 
37
+=== window event
38
+
39
+This event consists of a single serialized map containing a property
40
++change (string)+ which currently can indicate only that a new window
41
+has been successfully reparented (the value will be "new").
42
+
43
+Additionally a +container (object)+ field will be present, which consists
44
+of the window's parent container. Be aware that the container will hold
45
+the initial name of the newly reparented window (e.g. if you run urxvt
46
+with a shell that changes the title, you will still at this point get the
47
+window title as "urxvt").
48
+
49
+*Example:*
50
+---------------------------
51
+{
52
+ "change": "new",
53
+ "container": {
54
+  "id": 35569536,
55
+  "type": 2,
56
+  ...
57
+ }
58
+}
59
+---------------------------
60
+
61
 == See also (existing libraries)
62
 
63
 [[libraries]]

b/include/i3/ipc.h

68
@@ -96,4 +96,7 @@ typedef struct i3_ipc_header {
69
 /* The output event will be triggered upon mode changes */
70
 #define I3_IPC_EVENT_MODE                       (I3_IPC_EVENT_MASK | 2)
71
 
72
+/* The window event will be triggered upon window changes */
73
+#define I3_IPC_EVENT_WINDOW                     (I3_IPC_EVENT_MASK | 3)
74
+
75
 #endif

b/src/manage.c

80
@@ -10,6 +10,9 @@
81
  *
82
  */
83
 #include "all.h"
84
+#include "yajl_utils.h"
85
+
86
+#include <yajl/yajl_gen.h>
87
 
88
 /*
89
  * Go through all existing windows (if the window manager is restarted) and manage them
90
@@ -73,6 +76,35 @@ void restore_geometry(void) {
91
 }
92
 
93
 /*
94
+ * The following function sends a new window event, which consists
95
+ * of fields "change" and "container", the latter containing a dump
96
+ * of the window's container.
97
+ *
98
+ */
99
+static void ipc_send_window_new_event(Con *con) {
100
+    setlocale(LC_NUMERIC, "C");
101
+    yajl_gen gen = ygenalloc();
102
+
103
+    y(map_open);
104
+
105
+    ystr("change");
106
+    ystr("new");
107
+
108
+    ystr("container");
109
+    dump_node(gen, con, false);
110
+
111
+    y(map_close);
112
+
113
+    const unsigned char *payload;
114
+    ylength length;
115
+    y(get_buf, &payload, &length);
116
+ 
117
+    ipc_send_event("window", I3_IPC_EVENT_WINDOW, (const char *)payload);
118
+    y(free);
119
+    setlocale(LC_NUMERIC, "");
120
+}
121
+
122
+/*
123
  * Do some sanity checks and then reparent the window.
124
  *
125
  */
126
@@ -428,6 +460,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
127
     }
128
     tree_render();
129
 
130
+    /* Send an event about window creation */
131
+    ipc_send_window_new_event(nc);
132
+
133
 geom_out:
134
     free(geom);
135
 out:

b/testcases/t/205-ipc-windows.t

141
@@ -0,0 +1,43 @@
142
+#!perl
143
+# vim:ts=4:sw=4:expandtab
144
+#
145
+# Please read the following documents before working on tests:
146
+# • http://build.i3wm.org/docs/testsuite.html
147
+#   (or docs/testsuite)
148
+#
149
+# • http://build.i3wm.org/docs/lib-i3test.html
150
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
151
+#
152
+# • http://build.i3wm.org/docs/ipc.html
153
+#   (or docs/ipc)
154
+#
155
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
156
+#   (unless you are already familiar with Perl)
157
+
158
+use i3test;
159
+
160
+my $i3 = i3(get_socket_path());
161
+$i3->connect()->recv;
162
+
163
+################################
164
+# Window event
165
+################################
166
+
167
+# Events
168
+
169
+my $new = AnyEvent->condvar;
170
+$i3->subscribe({
171
+    window => sub {
172
+        my ($event) = @_;
173
+        $new->send($event->{change} eq 'new');
174
+    }
175
+})->recv;
176
+
177
+open_window;
178
+
179
+my $t;
180
+$t = AnyEvent->timer(after => 0.5, cb => sub { $new->send(0); });
181
+
182
+ok($new->recv, 'Window "new" event received');
183
+
184
+done_testing;