From a20226772ee1236cbeabc6fbb3efdce64e407932 Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Sun, 3 Jan 2016 18:52:53 +0100 Subject: [PATCH 1/3] swaybar: rename ipc_listen_sock.. to ipc_event_sock.. --- swaybar/main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/swaybar/main.c b/swaybar/main.c index cbedb2003..aa761b7d4 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -66,7 +66,7 @@ struct status_block { list_t *status_line = NULL; list_t *workspaces = NULL; -int ipc_socketfd, ipc_listen_socketfd; +int ipc_socketfd, ipc_event_socketfd; pid_t pid; int status_read_fd; char line[1024]; @@ -155,8 +155,8 @@ void swaybar_teardown() { close(ipc_socketfd); } - if (ipc_listen_socketfd) { - close(ipc_listen_socketfd); + if (ipc_event_socketfd) { + close(ipc_event_socketfd); } } @@ -403,9 +403,9 @@ void bar_ipc_init(int outputi, const char *bar_id) { json_object_put(bar_config); free(res); - const char *subscribe_json = "[ \"workspace\" ]"; + const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; len = strlen(subscribe_json); - res = ipc_single_command(ipc_listen_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); + res = ipc_single_command(ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); free(res); ipc_update_workspaces(); @@ -1015,7 +1015,7 @@ void poll_for_update() { dirty = false; FD_ZERO(&readfds); - FD_SET(ipc_listen_socketfd, &readfds); + FD_SET(ipc_event_socketfd, &readfds); FD_SET(status_read_fd, &readfds); activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); @@ -1023,10 +1023,10 @@ void poll_for_update() { sway_log(L_ERROR, "polling failed: %d", errno); } - if (FD_ISSET(ipc_listen_socketfd, &readfds)) { + if (FD_ISSET(ipc_event_socketfd, &readfds)) { sway_log(L_DEBUG, "Got workspace update."); uint32_t len; - char *buf = ipc_recv_response(ipc_listen_socketfd, &len); + char *buf = ipc_recv_response(ipc_event_socketfd, &len); free(buf); ipc_update_workspaces(); dirty = true; @@ -1131,7 +1131,7 @@ int main(int argc, char **argv) { } } ipc_socketfd = ipc_open_socket(socket_path); - ipc_listen_socketfd = ipc_open_socket(socket_path); + ipc_event_socketfd = ipc_open_socket(socket_path); if (argc == optind) { From 19833fbc8b607ce881fe9a7f65116240c7ecc87c Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Sun, 3 Jan 2016 20:37:10 +0100 Subject: [PATCH 2/3] Add IPC event types Adds custom IPC_EVENT_* types --- include/ipc.h | 7 +++++++ sway/ipc-server.c | 36 +++++++++++++++++------------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index 75be58a62..e0b3b7364 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -10,6 +10,13 @@ enum ipc_command_type { IPC_GET_MARKS = 5, IPC_GET_BAR_CONFIG = 6, IPC_GET_VERSION = 7, + // Events send from sway to clients. Events have the higest bit set. + IPC_EVENT_WORKSPACE = (1 << 31 | 0), + IPC_EVENT_OUTPUT = (1 << 31 | 1), + IPC_EVENT_MODE = (1 << 31 | 2), + IPC_EVENT_WINDOW = (1 << 31 | 3), + IPC_EVENT_BARCONFIG_UPDATE = (1 << 31 | 4), + IPC_EVENT_BINDING = (1 << 31 | 5), IPC_SWAY_GET_PIXELS = 0x81 }; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index e161c7567..2bb25202c 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -290,9 +290,9 @@ void ipc_client_handle_command(struct ipc_client *client) { for (int i = 0; i < json_object_array_length(request); i++) { const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); if (strcmp(event_type, "workspace") == 0) { - client->subscribed_events |= IPC_GET_WORKSPACES; + client->subscribed_events |= IPC_EVENT_WORKSPACE; } else if (strcmp(event_type, "barconfig_update") == 0) { - client->subscribed_events |= IPC_GET_BAR_CONFIG; + client->subscribed_events |= IPC_EVENT_BARCONFIG_UPDATE; } else { ipc_send_reply(client, "{\"success\": false}", 18); ipc_client_disconnect(client); @@ -562,6 +562,19 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { return json; } +void ipc_send_event(const char *json_string, enum ipc_command_type event) { + int i; + struct ipc_client *client; + for (i = 0; i < ipc_client_list->length; i++) { + client = ipc_client_list->items[i]; + if ((client->subscribed_events & event) == 0) { + continue; + } + client->current_command = event; + ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + } +} + void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); @@ -580,14 +593,7 @@ void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { } const char *json_string = json_object_to_json_string(obj); - - for (int i = 0; i < ipc_client_list->length; i++) { - struct ipc_client *client = ipc_client_list->items[i]; - if ((client->subscribed_events & IPC_GET_WORKSPACES) == 0) { - continue; - } - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); - } + ipc_send_event(json_string, IPC_EVENT_WORKSPACE); json_object_put(obj); // free } @@ -595,15 +601,7 @@ void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { void ipc_event_barconfig_update(struct bar_config *bar) { json_object *json = ipc_json_describe_bar_config(bar); const char *json_string = json_object_to_json_string(json); - int i; - struct ipc_client *client; - for (i = 0; i < ipc_client_list->length; ++i) { - client = ipc_client_list->items[i]; - if ((client->subscribed_events & IPC_GET_BAR_CONFIG) == 0) { - continue; - } - ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); - } + ipc_send_event(json_string, IPC_EVENT_BARCONFIG_UPDATE); json_object_put(json); // free } From 7298a9c67aed2d7a5c5c1df55bfa6052cac04d51 Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Sun, 3 Jan 2016 20:40:50 +0100 Subject: [PATCH 3/3] Add type to returned response. Makes `ipc_recv_response` return a struct with size, type and payload rather than just the payload string. This is useful if the type has to be checked on the client. --- common/ipc-client.c | 28 +++++++++++++++++++++------- include/ipc-client.h | 19 ++++++++++++++++--- swaybar/main.c | 5 ++--- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/common/ipc-client.c b/common/ipc-client.c index e92a09fee..813489135 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -10,6 +10,7 @@ #include "stringop.h" #include "ipc.h" #include "readline.h" +#include "ipc-client.h" static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; static const size_t ipc_header_size = sizeof(ipc_magic)+8; @@ -39,7 +40,7 @@ int ipc_open_socket(const char *socket_path) { return socketfd; } -char *ipc_recv_response(int socketfd, uint32_t *len) { +struct ipc_response *ipc_recv_response(int socketfd) { char data[ipc_header_size]; uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); @@ -52,21 +53,29 @@ char *ipc_recv_response(int socketfd, uint32_t *len) { total += received; } + struct ipc_response *response = malloc(sizeof(struct ipc_response)); total = 0; - *len = data32[0]; - char *response = malloc(*len + 1); - while (total < *len) { - ssize_t received = recv(socketfd, response + total, *len - total, 0); + response->size = data32[0]; + response->type = data32[1]; + char *payload = malloc(response->size + 1); + while (total < response->size) { + ssize_t received = recv(socketfd, payload + total, response->size - total, 0); if (received < 0) { sway_abort("Unable to receive IPC response"); } total += received; } - response[*len] = '\0'; + payload[response->size] = '\0'; + response->payload = payload; return response; } +void free_ipc_response(struct ipc_response *response) { + free(response->payload); + free(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)); @@ -82,5 +91,10 @@ char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint3 sway_abort("Unable to send IPC payload"); } - return ipc_recv_response(socketfd, len); + struct ipc_response *resp = ipc_recv_response(socketfd); + char *response = resp->payload; + *len = resp->size; + free(resp); + + return response; } diff --git a/include/ipc-client.h b/include/ipc-client.h index a4cfd87f6..030c80b67 100644 --- a/include/ipc-client.h +++ b/include/ipc-client.h @@ -3,6 +3,16 @@ #include "ipc.h" +/** + * IPC response including type of IPC response, size of payload and the json + * encoded payload string. + */ +struct ipc_response { + uint32_t size; + uint32_t type; + char *payload; +}; + /** * Gets the path to the IPC socket from sway. */ @@ -17,9 +27,12 @@ int ipc_open_socket(const char *socket_path); */ 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. + * Receives a single IPC response and returns an ipc_response. */ -char *ipc_recv_response(int socketfd, uint32_t *len); +struct ipc_response *ipc_recv_response(int socketfd); +/** + * Free ipc_response struct + */ +void free_ipc_response(struct ipc_response *response); #endif diff --git a/swaybar/main.c b/swaybar/main.c index aa761b7d4..d534345af 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -1025,9 +1025,8 @@ void poll_for_update() { if (FD_ISSET(ipc_event_socketfd, &readfds)) { sway_log(L_DEBUG, "Got workspace update."); - uint32_t len; - char *buf = ipc_recv_response(ipc_event_socketfd, &len); - free(buf); + struct ipc_response *resp = ipc_recv_response(ipc_event_socketfd); + free_ipc_response(resp); ipc_update_workspaces(); dirty = true; }