aboutsummaryrefslogtreecommitdiffstats
path: root/sway/ipc-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r--sway/ipc-server.c138
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
243static void ipc_send_event(const char *json_string, enum ipc_command_type event) { 244static 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
260void 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
282void ipc_event_window(struct sway_container *window, const char *change) { 286void 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 297void 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
306void 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
294int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { 316int 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
382static 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
360void ipc_client_handle_command(struct ipc_client *client) { 403void 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;