diff options
Diffstat (limited to 'swaybar/ipc.c')
-rw-r--r-- | swaybar/ipc.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/swaybar/ipc.c b/swaybar/ipc.c new file mode 100644 index 00000000..cb0b81aa --- /dev/null +++ b/swaybar/ipc.c | |||
@@ -0,0 +1,259 @@ | |||
1 | #include <string.h> | ||
2 | #include <json-c/json.h> | ||
3 | |||
4 | #include "ipc-client.h" | ||
5 | #include "list.h" | ||
6 | #include "log.h" | ||
7 | #include "config.h" | ||
8 | #include "ipc.h" | ||
9 | |||
10 | static void ipc_parse_config(struct swaybar_config *config, const char *payload) { | ||
11 | json_object *bar_config = json_tokener_parse(payload); | ||
12 | json_object *tray_output, *mode, *hidden_state, *position, *status_command; | ||
13 | json_object *font, *bar_height, *workspace_buttons, *strip_workspace_numbers; | ||
14 | json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol; | ||
15 | json_object_object_get_ex(bar_config, "tray_output", &tray_output); | ||
16 | json_object_object_get_ex(bar_config, "mode", &mode); | ||
17 | json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); | ||
18 | json_object_object_get_ex(bar_config, "position", &position); | ||
19 | json_object_object_get_ex(bar_config, "status_command", &status_command); | ||
20 | json_object_object_get_ex(bar_config, "font", &font); | ||
21 | json_object_object_get_ex(bar_config, "bar_height", &bar_height); | ||
22 | json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons); | ||
23 | json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers); | ||
24 | json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator); | ||
25 | json_object_object_get_ex(bar_config, "verbose", &verbose); | ||
26 | json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol); | ||
27 | json_object_object_get_ex(bar_config, "colors", &colors); | ||
28 | |||
29 | if (status_command) { | ||
30 | free(config->status_command); | ||
31 | config->status_command = strdup(json_object_get_string(status_command)); | ||
32 | } | ||
33 | |||
34 | if (position) { | ||
35 | config->position = parse_position(json_object_get_string(position)); | ||
36 | } | ||
37 | |||
38 | if (font) { | ||
39 | free(config->font); | ||
40 | config->font = parse_font(json_object_get_string(font)); | ||
41 | } | ||
42 | |||
43 | if (sep_symbol) { | ||
44 | free(config->sep_symbol); | ||
45 | config->sep_symbol = strdup(json_object_get_string(sep_symbol)); | ||
46 | } | ||
47 | |||
48 | if (strip_workspace_numbers) { | ||
49 | config->strip_workspace_numbers = json_object_get_boolean(strip_workspace_numbers); | ||
50 | } | ||
51 | |||
52 | if (binding_mode_indicator) { | ||
53 | config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator); | ||
54 | } | ||
55 | |||
56 | if (workspace_buttons) { | ||
57 | config->workspace_buttons = json_object_get_boolean(workspace_buttons); | ||
58 | } | ||
59 | |||
60 | if (bar_height) { | ||
61 | config->height = json_object_get_int(bar_height); | ||
62 | } | ||
63 | |||
64 | if (colors) { | ||
65 | json_object *background, *statusline, *separator; | ||
66 | json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text; | ||
67 | json_object *inactive_workspace_border, *inactive_workspace_bg, *inactive_workspace_text; | ||
68 | json_object *active_workspace_border, *active_workspace_bg, *active_workspace_text; | ||
69 | json_object *urgent_workspace_border, *urgent_workspace_bg, *urgent_workspace_text; | ||
70 | json_object *binding_mode_border, *binding_mode_bg, *binding_mode_text; | ||
71 | json_object_object_get_ex(colors, "background", &background); | ||
72 | json_object_object_get_ex(colors, "statusline", &statusline); | ||
73 | json_object_object_get_ex(colors, "separator", &separator); | ||
74 | json_object_object_get_ex(colors, "focused_workspace_border", &focused_workspace_border); | ||
75 | json_object_object_get_ex(colors, "focused_workspace_bg", &focused_workspace_bg); | ||
76 | json_object_object_get_ex(colors, "focused_workspace_text", &focused_workspace_text); | ||
77 | json_object_object_get_ex(colors, "active_workspace_border", &active_workspace_border); | ||
78 | json_object_object_get_ex(colors, "active_workspace_bg", &active_workspace_bg); | ||
79 | json_object_object_get_ex(colors, "active_workspace_text", &active_workspace_text); | ||
80 | json_object_object_get_ex(colors, "inactive_workspace_border", &inactive_workspace_border); | ||
81 | json_object_object_get_ex(colors, "inactive_workspace_bg", &inactive_workspace_bg); | ||
82 | json_object_object_get_ex(colors, "inactive_workspace_text", &inactive_workspace_text); | ||
83 | json_object_object_get_ex(colors, "urgent_workspace_border", &urgent_workspace_border); | ||
84 | json_object_object_get_ex(colors, "urgent_workspace_bg", &urgent_workspace_bg); | ||
85 | json_object_object_get_ex(colors, "urgent_workspace_text", &urgent_workspace_text); | ||
86 | json_object_object_get_ex(colors, "binding_mode_border", &binding_mode_border); | ||
87 | json_object_object_get_ex(colors, "binding_mode_bg", &binding_mode_bg); | ||
88 | json_object_object_get_ex(colors, "binding_mode_text", &binding_mode_text); | ||
89 | if (background) { | ||
90 | config->colors.background = parse_color(json_object_get_string(background)); | ||
91 | } | ||
92 | |||
93 | if (statusline) { | ||
94 | config->colors.statusline = parse_color(json_object_get_string(statusline)); | ||
95 | } | ||
96 | |||
97 | if (separator) { | ||
98 | config->colors.separator = parse_color(json_object_get_string(separator)); | ||
99 | } | ||
100 | |||
101 | if (focused_workspace_border) { | ||
102 | config->colors.focused_workspace.border = parse_color(json_object_get_string(focused_workspace_border)); | ||
103 | } | ||
104 | |||
105 | if (focused_workspace_bg) { | ||
106 | config->colors.focused_workspace.background = parse_color(json_object_get_string(focused_workspace_bg)); | ||
107 | } | ||
108 | |||
109 | if (focused_workspace_text) { | ||
110 | config->colors.focused_workspace.text = parse_color(json_object_get_string(focused_workspace_text)); | ||
111 | } | ||
112 | |||
113 | if (active_workspace_border) { | ||
114 | config->colors.active_workspace.border = parse_color(json_object_get_string(active_workspace_border)); | ||
115 | } | ||
116 | |||
117 | if (active_workspace_bg) { | ||
118 | config->colors.active_workspace.background = parse_color(json_object_get_string(active_workspace_bg)); | ||
119 | } | ||
120 | |||
121 | if (active_workspace_text) { | ||
122 | config->colors.active_workspace.text = parse_color(json_object_get_string(active_workspace_text)); | ||
123 | } | ||
124 | |||
125 | if (inactive_workspace_border) { | ||
126 | config->colors.inactive_workspace.border = parse_color(json_object_get_string(inactive_workspace_border)); | ||
127 | } | ||
128 | |||
129 | if (inactive_workspace_bg) { | ||
130 | config->colors.inactive_workspace.background = parse_color(json_object_get_string(inactive_workspace_bg)); | ||
131 | } | ||
132 | |||
133 | if (inactive_workspace_text) { | ||
134 | config->colors.inactive_workspace.text = parse_color(json_object_get_string(inactive_workspace_text)); | ||
135 | } | ||
136 | |||
137 | if (binding_mode_border) { | ||
138 | config->colors.binding_mode.border = parse_color(json_object_get_string(binding_mode_border)); | ||
139 | } | ||
140 | |||
141 | if (binding_mode_bg) { | ||
142 | config->colors.binding_mode.background = parse_color(json_object_get_string(binding_mode_bg)); | ||
143 | } | ||
144 | |||
145 | if (binding_mode_text) { | ||
146 | config->colors.binding_mode.text = parse_color(json_object_get_string(binding_mode_text)); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | json_object_put(bar_config); | ||
151 | } | ||
152 | |||
153 | static void ipc_update_workspaces(struct swaybar_state *state) { | ||
154 | if (state->output->workspaces) { | ||
155 | list_foreach(state->output->workspaces, free_workspace); | ||
156 | list_free(state->output->workspaces); | ||
157 | } | ||
158 | state->output->workspaces = create_list(); | ||
159 | |||
160 | uint32_t len = 0; | ||
161 | char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); | ||
162 | json_object *results = json_tokener_parse(res); | ||
163 | if (!results) { | ||
164 | free(res); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | int i; | ||
169 | int length = json_object_array_length(results); | ||
170 | json_object *ws_json; | ||
171 | json_object *num, *name, *visible, *focused, *out, *urgent; | ||
172 | for (i = 0; i < length; ++i) { | ||
173 | ws_json = json_object_array_get_idx(results, i); | ||
174 | |||
175 | json_object_object_get_ex(ws_json, "num", &num); | ||
176 | json_object_object_get_ex(ws_json, "name", &name); | ||
177 | json_object_object_get_ex(ws_json, "visible", &visible); | ||
178 | json_object_object_get_ex(ws_json, "focused", &focused); | ||
179 | json_object_object_get_ex(ws_json, "output", &out); | ||
180 | json_object_object_get_ex(ws_json, "urgent", &urgent); | ||
181 | |||
182 | if (strcmp(json_object_get_string(out), state->output->name) == 0) { | ||
183 | struct workspace *ws = malloc(sizeof(struct workspace)); | ||
184 | ws->num = json_object_get_int(num); | ||
185 | ws->name = strdup(json_object_get_string(name)); | ||
186 | ws->visible = json_object_get_boolean(visible); | ||
187 | ws->focused = json_object_get_boolean(focused); | ||
188 | ws->urgent = json_object_get_boolean(urgent); | ||
189 | list_add(state->output->workspaces, ws); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | json_object_put(results); | ||
194 | free(res); | ||
195 | } | ||
196 | |||
197 | void ipc_bar_init(struct swaybar_state *state, int outputi, const char *bar_id) { | ||
198 | uint32_t len = 0; | ||
199 | char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len); | ||
200 | json_object *outputs = json_tokener_parse(res); | ||
201 | json_object *info = json_object_array_get_idx(outputs, outputi); | ||
202 | json_object *name; | ||
203 | json_object_object_get_ex(info, "name", &name); | ||
204 | state->output->name = strdup(json_object_get_string(name)); | ||
205 | free(res); | ||
206 | json_object_put(outputs); | ||
207 | |||
208 | len = strlen(bar_id); | ||
209 | res = ipc_single_command(state->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); | ||
210 | |||
211 | ipc_parse_config(state->config, res); | ||
212 | free(res); | ||
213 | |||
214 | const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; | ||
215 | len = strlen(subscribe_json); | ||
216 | res = ipc_single_command(state->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); | ||
217 | free(res); | ||
218 | |||
219 | ipc_update_workspaces(state); | ||
220 | } | ||
221 | |||
222 | bool handle_ipc_event(struct swaybar_state *state) { | ||
223 | struct ipc_response *resp = ipc_recv_response(state->ipc_event_socketfd); | ||
224 | switch (resp->type) { | ||
225 | case IPC_EVENT_WORKSPACE: | ||
226 | ipc_update_workspaces(state); | ||
227 | break; | ||
228 | case IPC_EVENT_MODE: { | ||
229 | json_object *result = json_tokener_parse(resp->payload); | ||
230 | if (!result) { | ||
231 | free_ipc_response(resp); | ||
232 | sway_log(L_ERROR, "failed to parse payload as json"); | ||
233 | return false; | ||
234 | } | ||
235 | json_object *json_change; | ||
236 | if (json_object_object_get_ex(result, "change", &json_change)) { | ||
237 | const char *change = json_object_get_string(json_change); | ||
238 | |||
239 | free(state->config->mode); | ||
240 | if (strcmp(change, "default") == 0) { | ||
241 | state->config->mode = NULL; | ||
242 | } else { | ||
243 | state->config->mode = strdup(change); | ||
244 | } | ||
245 | } else { | ||
246 | sway_log(L_ERROR, "failed to parse response"); | ||
247 | } | ||
248 | |||
249 | json_object_put(result); | ||
250 | break; | ||
251 | } | ||
252 | default: | ||
253 | free_ipc_response(resp); | ||
254 | return false; | ||
255 | } | ||
256 | |||
257 | free_ipc_response(resp); | ||
258 | return true; | ||
259 | } | ||