summaryrefslogtreecommitdiffstats
path: root/sway/ipc-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r--sway/ipc-server.c136
1 files changed, 127 insertions, 9 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index be703915..7d2d8969 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -3,12 +3,18 @@
3// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0) 3// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0)
4#define _XOPEN_SOURCE 700 4#define _XOPEN_SOURCE 700
5#endif 5#endif
6#ifdef __linux__
7#include <linux/input-event-codes.h>
8#elif __FreeBSD__
9#include <dev/evdev/input-event-codes.h>
10#endif
6#include <assert.h> 11#include <assert.h>
7#include <errno.h> 12#include <errno.h>
8#include <fcntl.h> 13#include <fcntl.h>
9#include <json-c/json.h> 14#include <json-c/json.h>
10#include <stdbool.h> 15#include <stdbool.h>
11#include <stdint.h> 16#include <stdint.h>
17#include <stdio.h>
12#include <stdlib.h> 18#include <stdlib.h>
13#include <string.h> 19#include <string.h>
14#include <sys/socket.h> 20#include <sys/socket.h>
@@ -28,6 +34,7 @@
28#include "sway/tree/view.h" 34#include "sway/tree/view.h"
29#include "list.h" 35#include "list.h"
30#include "log.h" 36#include "log.h"
37#include "util.h"
31 38
32static int ipc_socket = -1; 39static int ipc_socket = -1;
33static struct wl_event_source *ipc_event_source = NULL; 40static struct wl_event_source *ipc_event_source = NULL;
@@ -291,13 +298,11 @@ void ipc_event_workspace(struct sway_container *old,
291 wlr_log(WLR_DEBUG, "Sending workspace::%s event", change); 298 wlr_log(WLR_DEBUG, "Sending workspace::%s event", change);
292 json_object *obj = json_object_new_object(); 299 json_object *obj = json_object_new_object();
293 json_object_object_add(obj, "change", json_object_new_string(change)); 300 json_object_object_add(obj, "change", json_object_new_string(change));
294 if (strcmp("focus", change) == 0) { 301 if (old) {
295 if (old) { 302 json_object_object_add(obj, "old",
296 json_object_object_add(obj, "old", 303 ipc_json_describe_container_recursive(old));
297 ipc_json_describe_container_recursive(old)); 304 } else {
298 } else { 305 json_object_object_add(obj, "old", NULL);
299 json_object_object_add(obj, "old", NULL);
300 }
301 } 306 }
302 307
303 if (new) { 308 if (new) {
@@ -353,6 +358,104 @@ void ipc_event_mode(const char *mode, bool pango) {
353 json_object_put(obj); 358 json_object_put(obj);
354} 359}
355 360
361void ipc_event_shutdown(const char *reason) {
362 if (!ipc_has_event_listeners(IPC_EVENT_SHUTDOWN)) {
363 return;
364 }
365 wlr_log(WLR_DEBUG, "Sending shutdown::%s event", reason);
366
367 json_object *json = json_object_new_object();
368 json_object_object_add(json, "change", json_object_new_string(reason));
369
370 const char *json_string = json_object_to_json_string(json);
371 ipc_send_event(json_string, IPC_EVENT_SHUTDOWN);
372 json_object_put(json);
373}
374
375void ipc_event_binding(struct sway_binding *binding) {
376 if (!ipc_has_event_listeners(IPC_EVENT_BINDING)) {
377 return;
378 }
379 wlr_log(WLR_DEBUG, "Sending binding event");
380
381 json_object *json_binding = json_object_new_object();
382 json_object_object_add(json_binding, "command", json_object_new_string(binding->command));
383
384 const char *names[10];
385 int len = get_modifier_names(names, binding->modifiers);
386 json_object *modifiers = json_object_new_array();
387 for (int i = 0; i < len; ++i) {
388 json_object_array_add(modifiers, json_object_new_string(names[i]));
389 }
390 json_object_object_add(json_binding, "event_state_mask", modifiers);
391
392 json_object *input_codes = json_object_new_array();
393 int input_code = 0;
394 json_object *symbols = json_object_new_array();
395 json_object *symbol = NULL;
396
397 if (binding->type == BINDING_KEYCODE) { // bindcode: populate input_codes
398 uint32_t keycode;
399 for (int i = 0; i < binding->keys->length; ++i) {
400 keycode = *(uint32_t *)binding->keys->items[i];
401 json_object_array_add(input_codes, json_object_new_int(keycode));
402 if (i == 0) {
403 input_code = keycode;
404 }
405 }
406 } else { // bindsym/mouse: populate symbols
407 uint32_t keysym;
408 char buffer[64];
409 for (int i = 0; i < binding->keys->length; ++i) {
410 keysym = *(uint32_t *)binding->keys->items[i];
411 if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) {
412 snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1);
413 } else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) {
414 continue;
415 }
416
417 json_object *str = json_object_new_string(buffer);
418 if (i == 0) {
419 // str is owned by both symbol and symbols. Make sure
420 // to bump the ref count.
421 json_object_array_add(symbols, json_object_get(str));
422 symbol = str;
423 } else {
424 json_object_array_add(symbols, str);
425 }
426 }
427 }
428
429 json_object_object_add(json_binding, "input_codes", input_codes);
430 json_object_object_add(json_binding, "input_code", json_object_new_int(input_code));
431 json_object_object_add(json_binding, "symbols", symbols);
432 json_object_object_add(json_binding, "symbol", symbol);
433 json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ?
434 json_object_new_string("mouse") : json_object_new_string("keyboard"));
435
436 json_object *json = json_object_new_object();
437 json_object_object_add(json, "change", json_object_new_string("run"));
438 json_object_object_add(json, "binding", json_binding);
439 const char *json_string = json_object_to_json_string(json);
440 ipc_send_event(json_string, IPC_EVENT_BINDING);
441 json_object_put(json);
442}
443
444static void ipc_event_tick(const char *payload) {
445 if (!ipc_has_event_listeners(IPC_EVENT_TICK)) {
446 return;
447 }
448 wlr_log(WLR_DEBUG, "Sending tick event");
449
450 json_object *json = json_object_new_object();
451 json_object_object_add(json, "first", json_object_new_boolean(false));
452 json_object_object_add(json, "payload", json_object_new_string(payload));
453
454 const char *json_string = json_object_to_json_string(json);
455 ipc_send_event(json_string, IPC_EVENT_TICK);
456 json_object_put(json);
457}
458
356int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { 459int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
357 struct ipc_client *client = data; 460 struct ipc_client *client = data;
358 461
@@ -494,6 +597,13 @@ void ipc_client_handle_command(struct ipc_client *client) {
494 goto exit_cleanup; 597 goto exit_cleanup;
495 } 598 }
496 599
600 case IPC_SEND_TICK:
601 {
602 ipc_event_tick(buf);
603 ipc_send_reply(client, "{\"success\": true}", 17);
604 goto exit_cleanup;
605 }
606
497 case IPC_GET_OUTPUTS: 607 case IPC_GET_OUTPUTS:
498 { 608 {
499 json_object *outputs = json_object_new_array(); 609 json_object *outputs = json_object_new_array();
@@ -540,6 +650,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
540 goto exit_cleanup; 650 goto exit_cleanup;
541 } 651 }
542 652
653 bool is_tick = false;
543 // parse requested event types 654 // parse requested event types
544 for (size_t i = 0; i < json_object_array_length(request); i++) { 655 for (size_t i = 0; i < json_object_array_length(request); i++) {
545 const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); 656 const char *event_type = json_object_get_string(json_object_array_get_idx(request, i));
@@ -549,12 +660,15 @@ void ipc_client_handle_command(struct ipc_client *client) {
549 client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); 660 client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE);
550 } else if (strcmp(event_type, "mode") == 0) { 661 } else if (strcmp(event_type, "mode") == 0) {
551 client->subscribed_events |= event_mask(IPC_EVENT_MODE); 662 client->subscribed_events |= event_mask(IPC_EVENT_MODE);
663 } else if (strcmp(event_type, "shutdown") == 0) {
664 client->subscribed_events |= event_mask(IPC_EVENT_SHUTDOWN);
552 } else if (strcmp(event_type, "window") == 0) { 665 } else if (strcmp(event_type, "window") == 0) {
553 client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); 666 client->subscribed_events |= event_mask(IPC_EVENT_WINDOW);
554 } else if (strcmp(event_type, "modifier") == 0) {
555 client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER);
556 } else if (strcmp(event_type, "binding") == 0) { 667 } else if (strcmp(event_type, "binding") == 0) {
557 client->subscribed_events |= event_mask(IPC_EVENT_BINDING); 668 client->subscribed_events |= event_mask(IPC_EVENT_BINDING);
669 } else if (strcmp(event_type, "tick") == 0) {
670 client->subscribed_events |= event_mask(IPC_EVENT_TICK);
671 is_tick = true;
558 } else { 672 } else {
559 client_valid = 673 client_valid =
560 ipc_send_reply(client, "{\"success\": false}", 18); 674 ipc_send_reply(client, "{\"success\": false}", 18);
@@ -566,6 +680,10 @@ void ipc_client_handle_command(struct ipc_client *client) {
566 680
567 json_object_put(request); 681 json_object_put(request);
568 client_valid = ipc_send_reply(client, "{\"success\": true}", 17); 682 client_valid = ipc_send_reply(client, "{\"success\": true}", 17);
683 if (is_tick) {
684 client->current_command = IPC_EVENT_TICK;
685 ipc_send_reply(client, "{\"first\": true, \"payload\": \"\"}", 30);
686 }
569 goto exit_cleanup; 687 goto exit_cleanup;
570 } 688 }
571 689