diff options
-rw-r--r-- | common/ipc-client.c | 28 | ||||
-rw-r--r-- | include/ipc-client.h | 19 | ||||
-rw-r--r-- | include/ipc.h | 7 | ||||
-rw-r--r-- | sway/ipc-server.c | 36 | ||||
-rw-r--r-- | swaybar/main.c | 21 |
5 files changed, 71 insertions, 40 deletions
diff --git a/common/ipc-client.c b/common/ipc-client.c index e92a09fe..81348913 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "stringop.h" | 10 | #include "stringop.h" |
11 | #include "ipc.h" | 11 | #include "ipc.h" |
12 | #include "readline.h" | 12 | #include "readline.h" |
13 | #include "ipc-client.h" | ||
13 | 14 | ||
14 | static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; | 15 | static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; |
15 | static const size_t ipc_header_size = sizeof(ipc_magic)+8; | 16 | static const size_t ipc_header_size = sizeof(ipc_magic)+8; |
@@ -39,7 +40,7 @@ int ipc_open_socket(const char *socket_path) { | |||
39 | return socketfd; | 40 | return socketfd; |
40 | } | 41 | } |
41 | 42 | ||
42 | char *ipc_recv_response(int socketfd, uint32_t *len) { | 43 | struct ipc_response *ipc_recv_response(int socketfd) { |
43 | char data[ipc_header_size]; | 44 | char data[ipc_header_size]; |
44 | uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); | 45 | uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); |
45 | 46 | ||
@@ -52,21 +53,29 @@ char *ipc_recv_response(int socketfd, uint32_t *len) { | |||
52 | total += received; | 53 | total += received; |
53 | } | 54 | } |
54 | 55 | ||
56 | struct ipc_response *response = malloc(sizeof(struct ipc_response)); | ||
55 | total = 0; | 57 | total = 0; |
56 | *len = data32[0]; | 58 | response->size = data32[0]; |
57 | char *response = malloc(*len + 1); | 59 | response->type = data32[1]; |
58 | while (total < *len) { | 60 | char *payload = malloc(response->size + 1); |
59 | ssize_t received = recv(socketfd, response + total, *len - total, 0); | 61 | while (total < response->size) { |
62 | ssize_t received = recv(socketfd, payload + total, response->size - total, 0); | ||
60 | if (received < 0) { | 63 | if (received < 0) { |
61 | sway_abort("Unable to receive IPC response"); | 64 | sway_abort("Unable to receive IPC response"); |
62 | } | 65 | } |
63 | total += received; | 66 | total += received; |
64 | } | 67 | } |
65 | response[*len] = '\0'; | 68 | payload[response->size] = '\0'; |
69 | response->payload = payload; | ||
66 | 70 | ||
67 | return response; | 71 | return response; |
68 | } | 72 | } |
69 | 73 | ||
74 | void free_ipc_response(struct ipc_response *response) { | ||
75 | free(response->payload); | ||
76 | free(response); | ||
77 | } | ||
78 | |||
70 | char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { | 79 | char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) { |
71 | char data[ipc_header_size]; | 80 | char data[ipc_header_size]; |
72 | uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); | 81 | 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 | |||
82 | sway_abort("Unable to send IPC payload"); | 91 | sway_abort("Unable to send IPC payload"); |
83 | } | 92 | } |
84 | 93 | ||
85 | return ipc_recv_response(socketfd, len); | 94 | struct ipc_response *resp = ipc_recv_response(socketfd); |
95 | char *response = resp->payload; | ||
96 | *len = resp->size; | ||
97 | free(resp); | ||
98 | |||
99 | return response; | ||
86 | } | 100 | } |
diff --git a/include/ipc-client.h b/include/ipc-client.h index a4cfd87f..030c80b6 100644 --- a/include/ipc-client.h +++ b/include/ipc-client.h | |||
@@ -4,6 +4,16 @@ | |||
4 | #include "ipc.h" | 4 | #include "ipc.h" |
5 | 5 | ||
6 | /** | 6 | /** |
7 | * IPC response including type of IPC response, size of payload and the json | ||
8 | * encoded payload string. | ||
9 | */ | ||
10 | struct ipc_response { | ||
11 | uint32_t size; | ||
12 | uint32_t type; | ||
13 | char *payload; | ||
14 | }; | ||
15 | |||
16 | /** | ||
7 | * Gets the path to the IPC socket from sway. | 17 | * Gets the path to the IPC socket from sway. |
8 | */ | 18 | */ |
9 | char *get_socketpath(void); | 19 | char *get_socketpath(void); |
@@ -17,9 +27,12 @@ int ipc_open_socket(const char *socket_path); | |||
17 | */ | 27 | */ |
18 | char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len); | 28 | char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len); |
19 | /** | 29 | /** |
20 | * Receives a single IPC resposne and returns the buffer. len will be updated | 30 | * Receives a single IPC response and returns an ipc_response. |
21 | * with the length of the buffer returned from sway. | 31 | */ |
32 | struct ipc_response *ipc_recv_response(int socketfd); | ||
33 | /** | ||
34 | * Free ipc_response struct | ||
22 | */ | 35 | */ |
23 | char *ipc_recv_response(int socketfd, uint32_t *len); | 36 | void free_ipc_response(struct ipc_response *response); |
24 | 37 | ||
25 | #endif | 38 | #endif |
diff --git a/include/ipc.h b/include/ipc.h index 75be58a6..e0b3b736 100644 --- a/include/ipc.h +++ b/include/ipc.h | |||
@@ -10,6 +10,13 @@ enum ipc_command_type { | |||
10 | IPC_GET_MARKS = 5, | 10 | IPC_GET_MARKS = 5, |
11 | IPC_GET_BAR_CONFIG = 6, | 11 | IPC_GET_BAR_CONFIG = 6, |
12 | IPC_GET_VERSION = 7, | 12 | IPC_GET_VERSION = 7, |
13 | // Events send from sway to clients. Events have the higest bit set. | ||
14 | IPC_EVENT_WORKSPACE = (1 << 31 | 0), | ||
15 | IPC_EVENT_OUTPUT = (1 << 31 | 1), | ||
16 | IPC_EVENT_MODE = (1 << 31 | 2), | ||
17 | IPC_EVENT_WINDOW = (1 << 31 | 3), | ||
18 | IPC_EVENT_BARCONFIG_UPDATE = (1 << 31 | 4), | ||
19 | IPC_EVENT_BINDING = (1 << 31 | 5), | ||
13 | IPC_SWAY_GET_PIXELS = 0x81 | 20 | IPC_SWAY_GET_PIXELS = 0x81 |
14 | }; | 21 | }; |
15 | 22 | ||
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index e161c756..2bb25202 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -290,9 +290,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
290 | for (int i = 0; i < json_object_array_length(request); i++) { | 290 | for (int i = 0; i < json_object_array_length(request); i++) { |
291 | const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); | 291 | const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); |
292 | if (strcmp(event_type, "workspace") == 0) { | 292 | if (strcmp(event_type, "workspace") == 0) { |
293 | client->subscribed_events |= IPC_GET_WORKSPACES; | 293 | client->subscribed_events |= IPC_EVENT_WORKSPACE; |
294 | } else if (strcmp(event_type, "barconfig_update") == 0) { | 294 | } else if (strcmp(event_type, "barconfig_update") == 0) { |
295 | client->subscribed_events |= IPC_GET_BAR_CONFIG; | 295 | client->subscribed_events |= IPC_EVENT_BARCONFIG_UPDATE; |
296 | } else { | 296 | } else { |
297 | ipc_send_reply(client, "{\"success\": false}", 18); | 297 | ipc_send_reply(client, "{\"success\": false}", 18); |
298 | ipc_client_disconnect(client); | 298 | ipc_client_disconnect(client); |
@@ -562,6 +562,19 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | |||
562 | return json; | 562 | return json; |
563 | } | 563 | } |
564 | 564 | ||
565 | void ipc_send_event(const char *json_string, enum ipc_command_type event) { | ||
566 | int i; | ||
567 | struct ipc_client *client; | ||
568 | for (i = 0; i < ipc_client_list->length; i++) { | ||
569 | client = ipc_client_list->items[i]; | ||
570 | if ((client->subscribed_events & event) == 0) { | ||
571 | continue; | ||
572 | } | ||
573 | client->current_command = event; | ||
574 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | ||
575 | } | ||
576 | } | ||
577 | |||
565 | void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { | 578 | void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { |
566 | json_object *obj = json_object_new_object(); | 579 | json_object *obj = json_object_new_object(); |
567 | json_object_object_add(obj, "change", json_object_new_string(change)); | 580 | 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) { | |||
580 | } | 593 | } |
581 | 594 | ||
582 | const char *json_string = json_object_to_json_string(obj); | 595 | const char *json_string = json_object_to_json_string(obj); |
583 | 596 | ipc_send_event(json_string, IPC_EVENT_WORKSPACE); | |
584 | for (int i = 0; i < ipc_client_list->length; i++) { | ||
585 | struct ipc_client *client = ipc_client_list->items[i]; | ||
586 | if ((client->subscribed_events & IPC_GET_WORKSPACES) == 0) { | ||
587 | continue; | ||
588 | } | ||
589 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | ||
590 | } | ||
591 | 597 | ||
592 | json_object_put(obj); // free | 598 | json_object_put(obj); // free |
593 | } | 599 | } |
@@ -595,15 +601,7 @@ void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { | |||
595 | void ipc_event_barconfig_update(struct bar_config *bar) { | 601 | void ipc_event_barconfig_update(struct bar_config *bar) { |
596 | json_object *json = ipc_json_describe_bar_config(bar); | 602 | json_object *json = ipc_json_describe_bar_config(bar); |
597 | const char *json_string = json_object_to_json_string(json); | 603 | const char *json_string = json_object_to_json_string(json); |
598 | int i; | 604 | ipc_send_event(json_string, IPC_EVENT_BARCONFIG_UPDATE); |
599 | struct ipc_client *client; | ||
600 | for (i = 0; i < ipc_client_list->length; ++i) { | ||
601 | client = ipc_client_list->items[i]; | ||
602 | if ((client->subscribed_events & IPC_GET_BAR_CONFIG) == 0) { | ||
603 | continue; | ||
604 | } | ||
605 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | ||
606 | } | ||
607 | 605 | ||
608 | json_object_put(json); // free | 606 | json_object_put(json); // free |
609 | } | 607 | } |
diff --git a/swaybar/main.c b/swaybar/main.c index 3ac337d1..2ee25589 100644 --- a/swaybar/main.c +++ b/swaybar/main.c | |||
@@ -66,7 +66,7 @@ struct status_block { | |||
66 | list_t *status_line = NULL; | 66 | list_t *status_line = NULL; |
67 | 67 | ||
68 | list_t *workspaces = NULL; | 68 | list_t *workspaces = NULL; |
69 | int ipc_socketfd, ipc_listen_socketfd; | 69 | int ipc_socketfd, ipc_event_socketfd; |
70 | pid_t pid; | 70 | pid_t pid; |
71 | int status_read_fd; | 71 | int status_read_fd; |
72 | char line[1024]; | 72 | char line[1024]; |
@@ -156,8 +156,8 @@ void swaybar_teardown() { | |||
156 | close(ipc_socketfd); | 156 | close(ipc_socketfd); |
157 | } | 157 | } |
158 | 158 | ||
159 | if (ipc_listen_socketfd) { | 159 | if (ipc_event_socketfd) { |
160 | close(ipc_listen_socketfd); | 160 | close(ipc_event_socketfd); |
161 | } | 161 | } |
162 | } | 162 | } |
163 | 163 | ||
@@ -408,9 +408,9 @@ void bar_ipc_init(int outputi, const char *bar_id) { | |||
408 | json_object_put(bar_config); | 408 | json_object_put(bar_config); |
409 | free(res); | 409 | free(res); |
410 | 410 | ||
411 | const char *subscribe_json = "[ \"workspace\" ]"; | 411 | const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; |
412 | len = strlen(subscribe_json); | 412 | len = strlen(subscribe_json); |
413 | res = ipc_single_command(ipc_listen_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); | 413 | res = ipc_single_command(ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); |
414 | free(res); | 414 | free(res); |
415 | 415 | ||
416 | ipc_update_workspaces(); | 416 | ipc_update_workspaces(); |
@@ -1049,7 +1049,7 @@ void poll_for_update() { | |||
1049 | 1049 | ||
1050 | dirty = false; | 1050 | dirty = false; |
1051 | FD_ZERO(&readfds); | 1051 | FD_ZERO(&readfds); |
1052 | FD_SET(ipc_listen_socketfd, &readfds); | 1052 | FD_SET(ipc_event_socketfd, &readfds); |
1053 | FD_SET(status_read_fd, &readfds); | 1053 | FD_SET(status_read_fd, &readfds); |
1054 | 1054 | ||
1055 | activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); | 1055 | activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); |
@@ -1057,11 +1057,10 @@ void poll_for_update() { | |||
1057 | sway_log(L_ERROR, "polling failed: %d", errno); | 1057 | sway_log(L_ERROR, "polling failed: %d", errno); |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | if (FD_ISSET(ipc_listen_socketfd, &readfds)) { | 1060 | if (FD_ISSET(ipc_event_socketfd, &readfds)) { |
1061 | sway_log(L_DEBUG, "Got workspace update."); | 1061 | sway_log(L_DEBUG, "Got workspace update."); |
1062 | uint32_t len; | 1062 | struct ipc_response *resp = ipc_recv_response(ipc_event_socketfd); |
1063 | char *buf = ipc_recv_response(ipc_listen_socketfd, &len); | 1063 | free_ipc_response(resp); |
1064 | free(buf); | ||
1065 | ipc_update_workspaces(); | 1064 | ipc_update_workspaces(); |
1066 | dirty = true; | 1065 | dirty = true; |
1067 | } | 1066 | } |
@@ -1165,7 +1164,7 @@ int main(int argc, char **argv) { | |||
1165 | } | 1164 | } |
1166 | } | 1165 | } |
1167 | ipc_socketfd = ipc_open_socket(socket_path); | 1166 | ipc_socketfd = ipc_open_socket(socket_path); |
1168 | ipc_listen_socketfd = ipc_open_socket(socket_path); | 1167 | ipc_event_socketfd = ipc_open_socket(socket_path); |
1169 | 1168 | ||
1170 | 1169 | ||
1171 | if (argc == optind) { | 1170 | if (argc == optind) { |