i3 - improved tiling WM


i3-msg: support SUBSCRIBE message type

Patch status: rejected

Patch by Vivien Didelot

Long description:

If i3-msg is invoked with -t subscribe, it will wait for the first event
corresponding to the given payload, before exiting.

For instance, get the number of the next focused workspace with:

    i3-msg -t subscribe '[ "workspace", "focus" ]' | sed 1d | jshon -e current -e num

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>

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

b/i3-msg/main.c

21
@@ -145,6 +145,8 @@ int main(int argc, char *argv[]) {
22
                 message_type = I3_IPC_MESSAGE_TYPE_COMMAND;
23
             else if (strcasecmp(optarg, "get_workspaces") == 0)
24
                 message_type = I3_IPC_MESSAGE_TYPE_GET_WORKSPACES;
25
+            else if (strcasecmp(optarg, "subscribe") == 0)
26
+                message_type = I3_IPC_MESSAGE_TYPE_SUBSCRIBE;
27
             else if (strcasecmp(optarg, "get_outputs") == 0)
28
                 message_type = I3_IPC_MESSAGE_TYPE_GET_OUTPUTS;
29
             else if (strcasecmp(optarg, "get_tree") == 0)
30
@@ -157,7 +159,7 @@ int main(int argc, char *argv[]) {
31
                 message_type = I3_IPC_MESSAGE_TYPE_GET_VERSION;
32
             else {
33
                 printf("Unknown message type\n");
34
-                printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_version\n");
35
+                printf("Known types: command, get_workspaces, subscribe, get_outputs, get_tree, get_marks, get_bar_config, get_version\n");
36
                 exit(EXIT_FAILURE);
37
             }
38
         } else if (o == 'q') {
39
@@ -219,16 +221,19 @@ int main(int argc, char *argv[]) {
40
     uint32_t reply_type;
41
     uint8_t *reply;
42
     int ret;
43
+recv:
44
     if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) {
45
         if (ret == -1)
46
             err(EXIT_FAILURE, "IPC: read()");
47
         exit(1);
48
     }
49
-    if (reply_type != message_type)
50
+
51
+    /* For events, the highest bit of the message type is set to 1. */
52
+    if (reply_type != message_type && (message_type == I3_IPC_MESSAGE_TYPE_SUBSCRIBE && !(reply_type >> 31)))
53
         errx(EXIT_FAILURE, "IPC: Received reply of type %d but expected %d", reply_type, message_type);
54
-    /* For the reply of commands, have a look if that command was successful.
55
+    /* For the reply of commands or subscribes, have a look if that command was successful.
56
      * If not, nicely format the error message. */
57
-    if (reply_type == I3_IPC_MESSAGE_TYPE_COMMAND) {
58
+    if (reply_type == I3_IPC_MESSAGE_TYPE_COMMAND || reply_type == I3_IPC_MESSAGE_TYPE_SUBSCRIBE) {
59
         yajl_handle handle;
60
         handle = yajl_alloc(&reply_callbacks, NULL, NULL);
61
         yajl_status state = yajl_parse(handle, (const unsigned char *)reply, reply_length);
62
@@ -246,6 +251,9 @@ int main(int argc, char *argv[]) {
63
     printf("%.*s\n", reply_length, reply);
64
     free(reply);
65
 
66
+    if (reply_type == I3_IPC_MESSAGE_TYPE_SUBSCRIBE)
67
+        goto recv;
68
+
69
     close(sockfd);
70
 
71
     return 0;