diff --git a/common/ipc-client.c b/common/ipc-client.c index 1ab6627bd..aa54c0875 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -88,7 +88,7 @@ void free_ipc_response(struct ipc_response *response) { free(response); } -char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { +void ipc_single_command_no_response(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)); @@ -102,6 +102,10 @@ char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint3 if (write(socketfd, payload, *len) == -1) { sway_abort("Unable to send IPC payload"); } +} + +char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { + ipc_single_command_no_response(socketfd, type, payload, len); struct ipc_response *resp = ipc_recv_response(socketfd); char *response = resp->payload; diff --git a/include/ipc-client.h b/include/ipc-client.h index c9f5b3441..13ed2143a 100644 --- a/include/ipc-client.h +++ b/include/ipc-client.h @@ -23,6 +23,10 @@ char *get_socketpath(void); * Opens the sway socket. */ int ipc_open_socket(const char *socket_path); +/** + * Issues a single IPC command without reading response. + */ +void ipc_single_command_no_response(int socketfd, uint32_t type, const char *payload, uint32_t *len); /** * Issues a single IPC command and returns the buffer. len will be updated with * the length of the buffer returned from sway. diff --git a/sway/ipc-server.c b/sway/ipc-server.c index dca881fa5..df5aa1d2a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -163,8 +163,8 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { int flags; if ((flags = fcntl(client_fd, F_GETFD)) == -1 - || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { - sway_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); + || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC|O_NONBLOCK) == -1) { + sway_log_errno(L_ERROR, "Unable to set CLOEXEC|NONBLOCK on IPC client socket"); close(client_fd); return 0; } diff --git a/swaybar/bar.c b/swaybar/bar.c index 5e87eac90..0c70b0a47 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -155,7 +155,6 @@ void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { /* connect to sway ipc */ bar->ipc_socketfd = ipc_open_socket(socket_path); - bar->ipc_event_socketfd = ipc_open_socket(socket_path); ipc_bar_init(bar, bar_id); @@ -205,7 +204,7 @@ bool dirty = true; static void respond_ipc(int fd, short mask, void *_bar) { struct bar *bar = (struct bar *)_bar; - sway_log(L_DEBUG, "Got IPC event."); + sway_log(L_DEBUG, "Got IPC event or reply."); dirty = handle_ipc_event(bar); } @@ -222,7 +221,7 @@ static void respond_output(int fd, short mask, void *_output) { } void bar_run(struct bar *bar) { - add_event(bar->ipc_event_socketfd, POLLIN, respond_ipc, bar); + add_event(bar->ipc_socketfd, POLLIN, respond_ipc, bar); add_event(bar->status_read_fd, POLLIN, respond_command, bar); int i; @@ -322,10 +321,6 @@ void bar_teardown(struct bar *bar) { close(bar->ipc_socketfd); } - if (bar->ipc_event_socketfd) { - close(bar->ipc_event_socketfd); - } - /* terminate status command process */ terminate_status_command(bar->status_command_pid); } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 93d1219c4..3481029f7 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -14,7 +14,7 @@ void ipc_send_workspace_command(const char *workspace_name) { char command[size]; sprintf(command, "workspace \"%s\"", workspace_name); - ipc_single_command(swaybar.ipc_socketfd, IPC_COMMAND, command, &size); + ipc_single_command_no_response(swaybar.ipc_socketfd, IPC_COMMAND, command, &size); } static void ipc_parse_config(struct config *config, const char *payload) { @@ -249,7 +249,16 @@ static void ipc_parse_config(struct config *config, const char *payload) { json_object_put(bar_config); } -static void ipc_update_workspaces(struct bar *bar) { +static void ipc_update_workspaces_request(struct bar *bar) { + sway_log(L_DEBUG, "Sending update request"); + + uint32_t len = 0; + ipc_single_command_no_response(bar->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); +} + +static void ipc_update_workspaces_response(struct bar *bar, char *res) { + sway_log(L_DEBUG, "Got update response"); + int i; for (i = 0; i < bar->outputs->length; ++i) { struct output *output = bar->outputs->items[i]; @@ -259,11 +268,8 @@ static void ipc_update_workspaces(struct bar *bar) { output->workspaces = create_list(); } - uint32_t len = 0; - char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); json_object *results = json_tokener_parse(res); if (!results) { - free(res); return; } @@ -303,7 +309,6 @@ static void ipc_update_workspaces(struct bar *bar) { } json_object_put(results); - free(res); } void ipc_bar_init(struct bar *bar, const char *bar_id) { @@ -359,22 +364,27 @@ void ipc_bar_init(struct bar *bar, const char *bar_id) { free(res); json_object_put(outputs); + ipc_update_workspaces_request(bar); + // This will handle update response, since we haven't subscribed yet + handle_ipc_event(bar); + const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; len = strlen(subscribe_json); - res = ipc_single_command(bar->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); + res = ipc_single_command(bar->ipc_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); free(res); - - ipc_update_workspaces(bar); } bool handle_ipc_event(struct bar *bar) { - struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); + struct ipc_response *resp = ipc_recv_response(bar->ipc_socketfd); if (!resp) { return false; } switch (resp->type) { case IPC_EVENT_WORKSPACE: - ipc_update_workspaces(bar); + ipc_update_workspaces_request(bar); + // This should read update response, but if there are events + // in socket, there shouldn't be problems. + handle_ipc_event(bar); break; case IPC_EVENT_MODE: { json_object *result = json_tokener_parse(resp->payload); @@ -400,7 +410,11 @@ bool handle_ipc_event(struct bar *bar) { json_object_put(result); break; } + case IPC_GET_WORKSPACES: + ipc_update_workspaces_response(bar, resp->payload); + break; default: + sway_log(L_DEBUG, "Unknown message type: 0x%x", resp->type); free_ipc_response(resp); return false; }