X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fipc.c;h=7ec2592bad2968de12d738155908bed6b4df814b;hb=c527497a4be64ff8d91d7978211db9358f9cef11;hp=40b6a71269fb6f91b07c5e02bce33383959b2298;hpb=fab8b84db753878ee13adf1c1950e83eff19cacf;p=i3%2Fi3 diff --git a/src/ipc.c b/src/ipc.c index 40b6a712..7ec2592b 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -3,7 +3,7 @@ * * i3 - an improved dynamic tiling window manager * - * © 2009-2010 Michael Stapelberg and contributors + * © 2009-2011 Michael Stapelberg and contributors * * See file LICENSE for license information. * @@ -17,9 +17,12 @@ #include #include #include +#include #include "all.h" +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)) @@ -74,7 +77,7 @@ static void ipc_send_message(int fd, const unsigned char *payload, char msg[buffer_size]; char *walk = msg; - strcpy(walk, "i3-ipc"); + strncpy(walk, "i3-ipc", buffer_size - 1); walk += strlen("i3-ipc"); memcpy(walk, &message_size, sizeof(uint32_t)); walk += sizeof(uint32_t); @@ -144,8 +147,8 @@ IPC_HANDLER(command) { char *command = scalloc(message_size + 1); strncpy(command, (const char*)message, message_size); LOG("IPC: received: *%s*\n", command); - const char *reply = parse_cmd((const char*)command); - tree_render(); + char *reply = parse_cmd((const char*)command); + char *save_reply = reply; free(command); /* If no reply was provided, we just use the default success message */ @@ -153,6 +156,22 @@ IPC_HANDLER(command) { reply = "{\"success\":true}"; ipc_send_message(fd, (const unsigned char*)reply, I3_IPC_REPLY_TYPE_COMMAND, strlen(reply)); + + FREE(save_reply); +} + +static void dump_rect(yajl_gen gen, const char *name, Rect r) { + ystr(name); + y(map_open); + ystr("x"); + y(integer, r.x); + ystr("y"); + y(integer, r.y); + ystr("width"); + y(integer, r.width); + ystr("height"); + y(integer, r.height); + y(map_close); } void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { @@ -164,35 +183,78 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { y(integer, con->type); ystr("orientation"); - y(integer, con->orientation); + switch (con->orientation) { + case NO_ORIENTATION: + ystr("none"); + break; + case HORIZ: + ystr("horizontal"); + break; + case VERT: + ystr("vertical"); + break; + } + + ystr("percent"); + if (con->percent == 0.0) + y(null); + else y(double, con->percent); ystr("urgent"); - y(integer, con->urgent); + y(bool, con->urgent); + + if (con->mark != NULL) { + ystr("mark"); + ystr(con->mark); + } ystr("focused"); - y(integer, (con == focused)); + y(bool, (con == focused)); ystr("layout"); - y(integer, con->layout); + switch (con->layout) { + case L_DEFAULT: + ystr("default"); + break; + case L_STACKED: + ystr("stacked"); + break; + case L_TABBED: + ystr("tabbed"); + break; + case L_DOCKAREA: + ystr("dockarea"); + break; + case L_OUTPUT: + ystr("output"); + break; + } ystr("border"); - y(integer, con->border_style); + switch (con->border_style) { + case BS_NORMAL: + ystr("normal"); + break; + case BS_NONE: + ystr("none"); + break; + case BS_1PIXEL: + ystr("1pixel"); + break; + } - ystr("rect"); - y(map_open); - ystr("x"); - y(integer, con->rect.x); - ystr("y"); - y(integer, con->rect.y); - ystr("width"); - y(integer, con->rect.width); - ystr("height"); - y(integer, con->rect.height); - y(map_close); + dump_rect(gen, "rect", con->rect); + dump_rect(gen, "window_rect", con->window_rect); + dump_rect(gen, "geometry", con->geometry); ystr("name"); ystr(con->name); + if (con->type == CT_WORKSPACE) { + ystr("num"); + y(integer, con->num); + } + ystr("window"); if (con->window) y(integer, con->window->id); @@ -201,8 +263,10 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { ystr("nodes"); y(array_open); Con *node; - TAILQ_FOREACH(node, &(con->nodes_head), nodes) { - dump_node(gen, node, inplace_restart); + if (con->type != CT_DOCKAREA || !inplace_restart) { + TAILQ_FOREACH(node, &(con->nodes_head), nodes) { + dump_node(gen, node, inplace_restart); + } } y(array_close); @@ -223,40 +287,69 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { ystr("fullscreen_mode"); y(integer, con->fullscreen_mode); + ystr("swallows"); + y(array_open); + Match *match; + TAILQ_FOREACH(match, &(con->swallow_head), matches) { + if (match->dock != -1) { + y(map_open); + ystr("dock"); + y(integer, match->dock); + ystr("insert_where"); + y(integer, match->insert_where); + y(map_close); + } + + /* TODO: the other swallow keys */ + } + if (inplace_restart) { if (con->window != NULL) { - ystr("swallows"); - y(array_open); y(map_open); ystr("id"); y(integer, con->window->id); y(map_close); - y(array_close); } } + y(array_close); 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 dump_node(gen, croot, false); + setlocale(LC_NUMERIC, ""); const unsigned char *payload; +#if YAJL_MAJOR >= 2 + size_t length; +#else unsigned int length; +#endif y(get_buf, &payload, &length); ipc_send_message(fd, payload, I3_IPC_REPLY_TYPE_TREE, length); y(free); } + /* * Formats the reply message for a GET_WORKSPACES request and sends it to the * client * */ 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 y(array_open); Con *focused_ws = con_get_workspace(focused); @@ -264,12 +357,14 @@ IPC_HANDLER(get_workspaces) { Con *output; TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { Con *ws; - TAILQ_FOREACH(ws, &(output->nodes_head), nodes) { + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { assert(ws->type == CT_WORKSPACE); y(map_open); ystr("num"); - y(integer, con_num_children(ws)); + if (ws->num == -1) + y(null); + else y(integer, ws->num); ystr("name"); ystr(ws->name); @@ -305,7 +400,11 @@ IPC_HANDLER(get_workspaces) { y(array_close); const unsigned char *payload; +#if YAJL_MAJOR >= 2 + size_t length; +#else unsigned int length; +#endif y(get_buf, &payload, &length); ipc_send_message(fd, payload, I3_IPC_REPLY_TYPE_WORKSPACES, length); @@ -318,7 +417,11 @@ 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 y(array_open); Output *output; @@ -345,7 +448,7 @@ IPC_HANDLER(get_outputs) { ystr("current_workspace"); Con *ws = NULL; - if (output->con && (ws = con_get_fullscreen_con(output->con))) + if (output->con && (ws = con_get_fullscreen_con(output->con, CF_OUTPUT))) ystr(ws->name); else y(null); @@ -355,19 +458,56 @@ IPC_HANDLER(get_outputs) { y(array_close); const unsigned char *payload; +#if YAJL_MAJOR >= 2 + size_t length; +#else unsigned int length; +#endif y(get_buf, &payload, &length); ipc_send_message(fd, payload, I3_IPC_REPLY_TYPE_OUTPUTS, length); y(free); } +/* + * Formats the reply message for a GET_MARKS request and sends it to the + * client + * + */ +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 + y(array_open); + + Con *con; + TAILQ_FOREACH(con, &all_cons, all_cons) + if (con->mark != NULL) + ystr(con->mark); + + y(array_close); + + const unsigned char *payload; + unsigned int length; + y(get_buf, &payload, &length); + + ipc_send_message(fd, payload, I3_IPC_REPLY_TYPE_MARKS, length); + y(free); +} + /* * 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 ipc_client *client = extra; DLOG("should add subscription to extra %p, sub %.*s\n", client, len, s); @@ -417,7 +557,11 @@ 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 stat = yajl_parse(p, (const unsigned char*)message, message_size); if (stat != yajl_status_ok) { unsigned char *err; @@ -440,12 +584,13 @@ IPC_HANDLER(subscribe) { /* The index of each callback function corresponds to the numeric * value of the message type (see include/i3/ipc.h) */ -handler_t handlers[5] = { +handler_t handlers[6] = { handle_command, handle_get_workspaces, handle_subscribe, handle_get_outputs, - handle_tree + handle_tree, + handle_get_marks }; /* @@ -517,7 +662,8 @@ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) { n -= strlen(I3_IPC_MAGIC); /* The next 32 bit after the magic are the message size */ - uint32_t message_size = *((uint32_t*)message); + uint32_t message_size; + memcpy(&message_size, (uint32_t*)message, sizeof(uint32_t)); message += sizeof(uint32_t); n -= sizeof(uint32_t); @@ -527,7 +673,8 @@ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) { } /* The last 32 bits of the header are the message type */ - uint32_t message_type = *((uint32_t*)message); + uint32_t message_type; + memcpy(&message_type, (uint32_t*)message, sizeof(uint32_t)); message += sizeof(uint32_t); n -= sizeof(uint32_t); @@ -566,7 +713,7 @@ void ipc_new_client(EV_P_ struct ev_io *w, int revents) { ev_io_init(package, ipc_receive_message, client, EV_READ); ev_io_start(EV_A_ package); - DLOG("IPC: new client connected\n"); + DLOG("IPC: new client connected on fd %d\n", w->fd); ipc_client *new = scalloc(sizeof(ipc_client)); new->fd = client; @@ -582,6 +729,8 @@ void ipc_new_client(EV_P_ struct ev_io *w, int revents) { int ipc_create_socket(const char *filename) { int sockfd; + FREE(current_socketpath); + char *resolved = resolve_tilde(filename); DLOG("Creating IPC-socket at %s\n", resolved); char *copy = sstrdup(resolved); @@ -611,13 +760,14 @@ int ipc_create_socket(const char *filename) { return -1; } - free(resolved); set_nonblock(sockfd); if (listen(sockfd, 5) < 0) { perror("listen()"); + free(resolved); return -1; } + current_socketpath = resolved; return sockfd; }