diff options
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r-- | sway/ipc-server.c | 138 |
1 files changed, 113 insertions, 25 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 50d0bcf3..394161af 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "sway/ipc-server.h" | 21 | #include "sway/ipc-server.h" |
22 | #include "sway/server.h" | 22 | #include "sway/server.h" |
23 | #include "sway/input/input-manager.h" | 23 | #include "sway/input/input-manager.h" |
24 | #include "sway/input/seat.h" | ||
24 | #include "list.h" | 25 | #include "list.h" |
25 | #include "log.h" | 26 | #include "log.h" |
26 | 27 | ||
@@ -241,33 +242,10 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | |||
241 | } | 242 | } |
242 | 243 | ||
243 | static void ipc_send_event(const char *json_string, enum ipc_command_type event) { | 244 | static void ipc_send_event(const char *json_string, enum ipc_command_type event) { |
244 | static struct { | ||
245 | enum ipc_command_type event; | ||
246 | enum ipc_feature feature; | ||
247 | } security_mappings[] = { | ||
248 | { IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE }, | ||
249 | { IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT }, | ||
250 | { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, | ||
251 | { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, | ||
252 | { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, | ||
253 | { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } | ||
254 | }; | ||
255 | |||
256 | uint32_t security_mask = 0; | ||
257 | for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) { | ||
258 | if (security_mappings[i].event == event) { | ||
259 | security_mask = security_mappings[i].feature; | ||
260 | break; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | int i; | 245 | int i; |
265 | struct ipc_client *client; | 246 | struct ipc_client *client; |
266 | for (i = 0; i < ipc_client_list->length; i++) { | 247 | for (i = 0; i < ipc_client_list->length; i++) { |
267 | client = ipc_client_list->items[i]; | 248 | client = ipc_client_list->items[i]; |
268 | if (!(client->security_policy & security_mask)) { | ||
269 | continue; | ||
270 | } | ||
271 | if ((client->subscribed_events & event_mask(event)) == 0) { | 249 | if ((client->subscribed_events & event_mask(event)) == 0) { |
272 | continue; | 250 | continue; |
273 | } | 251 | } |
@@ -279,6 +257,32 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) | |||
279 | } | 257 | } |
280 | } | 258 | } |
281 | 259 | ||
260 | void ipc_event_workspace(struct sway_container *old, | ||
261 | struct sway_container *new, const char *change) { | ||
262 | wlr_log(L_DEBUG, "Sending workspace::%s event", change); | ||
263 | json_object *obj = json_object_new_object(); | ||
264 | json_object_object_add(obj, "change", json_object_new_string(change)); | ||
265 | if (strcmp("focus", change) == 0) { | ||
266 | if (old) { | ||
267 | json_object_object_add(obj, "old", | ||
268 | ipc_json_describe_container_recursive(old)); | ||
269 | } else { | ||
270 | json_object_object_add(obj, "old", NULL); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | if (new) { | ||
275 | json_object_object_add(obj, "current", | ||
276 | ipc_json_describe_container_recursive(new)); | ||
277 | } else { | ||
278 | json_object_object_add(obj, "current", NULL); | ||
279 | } | ||
280 | |||
281 | const char *json_string = json_object_to_json_string(obj); | ||
282 | ipc_send_event(json_string, IPC_EVENT_WORKSPACE); | ||
283 | json_object_put(obj); | ||
284 | } | ||
285 | |||
282 | void ipc_event_window(struct sway_container *window, const char *change) { | 286 | void ipc_event_window(struct sway_container *window, const char *change) { |
283 | wlr_log(L_DEBUG, "Sending window::%s event", change); | 287 | wlr_log(L_DEBUG, "Sending window::%s event", change); |
284 | json_object *obj = json_object_new_object(); | 288 | json_object *obj = json_object_new_object(); |
@@ -287,8 +291,26 @@ void ipc_event_window(struct sway_container *window, const char *change) { | |||
287 | 291 | ||
288 | const char *json_string = json_object_to_json_string(obj); | 292 | const char *json_string = json_object_to_json_string(obj); |
289 | ipc_send_event(json_string, IPC_EVENT_WINDOW); | 293 | ipc_send_event(json_string, IPC_EVENT_WINDOW); |
294 | json_object_put(obj); | ||
295 | } | ||
290 | 296 | ||
291 | json_object_put(obj); // free | 297 | void ipc_event_barconfig_update(struct bar_config *bar) { |
298 | wlr_log(L_DEBUG, "Sending barconfig_update event"); | ||
299 | json_object *json = ipc_json_describe_bar_config(bar); | ||
300 | |||
301 | const char *json_string = json_object_to_json_string(json); | ||
302 | ipc_send_event(json_string, IPC_EVENT_BARCONFIG_UPDATE); | ||
303 | json_object_put(json); | ||
304 | } | ||
305 | |||
306 | void ipc_event_mode(const char *mode) { | ||
307 | wlr_log(L_DEBUG, "Sending mode::%s event", mode); | ||
308 | json_object *obj = json_object_new_object(); | ||
309 | json_object_object_add(obj, "change", json_object_new_string(mode)); | ||
310 | |||
311 | const char *json_string = json_object_to_json_string(obj); | ||
312 | ipc_send_event(json_string, IPC_EVENT_MODE); | ||
313 | json_object_put(obj); | ||
292 | } | 314 | } |
293 | 315 | ||
294 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | 316 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { |
@@ -357,6 +379,27 @@ void ipc_client_disconnect(struct ipc_client *client) { | |||
357 | free(client); | 379 | free(client); |
358 | } | 380 | } |
359 | 381 | ||
382 | static void ipc_get_workspaces_callback(struct sway_container *workspace, | ||
383 | void *data) { | ||
384 | if (workspace->type != C_WORKSPACE) { | ||
385 | return; | ||
386 | } | ||
387 | json_object *workspace_json = ipc_json_describe_container(workspace); | ||
388 | // override the default focused indicator because | ||
389 | // it's set differently for the get_workspaces reply | ||
390 | struct sway_seat *seat = | ||
391 | sway_input_manager_get_default_seat(input_manager); | ||
392 | struct sway_container *focused_ws = sway_seat_get_focus(seat); | ||
393 | if (focused_ws->type != C_WORKSPACE) { | ||
394 | focused_ws = container_parent(focused_ws, C_WORKSPACE); | ||
395 | } | ||
396 | bool focused = workspace == focused_ws; | ||
397 | json_object_object_del(workspace_json, "focused"); | ||
398 | json_object_object_add(workspace_json, "focused", | ||
399 | json_object_new_boolean(focused)); | ||
400 | json_object_array_add((json_object *)data, workspace_json); | ||
401 | } | ||
402 | |||
360 | void ipc_client_handle_command(struct ipc_client *client) { | 403 | void ipc_client_handle_command(struct ipc_client *client) { |
361 | if (!sway_assert(client != NULL, "client != NULL")) { | 404 | if (!sway_assert(client != NULL, "client != NULL")) { |
362 | return; | 405 | return; |
@@ -412,6 +455,17 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
412 | goto exit_cleanup; | 455 | goto exit_cleanup; |
413 | } | 456 | } |
414 | 457 | ||
458 | case IPC_GET_WORKSPACES: | ||
459 | { | ||
460 | json_object *workspaces = json_object_new_array(); | ||
461 | container_for_each_descendant_dfs(&root_container, | ||
462 | ipc_get_workspaces_callback, workspaces); | ||
463 | const char *json_string = json_object_to_json_string(workspaces); | ||
464 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | ||
465 | json_object_put(workspaces); // free | ||
466 | goto exit_cleanup; | ||
467 | } | ||
468 | |||
415 | case IPC_SUBSCRIBE: | 469 | case IPC_SUBSCRIBE: |
416 | { | 470 | { |
417 | // TODO: Check if they're permitted to use these events | 471 | // TODO: Check if they're permitted to use these events |
@@ -446,7 +500,6 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
446 | } | 500 | } |
447 | 501 | ||
448 | json_object_put(request); | 502 | json_object_put(request); |
449 | |||
450 | ipc_send_reply(client, "{\"success\": true}", 17); | 503 | ipc_send_reply(client, "{\"success\": true}", 17); |
451 | goto exit_cleanup; | 504 | goto exit_cleanup; |
452 | } | 505 | } |
@@ -483,6 +536,41 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
483 | goto exit_cleanup; | 536 | goto exit_cleanup; |
484 | } | 537 | } |
485 | 538 | ||
539 | case IPC_GET_BAR_CONFIG: | ||
540 | { | ||
541 | if (!buf[0]) { | ||
542 | // Send list of configured bar IDs | ||
543 | json_object *bars = json_object_new_array(); | ||
544 | for (int i = 0; i < config->bars->length; ++i) { | ||
545 | struct bar_config *bar = config->bars->items[i]; | ||
546 | json_object_array_add(bars, json_object_new_string(bar->id)); | ||
547 | } | ||
548 | const char *json_string = json_object_to_json_string(bars); | ||
549 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | ||
550 | json_object_put(bars); // free | ||
551 | } else { | ||
552 | // Send particular bar's details | ||
553 | struct bar_config *bar = NULL; | ||
554 | for (int i = 0; i < config->bars->length; ++i) { | ||
555 | bar = config->bars->items[i]; | ||
556 | if (strcmp(buf, bar->id) == 0) { | ||
557 | break; | ||
558 | } | ||
559 | bar = NULL; | ||
560 | } | ||
561 | if (!bar) { | ||
562 | const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; | ||
563 | ipc_send_reply(client, error, (uint32_t)strlen(error)); | ||
564 | goto exit_cleanup; | ||
565 | } | ||
566 | json_object *json = ipc_json_describe_bar_config(bar); | ||
567 | const char *json_string = json_object_to_json_string(json); | ||
568 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | ||
569 | json_object_put(json); // free | ||
570 | } | ||
571 | goto exit_cleanup; | ||
572 | } | ||
573 | |||
486 | default: | 574 | default: |
487 | wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); | 575 | wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); |
488 | goto exit_cleanup; | 576 | goto exit_cleanup; |