]> git.sur5r.net Git - i3/i3/blobdiff - src/ipc.c
Change the names of parser result structs
[i3/i3] / src / ipc.c
index b907e4ec6bdf57579880d365b9dd04df0b290b8e..c3b82b519a07820d2367a01d092c4eaa1e55cea9 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -117,7 +117,7 @@ IPC_HANDLER(command) {
     char *command = scalloc(message_size + 1);
     strncpy(command, (const char*)message, message_size);
     LOG("IPC: received: *%s*\n", command);
-    struct CommandResult *command_output = parse_command((const char*)command);
+    struct CommandResultIR *command_output = parse_command((const char*)command);
     free(command);
 
     if (command_output->needs_tree_render)
@@ -423,6 +423,138 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
     y(map_close);
 }
 
+static void dump_bar_config(yajl_gen gen, Barconfig *config) {
+    y(map_open);
+
+    ystr("id");
+    ystr(config->id);
+
+    if (config->num_outputs > 0) {
+        ystr("outputs");
+        y(array_open);
+        for (int c = 0; c < config->num_outputs; c++)
+            ystr(config->outputs[c]);
+        y(array_close);
+    }
+
+#define YSTR_IF_SET(name) \
+    do { \
+        if (config->name) { \
+            ystr( # name); \
+            ystr(config->name); \
+        } \
+    } while (0)
+
+    YSTR_IF_SET(tray_output);
+    YSTR_IF_SET(socket_path);
+
+    ystr("mode");
+    switch (config->mode) {
+        case M_HIDE:
+            ystr("hide");
+            break;
+        case M_INVISIBLE:
+            ystr("invisible");
+            break;
+        case M_DOCK:
+        default:
+            ystr("dock");
+            break;
+    }
+
+    ystr("hidden_state");
+    switch (config->hidden_state) {
+        case S_SHOW:
+            ystr("show");
+            break;
+        case S_HIDE:
+        default:
+            ystr("hide");
+            break;
+    }
+
+    ystr("modifier");
+    switch (config->modifier) {
+        case M_CONTROL:
+            ystr("ctrl");
+            break;
+        case M_SHIFT:
+            ystr("shift");
+            break;
+        case M_MOD1:
+            ystr("Mod1");
+            break;
+        case M_MOD2:
+            ystr("Mod2");
+            break;
+        case M_MOD3:
+            ystr("Mod3");
+            break;
+            /*
+               case M_MOD4:
+               ystr("Mod4");
+               break;
+               */
+        case M_MOD5:
+            ystr("Mod5");
+            break;
+        default:
+            ystr("Mod4");
+            break;
+    }
+
+    ystr("position");
+    if (config->position == P_BOTTOM)
+        ystr("bottom");
+    else ystr("top");
+
+    YSTR_IF_SET(status_command);
+    YSTR_IF_SET(font);
+
+    ystr("workspace_buttons");
+    y(bool, !config->hide_workspace_buttons);
+
+    ystr("strip_workspace_numbers");
+    y(bool, config->strip_workspace_numbers);
+
+    ystr("binding_mode_indicator");
+    y(bool, !config->hide_binding_mode_indicator);
+
+    ystr("verbose");
+    y(bool, config->verbose);
+
+#undef YSTR_IF_SET
+#define YSTR_IF_SET(name) \
+    do { \
+        if (config->colors.name) { \
+            ystr( # name); \
+            ystr(config->colors.name); \
+        } \
+    } while (0)
+
+    ystr("colors");
+    y(map_open);
+    YSTR_IF_SET(background);
+    YSTR_IF_SET(statusline);
+    YSTR_IF_SET(separator);
+    YSTR_IF_SET(focused_workspace_border);
+    YSTR_IF_SET(focused_workspace_bg);
+    YSTR_IF_SET(focused_workspace_text);
+    YSTR_IF_SET(active_workspace_border);
+    YSTR_IF_SET(active_workspace_bg);
+    YSTR_IF_SET(active_workspace_text);
+    YSTR_IF_SET(inactive_workspace_border);
+    YSTR_IF_SET(inactive_workspace_bg);
+    YSTR_IF_SET(inactive_workspace_text);
+    YSTR_IF_SET(urgent_workspace_border);
+    YSTR_IF_SET(urgent_workspace_bg);
+    YSTR_IF_SET(urgent_workspace_text);
+    y(map_close);
+
+    y(map_close);
+#undef YSTR_IF_SET
+}
+
 IPC_HANDLER(tree) {
     setlocale(LC_NUMERIC, "C");
     yajl_gen gen = ygenalloc();
@@ -651,141 +783,19 @@ IPC_HANDLER(get_bar_config) {
         break;
     }
 
-    y(map_open);
-
     if (!config) {
         /* If we did not find a config for the given ID, the reply will contain
          * a null 'id' field. */
+        y(map_open);
+
         ystr("id");
         y(null);
-    } else {
-        ystr("id");
-        ystr(config->id);
-
-        if (config->num_outputs > 0) {
-            ystr("outputs");
-            y(array_open);
-            for (int c = 0; c < config->num_outputs; c++)
-                ystr(config->outputs[c]);
-            y(array_close);
-        }
-
-#define YSTR_IF_SET(name) \
-        do { \
-            if (config->name) { \
-                ystr( # name); \
-                ystr(config->name); \
-            } \
-        } while (0)
-
-        YSTR_IF_SET(tray_output);
-        YSTR_IF_SET(socket_path);
-
-        ystr("mode");
-        switch (config->mode) {
-            case M_HIDE:
-                ystr("hide");
-                break;
-            case M_INVISIBLE:
-                ystr("invisible");
-                break;
-            case M_DOCK:
-            default:
-                ystr("dock");
-                break;
-        }
-
-        ystr("hidden_state");
-        switch (config->hidden_state) {
-            case S_SHOW:
-                ystr("show");
-                break;
-            case S_HIDE:
-            default:
-                ystr("hide");
-                break;
-        }
-
-        ystr("modifier");
-        switch (config->modifier) {
-            case M_CONTROL:
-                ystr("ctrl");
-                break;
-            case M_SHIFT:
-                ystr("shift");
-                break;
-            case M_MOD1:
-                ystr("Mod1");
-                break;
-            case M_MOD2:
-                ystr("Mod2");
-                break;
-            case M_MOD3:
-                ystr("Mod3");
-                break;
-            /*
-            case M_MOD4:
-                ystr("Mod4");
-                break;
-            */
-            case M_MOD5:
-                ystr("Mod5");
-                break;
-            default:
-                ystr("Mod4");
-                break;
-        }
-
-        ystr("position");
-        if (config->position == P_BOTTOM)
-            ystr("bottom");
-        else ystr("top");
-
-        YSTR_IF_SET(status_command);
-        YSTR_IF_SET(font);
-
-        ystr("workspace_buttons");
-        y(bool, !config->hide_workspace_buttons);
-
-        ystr("binding_mode_indicator");
-        y(bool, !config->hide_binding_mode_indicator);
 
-        ystr("verbose");
-        y(bool, config->verbose);
-
-#undef YSTR_IF_SET
-#define YSTR_IF_SET(name) \
-        do { \
-            if (config->colors.name) { \
-                ystr( # name); \
-                ystr(config->colors.name); \
-            } \
-        } while (0)
-
-        ystr("colors");
-        y(map_open);
-        YSTR_IF_SET(background);
-        YSTR_IF_SET(statusline);
-        YSTR_IF_SET(separator);
-        YSTR_IF_SET(focused_workspace_border);
-        YSTR_IF_SET(focused_workspace_bg);
-        YSTR_IF_SET(focused_workspace_text);
-        YSTR_IF_SET(active_workspace_border);
-        YSTR_IF_SET(active_workspace_bg);
-        YSTR_IF_SET(active_workspace_text);
-        YSTR_IF_SET(inactive_workspace_border);
-        YSTR_IF_SET(inactive_workspace_bg);
-        YSTR_IF_SET(inactive_workspace_text);
-        YSTR_IF_SET(urgent_workspace_border);
-        YSTR_IF_SET(urgent_workspace_bg);
-        YSTR_IF_SET(urgent_workspace_text);
         y(map_close);
-
-#undef YSTR_IF_SET
+    } else {
+        dump_bar_config(gen, config);
     }
 
-    y(map_close);
-
     const unsigned char *payload;
     ylength length;
     y(get_buf, &payload, &length);
@@ -827,7 +837,6 @@ static int add_subscription(void *extra, const unsigned char *s,
  */
 IPC_HANDLER(subscribe) {
     yajl_handle p;
-    yajl_callbacks callbacks;
     yajl_status stat;
     ipc_client *current, *client = NULL;
 
@@ -846,8 +855,9 @@ IPC_HANDLER(subscribe) {
     }
 
     /* Setup the JSON parser */
-    memset(&callbacks, 0, sizeof(yajl_callbacks));
-    callbacks.yajl_string = add_subscription;
+    static yajl_callbacks callbacks = {
+        .yajl_string = add_subscription,
+    };
 
     p = yalloc(&callbacks, (void*)client);
     stat = yajl_parse(p, (const unsigned char*)message, message_size);
@@ -894,14 +904,16 @@ handler_t handlers[8] = {
 static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) {
     uint32_t message_type;
     uint32_t message_length;
-    uint8_t *message;
+    uint8_t *message = NULL;
 
     int ret = ipc_recv_message(w->fd, &message_type, &message_length, &message);
     /* EOF or other error */
     if (ret < 0) {
         /* Was this a spurious read? See ev(3) */
-        if (ret == -1 && errno == EAGAIN)
+        if (ret == -1 && errno == EAGAIN) {
+            FREE(message);
             return;
+        }
 
         /* If not, there was some kind of error. We don’t bother
          * and close the connection */
@@ -924,6 +936,7 @@ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) {
 
         ev_io_stop(EV_A_ w);
         free(w);
+        FREE(message);
 
         DLOG("IPC: client disconnected\n");
         return;
@@ -935,6 +948,8 @@ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) {
         handler_t h = handlers[message_type];
         h(w->fd, message, 0, message_length, message_type);
     }
+
+    FREE(message);
 }
 
 /*
@@ -1022,3 +1037,86 @@ int ipc_create_socket(const char *filename) {
     current_socketpath = resolved;
     return sockfd;
 }
+
+/*
+ * For the workspace "focus" event we send, along the usual "change" field,
+ * also the current and previous workspace, in "current" and "old"
+ * respectively.
+ */
+void ipc_send_workspace_focus_event(Con *current, Con *old) {
+    setlocale(LC_NUMERIC, "C");
+    yajl_gen gen = ygenalloc();
+
+    y(map_open);
+
+    ystr("change");
+    ystr("focus");
+
+    ystr("current");
+    dump_node(gen, current, false);
+
+    ystr("old");
+    if (old == NULL)
+        y(null);
+    else
+        dump_node(gen, old, false);
+
+    y(map_close);
+
+    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, "");
+}
+
+/**
+ * For the window events we send, along the usual "change" field,
+ * also the window container, in "container".
+ */
+void ipc_send_window_event(const char *property, Con *con) {
+    DLOG("Issue IPC window %s event (con = %p, window = 0x%08x)\n",
+            property, con, (con->window ? con->window->id : XCB_WINDOW_NONE));
+
+    setlocale(LC_NUMERIC, "C");
+    yajl_gen gen = ygenalloc();
+
+    y(map_open);
+
+    ystr("change");
+    ystr(property);
+
+    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, "");
+}
+
+/**
+ * For the barconfig update events, we send the serialized barconfig.
+ */
+void ipc_send_barconfig_update_event(Barconfig *barconfig) {
+    DLOG("Issue barconfig_update event for id = %s\n", barconfig->id);
+    setlocale(LC_NUMERIC, "C");
+    yajl_gen gen = ygenalloc();
+
+    dump_bar_config(gen, barconfig);
+
+    const unsigned char *payload;
+    ylength length;
+    y(get_buf, &payload, &length);
+
+    ipc_send_event("barconfig_update", I3_IPC_EVENT_BARCONFIG_UPDATE, (const char *)payload);
+    y(free);
+    setlocale(LC_NUMERIC, "");
+}