From e277d4e094a8294f9541048c0a4a6d0cf9c3f0bc Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 13 Dec 2015 16:04:54 -0500 Subject: [PATCH] Subscribe to workspace change events and redraw --- common/ipc-client.c | 31 ++++++---- include/ipc-client.h | 5 ++ swaybar/main.c | 140 ++++++++++++++++++++++++------------------- 3 files changed, 103 insertions(+), 73 deletions(-) diff --git a/common/ipc-client.c b/common/ipc-client.c index 5d2d5808..e92a09fe 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -39,20 +39,9 @@ int ipc_open_socket(const char *socket_path) { return socketfd; } -char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { +char *ipc_recv_response(int socketfd, uint32_t *len) { char data[ipc_header_size]; uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); - memcpy(data, ipc_magic, sizeof(ipc_magic)); - data32[0] = *len; - data32[1] = type; - - if (write(socketfd, data, ipc_header_size) == -1) { - sway_abort("Unable to send IPC header"); - } - - if (write(socketfd, payload, *len) == -1) { - sway_abort("Unable to send IPC payload"); - } size_t total = 0; while (total < ipc_header_size) { @@ -77,3 +66,21 @@ char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint3 return response; } + +char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { + char data[ipc_header_size]; + uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); + memcpy(data, ipc_magic, sizeof(ipc_magic)); + data32[0] = *len; + data32[1] = type; + + if (write(socketfd, data, ipc_header_size) == -1) { + sway_abort("Unable to send IPC header"); + } + + if (write(socketfd, payload, *len) == -1) { + sway_abort("Unable to send IPC payload"); + } + + return ipc_recv_response(socketfd, len); +} diff --git a/include/ipc-client.h b/include/ipc-client.h index e6c988c2..a4cfd87f 100644 --- a/include/ipc-client.h +++ b/include/ipc-client.h @@ -16,5 +16,10 @@ int ipc_open_socket(const char *socket_path); * the length of the buffer returned from sway. */ char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len); +/** + * Receives a single IPC resposne and returns the buffer. len will be updated + * with the length of the buffer returned from sway. + */ +char *ipc_recv_response(int socketfd, uint32_t *len); #endif diff --git a/swaybar/main.c b/swaybar/main.c index c7c4ed47..56c69aff 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -3,7 +3,11 @@ #include #include #include +#include #include +#include +#include +#include #include "ipc-client.h" #include "readline.h" #include "client/registry.h" @@ -93,8 +97,74 @@ void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { (color & 0xFF) / 256.0); } +void ipc_update_workspaces() { + if (workspaces) { + free_flat_list(workspaces); + } + workspaces = create_list(); + + uint32_t len = 0; + char *res = ipc_single_command(socketfd, IPC_GET_WORKSPACES, NULL, &len); + json_object *results = json_tokener_parse(res); + + int i; + for (i = 0; i < json_object_array_length(results); ++i) { + json_object *ws_json = json_object_array_get_idx(results, i); + json_object *num, *name, *visible, *focused, *out, *urgent; + json_object_object_get_ex(ws_json, "num", &num); + json_object_object_get_ex(ws_json, "name", &name); + json_object_object_get_ex(ws_json, "visible", &visible); + json_object_object_get_ex(ws_json, "focused", &focused); + json_object_object_get_ex(ws_json, "output", &out); + json_object_object_get_ex(ws_json, "urgent", &urgent); + + if (strcmp(json_object_get_string(out), output) == 0) { + struct workspace *ws = malloc(sizeof(struct workspace)); + ws->num = json_object_get_int(num); + ws->name = strdup(json_object_get_string(name)); + ws->visible = json_object_get_boolean(visible); + ws->focused = json_object_get_boolean(focused); + ws->urgent = json_object_get_boolean(urgent); + list_add(workspaces, ws); + sway_log(L_INFO, "Handling workspace %s", ws->name); + } + + json_object_put(num); + json_object_put(name); + json_object_put(visible); + json_object_put(focused); + json_object_put(out); + json_object_put(urgent); + json_object_put(ws_json); + } + + json_object_put(results); + free(res); +} + +void bar_ipc_init(int outputi) { + uint32_t len = 0; + char *res = ipc_single_command(socketfd, IPC_GET_OUTPUTS, NULL, &len); + json_object *outputs = json_tokener_parse(res); + json_object *info = json_object_array_get_idx(outputs, outputi); + json_object *name; + json_object_object_get_ex(info, "name", &name); + output = strdup(json_object_get_string(name)); + free(res); + json_object_put(outputs); + sway_log(L_INFO, "Running on output %s", output); + + const char *subscribe_json = "[ \"workspace\" ]"; + len = strlen(subscribe_json); + res = ipc_single_command(socketfd, IPC_SUBSCRIBE, subscribe_json, &len); + sway_log(L_INFO, "%s", res); + + ipc_update_workspaces(); +} + void update() { - if (!feof(command)) { + int pending; + if (ioctl(fileno(command), FIONREAD, &pending) != -1 && pending > 0) { free(line); line = read_line(command); int l = strlen(line) - 1; @@ -102,6 +172,14 @@ void update() { line[l] = '\0'; } } + if (ioctl(socketfd, FIONREAD, &pending) != -1 && pending > 0) { + sway_log(L_INFO, "data available"); + uint32_t len; + char *buf = ipc_recv_response(socketfd, &len); + sway_log(L_INFO, "%s", buf); + free(buf); + ipc_update_workspaces(); + } } void render() { @@ -155,66 +233,6 @@ void render() { } } -void ipc_update_workspaces() { - if (workspaces) { - free_flat_list(workspaces); - } - workspaces = create_list(); - - uint32_t len = 0; - char *res = ipc_single_command(socketfd, IPC_GET_WORKSPACES, NULL, &len); - json_object *results = json_tokener_parse(res); - - int i; - for (i = 0; i < json_object_array_length(results); ++i) { - json_object *ws_json = json_object_array_get_idx(results, i); - json_object *num, *name, *visible, *focused, *out, *urgent; - json_object_object_get_ex(ws_json, "num", &num); - json_object_object_get_ex(ws_json, "name", &name); - json_object_object_get_ex(ws_json, "visible", &visible); - json_object_object_get_ex(ws_json, "focused", &focused); - json_object_object_get_ex(ws_json, "output", &out); - json_object_object_get_ex(ws_json, "urgent", &urgent); - - if (strcmp(json_object_get_string(out), output) == 0) { - struct workspace *ws = malloc(sizeof(struct workspace)); - ws->num = json_object_get_int(num); - ws->name = strdup(json_object_get_string(name)); - ws->visible = json_object_get_boolean(visible); - ws->focused = json_object_get_boolean(focused); - ws->urgent = json_object_get_boolean(urgent); - list_add(workspaces, ws); - sway_log(L_INFO, "Handling workspace %s", ws->name); - } - - json_object_put(num); - json_object_put(name); - json_object_put(visible); - json_object_put(focused); - json_object_put(out); - json_object_put(urgent); - json_object_put(ws_json); - } - - json_object_put(results); - free(res); -} - -void bar_ipc_init(int outputi) { - uint32_t len = 0; - char *res = ipc_single_command(socketfd, IPC_GET_OUTPUTS, NULL, &len); - json_object *outputs = json_tokener_parse(res); - json_object *info = json_object_array_get_idx(outputs, outputi); - json_object *name; - json_object_object_get_ex(info, "name", &name); - output = strdup(json_object_get_string(name)); - free(res); - json_object_put(outputs); - sway_log(L_INFO, "Running on output %s", output); - - ipc_update_workspaces(); -} - int main(int argc, char **argv) { init_log(L_INFO); registry = registry_poll();