diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | common/util.c | 14 | ||||
-rw-r--r-- | include/config.h | 1 | ||||
-rw-r--r-- | include/ipc-server.h | 4 | ||||
-rw-r--r-- | include/util.h | 7 | ||||
-rw-r--r-- | sway/config.c | 18 | ||||
-rw-r--r-- | sway/handlers.c | 35 | ||||
-rw-r--r-- | sway/ipc-server.c | 53 |
8 files changed, 126 insertions, 10 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c556b0e..447fd584 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -44,6 +44,7 @@ option(enable-swaybar "Enables the swaybar utility" YES) | |||
44 | option(enable-swaygrab "Enables the swaygrab utility" YES) | 44 | option(enable-swaygrab "Enables the swaygrab utility" YES) |
45 | option(enable-swaymsg "Enables the swaymsg utility" YES) | 45 | option(enable-swaymsg "Enables the swaymsg utility" YES) |
46 | option(enable-gdk-pixbuf "Use Pixbuf to support more image formats" YES) | 46 | option(enable-gdk-pixbuf "Use Pixbuf to support more image formats" YES) |
47 | option(enable-binding-event "Enables binding event subscription" YES) | ||
47 | 48 | ||
48 | find_package(JsonC REQUIRED) | 49 | find_package(JsonC REQUIRED) |
49 | find_package(PCRE REQUIRED) | 50 | find_package(PCRE REQUIRED) |
@@ -112,6 +113,9 @@ if(enable-swaylock) | |||
112 | message(WARNING "Not building swaylock - cairo, pango, and PAM are required.") | 113 | message(WARNING "Not building swaylock - cairo, pango, and PAM are required.") |
113 | endif() | 114 | endif() |
114 | endif() | 115 | endif() |
116 | if(enable-binding-event) | ||
117 | add_definitions(-DSWAY_BINDING_EVENT=1) | ||
118 | endif() | ||
115 | 119 | ||
116 | install( | 120 | install( |
117 | FILES ${CMAKE_CURRENT_SOURCE_DIR}/sway.desktop | 121 | FILES ${CMAKE_CURRENT_SOURCE_DIR}/sway.desktop |
diff --git a/common/util.c b/common/util.c index b5037d35..243f90a8 100644 --- a/common/util.c +++ b/common/util.c | |||
@@ -51,3 +51,17 @@ const char *get_modifier_name_by_mask(uint32_t modifier) { | |||
51 | 51 | ||
52 | return NULL; | 52 | return NULL; |
53 | } | 53 | } |
54 | |||
55 | int get_modifier_names(const char **names, uint32_t modifier_masks) { | ||
56 | int length = 0; | ||
57 | int i; | ||
58 | for (i = 0; i < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++i) { | ||
59 | if ((modifier_masks & modifiers[i].mod) != 0) { | ||
60 | names[length] = modifiers[i].name; | ||
61 | ++length; | ||
62 | modifier_masks ^= modifiers[i].mod; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | return length; | ||
67 | } | ||
diff --git a/include/config.h b/include/config.h index 8220f804..1f2bbdd0 100644 --- a/include/config.h +++ b/include/config.h | |||
@@ -189,6 +189,7 @@ int sway_binding_cmp(const void *a, const void *b); | |||
189 | int sway_binding_cmp_qsort(const void *a, const void *b); | 189 | int sway_binding_cmp_qsort(const void *a, const void *b); |
190 | int sway_binding_cmp_keys(const void *a, const void *b); | 190 | int sway_binding_cmp_keys(const void *a, const void *b); |
191 | void free_sway_binding(struct sway_binding *sb); | 191 | void free_sway_binding(struct sway_binding *sb); |
192 | struct sway_binding *sway_binding_dup(struct sway_binding *sb); | ||
192 | 193 | ||
193 | int sway_mouse_binding_cmp(const void *a, const void *b); | 194 | int sway_mouse_binding_cmp(const void *a, const void *b); |
194 | int sway_mouse_binding_cmp_qsort(const void *a, const void *b); | 195 | int sway_mouse_binding_cmp_qsort(const void *a, const void *b); |
diff --git a/include/ipc-server.h b/include/ipc-server.h index 47026bfd..96b7902f 100644 --- a/include/ipc-server.h +++ b/include/ipc-server.h | |||
@@ -21,6 +21,10 @@ void ipc_event_mode(const char *mode); | |||
21 | * the name of that modifier. | 21 | * the name of that modifier. |
22 | */ | 22 | */ |
23 | void ipc_event_modifier(uint32_t modifier, const char *state); | 23 | void ipc_event_modifier(uint32_t modifier, const char *state); |
24 | /** | ||
25 | * Send IPC keyboard binding event. | ||
26 | */ | ||
27 | void ipc_event_binding_keyboard(struct sway_binding *sb); | ||
24 | const char *swayc_type_string(enum swayc_types type); | 28 | const char *swayc_type_string(enum swayc_types type); |
25 | 29 | ||
26 | #endif | 30 | #endif |
diff --git a/include/util.h b/include/util.h index 4bbb64c8..dc47e343 100644 --- a/include/util.h +++ b/include/util.h | |||
@@ -29,4 +29,11 @@ uint32_t get_modifier_mask_by_name(const char *name); | |||
29 | */ | 29 | */ |
30 | const char *get_modifier_name_by_mask(uint32_t modifier); | 30 | const char *get_modifier_name_by_mask(uint32_t modifier); |
31 | 31 | ||
32 | /** | ||
33 | * Get an array of modifier names from modifier_masks | ||
34 | * | ||
35 | * Populates the names array and return the number of names added. | ||
36 | */ | ||
37 | int get_modifier_names(const char **names, uint32_t modifier_masks); | ||
38 | |||
32 | #endif | 39 | #endif |
diff --git a/sway/config.c b/sway/config.c index 95d8f339..d923eea5 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -721,6 +721,24 @@ void free_sway_mouse_binding(struct sway_mouse_binding *binding) { | |||
721 | free(binding); | 721 | free(binding); |
722 | } | 722 | } |
723 | 723 | ||
724 | struct sway_binding *sway_binding_dup(struct sway_binding *sb) { | ||
725 | struct sway_binding *new_sb = malloc(sizeof(struct sway_binding)); | ||
726 | |||
727 | new_sb->order = sb->order; | ||
728 | new_sb->modifiers = sb->modifiers; | ||
729 | new_sb->command = strdup(sb->command); | ||
730 | |||
731 | new_sb->keys = create_list(); | ||
732 | int i; | ||
733 | for (i = 0; i < sb->keys->length; ++i) { | ||
734 | xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); | ||
735 | *key = *(xkb_keysym_t *)sb->keys->items[i]; | ||
736 | list_add(new_sb->keys, key); | ||
737 | } | ||
738 | |||
739 | return new_sb; | ||
740 | } | ||
741 | |||
724 | struct bar_config *default_bar_config(void) { | 742 | struct bar_config *default_bar_config(void) { |
725 | struct bar_config *bar = NULL; | 743 | struct bar_config *bar = NULL; |
726 | bar = malloc(sizeof(struct bar_config)); | 744 | bar = malloc(sizeof(struct bar_config)); |
diff --git a/sway/handlers.c b/sway/handlers.c index e0acebea..76778450 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -336,6 +336,29 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s | |||
336 | return; | 336 | return; |
337 | } | 337 | } |
338 | 338 | ||
339 | static void handle_binding_command(struct sway_binding *binding) { | ||
340 | struct sway_binding *binding_copy = binding; | ||
341 | bool reload = false; | ||
342 | // if this is a reload command we need to make a duplicate of the | ||
343 | // binding since it will be gone after the reload has completed. | ||
344 | if (strcasecmp(binding->command, "reload") == 0) { | ||
345 | binding_copy = sway_binding_dup(binding); | ||
346 | reload = true; | ||
347 | } | ||
348 | |||
349 | struct cmd_results *res = handle_command(binding->command); | ||
350 | if (res->status != CMD_SUCCESS) { | ||
351 | sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
352 | } | ||
353 | ipc_event_binding_keyboard(binding_copy); | ||
354 | |||
355 | if (reload) { // free the binding if we made a copy | ||
356 | free_sway_binding(binding_copy); | ||
357 | } | ||
358 | |||
359 | free_cmd_results(res); | ||
360 | } | ||
361 | |||
339 | static bool handle_bindsym(struct sway_binding *binding) { | 362 | static bool handle_bindsym(struct sway_binding *binding) { |
340 | bool match = false; | 363 | bool match = false; |
341 | int i; | 364 | int i; |
@@ -347,11 +370,7 @@ static bool handle_bindsym(struct sway_binding *binding) { | |||
347 | } | 370 | } |
348 | 371 | ||
349 | if (match) { | 372 | if (match) { |
350 | struct cmd_results *res = handle_command(binding->command); | 373 | handle_binding_command(binding); |
351 | if (res->status != CMD_SUCCESS) { | ||
352 | sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
353 | } | ||
354 | free_cmd_results(res); | ||
355 | return true; | 374 | return true; |
356 | } | 375 | } |
357 | 376 | ||
@@ -362,11 +381,7 @@ static bool handle_bindsym_release(struct sway_binding *binding) { | |||
362 | if (binding->keys->length == 1) { | 381 | if (binding->keys->length == 1) { |
363 | xkb_keysym_t *key = binding->keys->items[0]; | 382 | xkb_keysym_t *key = binding->keys->items[0]; |
364 | if (check_released_key(*key)) { | 383 | if (check_released_key(*key)) { |
365 | struct cmd_results *res = handle_command(binding->command); | 384 | handle_binding_command(binding); |
366 | if (res->status != CMD_SUCCESS) { | ||
367 | sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
368 | } | ||
369 | free_cmd_results(res); | ||
370 | return true; | 385 | return true; |
371 | } | 386 | } |
372 | } | 387 | } |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index f3a4647b..bde20931 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -298,6 +298,10 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
298 | client->subscribed_events |= IPC_EVENT_MODE; | 298 | client->subscribed_events |= IPC_EVENT_MODE; |
299 | } else if (strcmp(event_type, "modifier") == 0) { | 299 | } else if (strcmp(event_type, "modifier") == 0) { |
300 | client->subscribed_events |= IPC_EVENT_MODIFIER; | 300 | client->subscribed_events |= IPC_EVENT_MODIFIER; |
301 | #if SWAY_BINDING_EVENT | ||
302 | } else if (strcmp(event_type, "binding") == 0) { | ||
303 | client->subscribed_events |= IPC_EVENT_BINDING; | ||
304 | #endif | ||
301 | } else { | 305 | } else { |
302 | ipc_send_reply(client, "{\"success\": false}", 18); | 306 | ipc_send_reply(client, "{\"success\": false}", 18); |
303 | ipc_client_disconnect(client); | 307 | ipc_client_disconnect(client); |
@@ -633,3 +637,52 @@ void ipc_event_modifier(uint32_t modifier, const char *state) { | |||
633 | 637 | ||
634 | json_object_put(obj); // free | 638 | json_object_put(obj); // free |
635 | } | 639 | } |
640 | |||
641 | #if SWAY_BINDING_EVENT | ||
642 | static void ipc_event_binding(json_object *sb_obj) { | ||
643 | json_object *obj = json_object_new_object(); | ||
644 | json_object_object_add(obj, "change", json_object_new_string("run")); | ||
645 | json_object_object_add(obj, "binding", sb_obj); | ||
646 | |||
647 | const char *json_string = json_object_to_json_string(obj); | ||
648 | ipc_send_event(json_string, IPC_EVENT_BINDING); | ||
649 | |||
650 | json_object_put(obj); // free | ||
651 | } | ||
652 | #endif | ||
653 | |||
654 | void ipc_event_binding_keyboard(struct sway_binding *sb) { | ||
655 | #if SWAY_BINDING_EVENT | ||
656 | json_object *sb_obj = json_object_new_object(); | ||
657 | json_object_object_add(sb_obj, "command", json_object_new_string(sb->command)); | ||
658 | |||
659 | const char *names[10]; | ||
660 | |||
661 | int len = get_modifier_names(names, sb->modifiers); | ||
662 | int i; | ||
663 | json_object *modifiers = json_object_new_array(); | ||
664 | for (i = 0; i < len; ++i) { | ||
665 | json_object_array_add(modifiers, json_object_new_string(names[i])); | ||
666 | } | ||
667 | |||
668 | json_object_object_add(sb_obj, "event_state_mask", modifiers); | ||
669 | |||
670 | // TODO: implement bindcode | ||
671 | json_object_object_add(sb_obj, "input_code", json_object_new_int(0)); | ||
672 | |||
673 | json_object *symbols = json_object_new_array(); | ||
674 | uint32_t keysym; | ||
675 | char buffer[64]; | ||
676 | for (i = 0; i < sb->keys->length; ++i) { | ||
677 | keysym = *(uint32_t *)sb->keys->items[i]; | ||
678 | if (xkb_keysym_get_name(keysym, buffer, 64) > 0) { | ||
679 | json_object_array_add(symbols, json_object_new_string(buffer)); | ||
680 | } | ||
681 | } | ||
682 | |||
683 | json_object_object_add(sb_obj, "symbols", symbols); | ||
684 | json_object_object_add(sb_obj, "input_type", json_object_new_string("keyboard")); | ||
685 | |||
686 | ipc_event_binding(sb_obj); | ||
687 | #endif | ||
688 | } | ||