]> git.sur5r.net Git - i3/i3/commitdiff
Include workspace con in workspace event
authorTony Crisci <tony@dubstepdish.com>
Sat, 20 Dec 2014 04:43:47 +0000 (23:43 -0500)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 22 Dec 2014 08:47:31 +0000 (09:47 +0100)
Send the affected workspace in the "current" property for each workspace
event for any type of workspace event that affects a particular
workspace.

fixes #1411

docs/ipc
include/ipc.h
src/commands.c
src/con.c
src/ipc.c
src/move.c
src/workspace.c
testcases/t/115-ipc-workspaces.t
testcases/t/227-ipc-workspace-empty.t

index 4a2b1df91ed27ca7dd5565b9809b89345265bf7a..ff7c8aaeb0f185299520dc5f271460060a8d13be 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -668,15 +668,16 @@ if ($is_event) {
 
 This event consists of a single serialized map containing a property
 +change (string)+ which indicates the type of the change ("focus", "init",
-"empty", "urgent").
-
-Moreover, when the change is "focus", an +old (object)+ and a +current
-(object)+ properties will be present with the previous and current
-workspace respectively.  When the first switch occurs (when i3 focuses
-the workspace visible at the beginning) there is no previous
-workspace, and the +old+ property will be set to +null+.  Also note
-that if the previous is empty it will get destroyed when switching,
-but will still be present in the "old" property.
+"empty", "urgent"). A +current (object)+ property will be present with the
+affected workspace whenever the type of event affects a workspace (otherwise,
+it will be +null).
+
+When the change is "focus", an +old (object)+ property will be present with the
+previous workspace.  When the first switch occurs (when i3 focuses the
+workspace visible at the beginning) there is no previous workspace, and the
++old+ property will be set to +null+.  Also note that if the previous is empty
+it will get destroyed when switching, but will still be present in the "old"
+property.
 
 *Example:*
 ---------------------
index 77dcad210e8c7b0e35b143a22dadf815c5bbfab8..96a60a1f29d27ea7f3b9ea719269ea269fef35f5 100644 (file)
@@ -89,11 +89,17 @@ void ipc_shutdown(void);
 void dump_node(yajl_gen gen, Con *con, bool inplace_restart);
 
 /**
- * For the workspace "focus" event we send, along the usual "change" field,
- * also the current and previous workspace, in "current" and "old"
- * respectively.
+ * Generates a json workspace event. Returns a dynamically allocated yajl
+ * generator. Free with yajl_gen_free().
  */
-void ipc_send_workspace_focus_event(Con *current, Con *old);
+yajl_gen ipc_marshal_workspace_event(const char *change, Con *current, Con *old);
+
+/**
+ * For the workspace events we send, along with the usual "change" field, also
+ * the workspace container in "current". For focus events, we send the
+ * previously focused workspace in "old".
+ */
+void ipc_send_workspace_event(const char *change, Con *current, Con *old);
 
 /**
  * For the window events we send, along the usual "change" field,
index e87617c97673d97e23ae3c6a48bbc45020513488..498c25c85b7aa5a33578219bf637e30cd8c877c8 100644 (file)
@@ -944,7 +944,7 @@ void cmd_append_layout(I3_CMD, char *path) {
     restore_open_placeholder_windows(parent);
 
     if (content == JSON_CONTENT_WORKSPACE)
-        ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"restored\"}");
+        ipc_send_workspace_event("restored", parent, NULL);
 
     cmd_output->needs_tree_render = true;
 }
@@ -1313,7 +1313,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
                 create_workspace_on_output(current_output, ws->parent);
 
             /* notify the IPC listeners */
-            ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
+            ipc_send_workspace_event("init", ws, NULL);
         }
         DLOG("Detaching\n");
 
@@ -1334,7 +1334,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
         TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
         floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
 
-        ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"move\"}");
+        ipc_send_workspace_event("move", ws, NULL);
         if (workspace_was_visible) {
             /* Focus the moved workspace on the destination output. */
             workspace_show(ws);
@@ -1761,7 +1761,7 @@ void cmd_reload(I3_CMD) {
     load_configuration(conn, NULL, true);
     x_set_i3_atoms();
     /* Send an IPC event just in case the ws names have changed */
-    ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"reload\"}");
+    ipc_send_workspace_event("reload", NULL, NULL);
     /* Send an update event for the barconfig just in case it has changed */
     update_barconfig();
 
@@ -2040,7 +2040,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
     cmd_output->needs_tree_render = true;
     ysuccess(true);
 
-    ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"rename\"}");
+    ipc_send_workspace_event("rename", workspace, NULL);
     ewmh_update_desktop_names();
     ewmh_update_desktop_viewport();
     ewmh_update_current_desktop();
index 3293a9fd89f940cad06144d5d7f2553b8f362c95..38ea0585e17f0887e178d0304f04ea6153a62e85 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -12,6 +12,7 @@
  *
  */
 #include "all.h"
+#include "yajl_utils.h"
 
 static void con_on_remove_child(Con *con);
 
@@ -1435,8 +1436,15 @@ static void con_on_remove_child(Con *con) {
     if (con->type == CT_WORKSPACE) {
         if (TAILQ_EMPTY(&(con->focus_head)) && !workspace_is_visible(con)) {
             LOG("Closing old workspace (%p / %s), it is empty\n", con, con->name);
+            yajl_gen gen = ipc_marshal_workspace_event("empty", con, NULL);
             tree_close(con, DONT_KILL_WINDOW, false, false);
-            ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
+
+            const unsigned char *payload;
+            ylength length;
+            y(get_buf, &payload, &length);
+            ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
+
+            y(free);
         }
         return;
     }
index c70ec323da334dddf146dfd0bf9006e106ef997b..7dbb6632cb88191f77a86cfe398efaeff1c57297 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -1120,21 +1120,23 @@ int ipc_create_socket(const char *filename) {
 }
 
 /*
- * For the workspace "focus" event we send, along the usual "change" field,
- * also the current and previous workspace, in "current" and "old"
- * respectively.
+ * Generates a json workspace event. Returns a dynamically allocated yajl
+ * generator. Free with yajl_gen_free().
  */
-void ipc_send_workspace_focus_event(Con *current, Con *old) {
+yajl_gen ipc_marshal_workspace_event(const char *change, Con *current, Con *old) {
     setlocale(LC_NUMERIC, "C");
     yajl_gen gen = ygenalloc();
 
     y(map_open);
 
     ystr("change");
-    ystr("focus");
+    ystr(change);
 
     ystr("current");
-    dump_node(gen, current, false);
+    if (current == NULL)
+        y(null);
+    else
+        dump_node(gen, current, false);
 
     ystr("old");
     if (old == NULL)
@@ -1144,13 +1146,26 @@ void ipc_send_workspace_focus_event(Con *current, Con *old) {
 
     y(map_close);
 
+    setlocale(LC_NUMERIC, "");
+
+    return gen;
+}
+
+/*
+ * For the workspace events we send, along with the usual "change" field, also
+ * the workspace container in "current". For focus events, we send the
+ * previously focused workspace in "old".
+ */
+void ipc_send_workspace_event(const char *change, Con *current, Con *old) {
+    yajl_gen gen = ipc_marshal_workspace_event(change, current, old);
+
     const unsigned char *payload;
     ylength length;
     y(get_buf, &payload, &length);
 
     ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
+
     y(free);
-    setlocale(LC_NUMERIC, "");
 }
 
 /**
index 9c0f310f769f641fc2dfb58e92446f269f78650e..1999a1fe901853d06924df49f5c026cc4f7977e2 100644 (file)
@@ -128,7 +128,7 @@ static void move_to_output_directed(Con *con, direction_t direction) {
 
     tree_flatten(croot);
 
-    ipc_send_workspace_focus_event(ws, old_ws);
+    ipc_send_workspace_event("focus", ws, old_ws);
 }
 
 /*
index 1bb619c3a65a07b6899bff834332d050e98012f5..a30566339f246b40e10de9932d1eac7f82a1ab6e 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 #include "all.h"
+#include "yajl_utils.h"
 
 /* Stores a copy of the name of the last used workspace for the workspace
  * back-and-forth switching. */
@@ -91,7 +92,7 @@ Con *workspace_get(const char *num, bool *created) {
 
         con_attach(workspace, content, false);
 
-        ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
+        ipc_send_workspace_event("init", workspace, NULL);
         ewmh_update_number_of_desktops();
         ewmh_update_desktop_names();
         ewmh_update_desktop_viewport();
@@ -409,7 +410,7 @@ static void _workspace_show(Con *workspace) {
     } else
         con_focus(next);
 
-    ipc_send_workspace_focus_event(workspace, current);
+    ipc_send_workspace_event("focus", workspace, current);
 
     DLOG("old = %p / %s\n", old, (old ? old->name : "(null)"));
     /* Close old workspace if necessary. This must be done *after* doing
@@ -421,8 +422,16 @@ static void _workspace_show(Con *workspace) {
         /* check if this workspace is currently visible */
         if (!workspace_is_visible(old)) {
             LOG("Closing old workspace (%p / %s), it is empty\n", old, old->name);
+            yajl_gen gen = ipc_marshal_workspace_event("empty", old, NULL);
             tree_close(old, DONT_KILL_WINDOW, false, false);
-            ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
+
+            const unsigned char *payload;
+            ylength length;
+            y(get_buf, &payload, &length);
+            ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
+
+            y(free);
+
             ewmh_update_number_of_desktops();
             ewmh_update_desktop_names();
             ewmh_update_desktop_viewport();
@@ -766,7 +775,7 @@ void workspace_update_urgent_flag(Con *ws) {
     DLOG("Workspace urgency flag changed from %d to %d\n", old_flag, ws->urgent);
 
     if (old_flag != ws->urgent)
-        ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"urgent\"}");
+        ipc_send_workspace_event("urgent", ws, NULL);
 }
 
 /*
index 29837430b34d06c0bd37865ed4cc432c561ed829..2bcc6d602f7ec4b57c317f111926a29c81926235 100644 (file)
@@ -23,7 +23,7 @@ $i3->connect()->recv;
 # Workspaces requests and events
 ################################
 
-my $focused = get_ws(focused_ws());
+my $old_ws = get_ws(focused_ws());
 
 # Events
 
@@ -36,15 +36,11 @@ $i3->subscribe({
     workspace => sub {
         my ($event) = @_;
         if ($event->{change} eq 'init') {
-            $init->send(1);
+            $init->send($event);
         } elsif ($event->{change} eq 'focus') {
-            # Check that we have the old and new workspace
-            $focus->send(
-                $event->{current}->{name} == '2' &&
-                $event->{old}->{name} == $focused->{name}
-            );
+            $focus->send($event);
         } elsif ($event->{change} eq 'empty') {
-            $empty->send(1);
+            $empty->send($event);
         }
     }
 })->recv;
@@ -61,8 +57,20 @@ $t = AnyEvent->timer(
     }
 );
 
-ok($init->recv, 'Workspace "init" event received');
-ok($focus->recv, 'Workspace "focus" event received');
-ok($empty->recv, 'Workspace "empty" event received');
+my $init_event = $init->recv;
+my $focus_event = $focus->recv;
+my $empty_event = $empty->recv;
+
+my $current_ws = get_ws(focused_ws());
+
+ok($init_event, 'workspace "init" event received');
+is($init_event->{current}->{id}, $current_ws->{id}, 'the "current" property should contain the initted workspace con');
+
+ok($focus_event, 'workspace "focus" event received');
+is($focus_event->{current}->{id}, $current_ws->{id}, 'the "current" property should contain the focused workspace con');
+is($focus_event->{old}->{id}, $old_ws->{id}, 'the "old" property should contain the workspace con that was focused last');
+
+ok($empty_event, 'workspace "empty" event received');
+is($empty_event->{current}->{id}, $old_ws->{id}, 'the "current" property should contain the emptied workspace con');
 
 done_testing;
index 185910e8886a37ff5433e1c210616c1093e9c3e1..0c67423eaf4cfe19839a96866ccf07fdaedb3985 100644 (file)
@@ -50,6 +50,7 @@ subtest 'Workspace empty event upon switch', sub {
 
     my $event = $cond->recv;
     is($event->{change}, 'empty', '"Empty" event received upon workspace switch');
+    is($event->{current}->{name}, $ws1, '"current" property should be set to the workspace con');
 };
 
 ################################################################################
@@ -116,6 +117,7 @@ subtest 'Workspace empty event upon window close', sub {
 
     my $event = $cond->recv;
     is($event->{change}, 'empty', '"Empty" event received upon window close');
+    is($event->{current}->{name}, $ws1, '"current" property should be set to the workspace con');
 };
 
 }