]> git.sur5r.net Git - i3/i3/commitdiff
Add a new IPC event for changes on windows.
authorPiotr S. Staszewski <p.staszewski@gmail.com>
Fri, 11 Jan 2013 18:58:32 +0000 (19:58 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 18 Feb 2013 09:55:11 +0000 (10:55 +0100)
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'.

docs/ipc
include/i3/ipc.h
src/manage.c
testcases/t/205-ipc-windows.t [new file with mode: 0644]

index e1a1fc5fe1c5a5fc9ff37190974c8199911e7992..8cfb21d035659d2089a4c59a0a3809b205192c7f 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -623,6 +623,9 @@ output (1)::
        outputs, CRTCs or output properties).
 mode (2)::
        Sent whenever i3 changes its binding mode.
+window (3)::
+       Sent when a client's window is successfully reparented (that is when i3
+       has finished fitting it into a container).
 
 *Example:*
 --------------------------------------------------------------------
@@ -696,6 +699,30 @@ mode is simply named default.
 { "change": "default" }
 ---------------------------
 
+=== window event
+
+This event consists of a single serialized map containing a property
++change (string)+ which currently can indicate only that a new window
+has been successfully reparented (the value will be "new").
+
+Additionally a +container (object)+ field will be present, which consists
+of the window's parent container. Be aware that the container will hold
+the initial name of the newly reparented window (e.g. if you run urxvt
+with a shell that changes the title, you will still at this point get the
+window title as "urxvt").
+
+*Example:*
+---------------------------
+{
+ "change": "new",
+ "container": {
+  "id": 35569536,
+  "type": 2,
+  ...
+ }
+}
+---------------------------
+
 == See also (existing libraries)
 
 [[libraries]]
index 2380edab30c79437cd9aca1de1fbb784f11b810b..2a3321b50302727281a6838baf893a5c345669d0 100644 (file)
@@ -96,4 +96,7 @@ typedef struct i3_ipc_header {
 /* The output event will be triggered upon mode changes */
 #define I3_IPC_EVENT_MODE                       (I3_IPC_EVENT_MASK | 2)
 
+/* The window event will be triggered upon window changes */
+#define I3_IPC_EVENT_WINDOW                     (I3_IPC_EVENT_MASK | 3)
+
 #endif
index ff7fdc6d09bae81c641cbc66162667995f00ec91..a231991204d11c771f85b68a699b31a091150b75 100644 (file)
@@ -10,6 +10,9 @@
  *
  */
 #include "all.h"
+#include "yajl_utils.h"
+
+#include <yajl/yajl_gen.h>
 
 /*
  * Go through all existing windows (if the window manager is restarted) and manage them
@@ -72,6 +75,35 @@ void restore_geometry(void) {
     xcb_aux_sync(conn);
 }
 
+/*
+ * The following function sends a new window event, which consists
+ * of fields "change" and "container", the latter containing a dump
+ * of the window's container.
+ *
+ */
+static void ipc_send_window_new_event(Con *con) {
+    setlocale(LC_NUMERIC, "C");
+    yajl_gen gen = ygenalloc();
+
+    y(map_open);
+
+    ystr("change");
+    ystr("new");
+
+    ystr("container");
+    dump_node(gen, con, false);
+
+    y(map_close);
+
+    const unsigned char *payload;
+    ylength length;
+    y(get_buf, &payload, &length);
+
+    ipc_send_event("window", I3_IPC_EVENT_WINDOW, (const char *)payload);
+    y(free);
+    setlocale(LC_NUMERIC, "");
+}
+
 /*
  * Do some sanity checks and then reparent the window.
  *
@@ -428,6 +460,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     }
     tree_render();
 
+    /* Send an event about window creation */
+    ipc_send_window_new_event(nc);
+
 geom_out:
     free(geom);
 out:
diff --git a/testcases/t/205-ipc-windows.t b/testcases/t/205-ipc-windows.t
new file mode 100644 (file)
index 0000000..e3b7196
--- /dev/null
@@ -0,0 +1,43 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+#   (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+#   (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+#   (unless you are already familiar with Perl)
+
+use i3test;
+
+my $i3 = i3(get_socket_path());
+$i3->connect()->recv;
+
+################################
+# Window event
+################################
+
+# Events
+
+my $new = AnyEvent->condvar;
+$i3->subscribe({
+    window => sub {
+        my ($event) = @_;
+        $new->send($event->{change} eq 'new');
+    }
+})->recv;
+
+open_window;
+
+my $t;
+$t = AnyEvent->timer(after => 0.5, cb => sub { $new->send(0); });
+
+ok($new->recv, 'Window "new" event received');
+
+done_testing;