X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fipc.c;h=ab12dcb0a88befa7bffbec21d79b9425e3121fec;hb=c964c010f050ae82bb15679333d010afd520d5dd;hp=84ef2c36289adc63736c74583d4b0bd49e6cbcaf;hpb=2252b4f5b956551ad4844deabee0ab38ccc73c99;p=i3%2Fi3 diff --git a/src/ipc.c b/src/ipc.c index 84ef2c36..ab12dcb0 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -10,6 +10,7 @@ * */ #include "all.h" +#include "yajl_utils.h" #include #include @@ -18,14 +19,9 @@ #include #include #include -#include char *current_socketpath = NULL; -/* Shorter names for all those yajl_gen_* functions */ -#define y(x, ...) yajl_gen_ ## x (gen, ##__VA_ARGS__) -#define ystr(str) yajl_gen_string(gen, (unsigned char*)str, strlen(str)) - TAILQ_HEAD(ipc_client_head, ipc_client) all_clients = TAILQ_HEAD_INITIALIZER(all_clients); /* @@ -128,11 +124,7 @@ IPC_HANDLER(command) { tree_render(); const unsigned char *reply; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; yajl_gen_get_buf(command_output->json_gen, &reply, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_COMMAND, @@ -161,11 +153,34 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { y(integer, (long int)con); ystr("type"); - y(integer, con->type); + switch (con->type) { + case CT_ROOT: + ystr("root"); + break; + case CT_OUTPUT: + ystr("output"); + break; + case CT_CON: + ystr("con"); + break; + case CT_FLOATING_CON: + ystr("floating_con"); + break; + case CT_WORKSPACE: + ystr("workspace"); + break; + case CT_DOCKAREA: + ystr("dockarea"); + break; + default: + DLOG("About to dump unknown container type=%d. This is a bug.\n", con->type); + assert(false); + break; + } /* provided for backwards compatibility only. */ ystr("orientation"); - if (!con->split) + if (!con_is_split(con)) ystr("none"); else { if (con_orientation(con) == HORIZ) @@ -202,9 +217,6 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { ystr("focused"); y(bool, (con == focused)); - ystr("split"); - y(bool, con->split); - ystr("layout"); switch (con->layout) { case L_DEFAULT: @@ -294,6 +306,32 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { y(integer, con->window->id); else y(null); + if (con->window && !inplace_restart) { + /* Window properties are useless to preserve when restarting because + * they will be queried again anyway. However, for i3-save-tree(1), + * they are very useful and save i3-save-tree dealing with X11. */ + ystr("window_properties"); + y(map_open); + +#define DUMP_PROPERTY(key, prop_name) do { \ + if (con->window->prop_name != NULL) { \ + ystr(key); \ + ystr(con->window->prop_name); \ + } \ +} while (0) + + DUMP_PROPERTY("class", class_class); + DUMP_PROPERTY("instance", class_instance); + DUMP_PROPERTY("window_role", role); + + if (con->window->name != NULL) { + ystr("title"); + ystr(i3string_as_utf8(con->window->name)); + } + + y(map_close); + } + ystr("nodes"); y(array_open); Con *node; @@ -365,25 +403,22 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { } y(array_close); + if (inplace_restart && con->window != NULL) { + ystr("depth"); + y(integer, con->depth); + } + y(map_close); } IPC_HANDLER(tree) { setlocale(LC_NUMERIC, "C"); -#if YAJL_MAJOR >= 2 - yajl_gen gen = yajl_gen_alloc(NULL); -#else - yajl_gen gen = yajl_gen_alloc(NULL, NULL); -#endif + yajl_gen gen = ygenalloc(); dump_node(gen, croot, false); setlocale(LC_NUMERIC, ""); const unsigned char *payload; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; y(get_buf, &payload, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_TREE, payload); @@ -397,11 +432,7 @@ IPC_HANDLER(tree) { * */ IPC_HANDLER(get_workspaces) { -#if YAJL_MAJOR >= 2 - yajl_gen gen = yajl_gen_alloc(NULL); -#else - yajl_gen gen = yajl_gen_alloc(NULL, NULL); -#endif + yajl_gen gen = ygenalloc(); y(array_open); Con *focused_ws = con_get_workspace(focused); @@ -454,11 +485,7 @@ IPC_HANDLER(get_workspaces) { y(array_close); const unsigned char *payload; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; y(get_buf, &payload, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_WORKSPACES, payload); @@ -471,11 +498,7 @@ IPC_HANDLER(get_workspaces) { * */ IPC_HANDLER(get_outputs) { -#if YAJL_MAJOR >= 2 - yajl_gen gen = yajl_gen_alloc(NULL); -#else - yajl_gen gen = yajl_gen_alloc(NULL, NULL); -#endif + yajl_gen gen = ygenalloc(); y(array_open); Output *output; @@ -515,11 +538,7 @@ IPC_HANDLER(get_outputs) { y(array_close); const unsigned char *payload; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; y(get_buf, &payload, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_OUTPUTS, payload); @@ -532,11 +551,7 @@ IPC_HANDLER(get_outputs) { * */ IPC_HANDLER(get_marks) { -#if YAJL_MAJOR >= 2 - yajl_gen gen = yajl_gen_alloc(NULL); -#else - yajl_gen gen = yajl_gen_alloc(NULL, NULL); -#endif + yajl_gen gen = ygenalloc(); y(array_open); Con *con; @@ -547,11 +562,7 @@ IPC_HANDLER(get_marks) { y(array_close); const unsigned char *payload; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; y(get_buf, &payload, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_MARKS, payload); @@ -563,11 +574,7 @@ IPC_HANDLER(get_marks) { * */ IPC_HANDLER(get_version) { -#if YAJL_MAJOR >= 2 - yajl_gen gen = yajl_gen_alloc(NULL); -#else - yajl_gen gen = yajl_gen_alloc(NULL, NULL); -#endif + yajl_gen gen = ygenalloc(); y(map_open); ystr("major"); @@ -585,11 +592,7 @@ IPC_HANDLER(get_version) { y(map_close); const unsigned char *payload; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; y(get_buf, &payload, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_VERSION, payload); @@ -602,11 +605,7 @@ IPC_HANDLER(get_version) { * */ IPC_HANDLER(get_bar_config) { -#if YAJL_MAJOR >= 2 - yajl_gen gen = yajl_gen_alloc(NULL); -#else - yajl_gen gen = yajl_gen_alloc(NULL, NULL); -#endif + yajl_gen gen = ygenalloc(); /* If no ID was passed, we return a JSON array with all IDs */ if (message_size == 0) { @@ -618,11 +617,7 @@ IPC_HANDLER(get_bar_config) { y(array_close); const unsigned char *payload; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; y(get_buf, &payload, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_BAR_CONFIG, payload); @@ -675,9 +670,29 @@ IPC_HANDLER(get_bar_config) { YSTR_IF_SET(socket_path); ystr("mode"); - if (config->mode == M_HIDE) - ystr("hide"); - else ystr("dock"); + 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) { @@ -720,6 +735,9 @@ IPC_HANDLER(get_bar_config) { 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); @@ -736,6 +754,7 @@ IPC_HANDLER(get_bar_config) { 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); @@ -756,11 +775,7 @@ IPC_HANDLER(get_bar_config) { y(map_close); const unsigned char *payload; -#if YAJL_MAJOR >= 2 - size_t length; -#else - unsigned int length; -#endif + ylength length; y(get_buf, &payload, &length); ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_BAR_CONFIG, payload); @@ -771,13 +786,8 @@ IPC_HANDLER(get_bar_config) { * Callback for the YAJL parser (will be called when a string is parsed). * */ -#if YAJL_MAJOR < 2 static int add_subscription(void *extra, const unsigned char *s, - unsigned int len) { -#else -static int add_subscription(void *extra, const unsigned char *s, - size_t len) { -#endif + ylength len) { ipc_client *client = extra; DLOG("should add subscription to extra %p, sub %.*s\n", client, (int)len, s); @@ -827,11 +837,7 @@ IPC_HANDLER(subscribe) { memset(&callbacks, 0, sizeof(yajl_callbacks)); callbacks.yajl_string = add_subscription; -#if YAJL_MAJOR >= 2 - p = yajl_alloc(&callbacks, NULL, (void*)client); -#else - p = yajl_alloc(&callbacks, NULL, NULL, (void*)client); -#endif + p = yalloc(&callbacks, (void*)client); stat = yajl_parse(p, (const unsigned char*)message, message_size); if (stat != yajl_status_ok) { unsigned char *err; @@ -874,18 +880,16 @@ handler_t handlers[8] = { * */ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) { - char buf[2048]; - int n = read(w->fd, buf, sizeof(buf)); - - /* On error or an empty message, we close the connection */ - if (n <= 0) { -#if 0 - /* FIXME: I get these when closing a client socket, - * therefore we just treat them as an error. Is this - * correct? */ - if (errno == EAGAIN || errno == EWOULDBLOCK) - return; -#endif + uint32_t message_type; + uint32_t message_length; + uint8_t *message; + + 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) + return; /* If not, there was some kind of error. We don’t bother * and close the connection */ @@ -913,51 +917,11 @@ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) { return; } - /* Terminate the message correctly */ - buf[n] = '\0'; - - /* Check if the message starts with the i3 IPC magic code */ - if (n < strlen(I3_IPC_MAGIC)) { - DLOG("IPC: message too short, ignoring\n"); - return; - } - - if (strncmp(buf, I3_IPC_MAGIC, strlen(I3_IPC_MAGIC)) != 0) { - DLOG("IPC: message does not start with the IPC magic\n"); - return; - } - - uint8_t *message = (uint8_t*)buf; - while (n > 0) { - DLOG("IPC: n = %d\n", n); - message += strlen(I3_IPC_MAGIC); - n -= strlen(I3_IPC_MAGIC); - - /* The next 32 bit after the magic are the message size */ - uint32_t message_size; - memcpy(&message_size, (uint32_t*)message, sizeof(uint32_t)); - message += sizeof(uint32_t); - n -= sizeof(uint32_t); - - if (message_size > n) { - DLOG("IPC: Either the message size was wrong or the message was not read completely, dropping\n"); - return; - } - - /* The last 32 bits of the header are the message type */ - uint32_t message_type; - memcpy(&message_type, (uint32_t*)message, sizeof(uint32_t)); - message += sizeof(uint32_t); - n -= sizeof(uint32_t); - - if (message_type >= (sizeof(handlers) / sizeof(handler_t))) - DLOG("Unhandled message type: %d\n", message_type); - else { - handler_t h = handlers[message_type]; - h(w->fd, message, n, message_size, message_type); - } - n -= message_size; - message += message_size; + if (message_type >= (sizeof(handlers) / sizeof(handler_t))) + DLOG("Unhandled message type: %d\n", message_type); + else { + handler_t h = handlers[message_type]; + h(w->fd, message, 0, message_length, message_type); } }