diff --git a/docs/ipc b/docs/ipc index e1a1fc5f..8cfb21d0 100644 --- 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]] diff --git a/include/i3/ipc.h b/include/i3/ipc.h index 2380edab..2a3321b5 100644 --- a/include/i3/ipc.h +++ b/include/i3/ipc.h @@ -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 diff --git a/src/manage.c b/src/manage.c index ff7fdc6d..a2319912 100644 --- a/src/manage.c +++ b/src/manage.c @@ -10,6 +10,9 @@ * */ #include "all.h" +#include "yajl_utils.h" + +#include /* * 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 index 00000000..e3b7196c --- /dev/null +++ b/testcases/t/205-ipc-windows.t @@ -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;