diff options
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | include/sway/ipc-server.h | 1 | ||||
-rw-r--r-- | sway/commands/bind.c | 52 | ||||
-rw-r--r-- | sway/ipc-server.c | 76 |
4 files changed, 128 insertions, 3 deletions
diff --git a/include/sway/config.h b/include/sway/config.h index 0f74b439..909b6827 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -488,8 +488,6 @@ int sway_binding_cmp_keys(const void *a, const void *b); | |||
488 | 488 | ||
489 | void free_sway_binding(struct sway_binding *sb); | 489 | void free_sway_binding(struct sway_binding *sb); |
490 | 490 | ||
491 | struct sway_binding *sway_binding_dup(struct sway_binding *sb); | ||
492 | |||
493 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding); | 491 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding); |
494 | 492 | ||
495 | void load_swaybars(); | 493 | void load_swaybars(); |
diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index a11735cf..4b6d0e25 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h | |||
@@ -17,5 +17,6 @@ void ipc_event_window(struct sway_container *window, const char *change); | |||
17 | void ipc_event_barconfig_update(struct bar_config *bar); | 17 | void ipc_event_barconfig_update(struct bar_config *bar); |
18 | void ipc_event_mode(const char *mode, bool pango); | 18 | void ipc_event_mode(const char *mode, bool pango); |
19 | void ipc_event_shutdown(const char *reason); | 19 | void ipc_event_shutdown(const char *reason); |
20 | void ipc_event_binding(struct sway_binding *binding); | ||
20 | 21 | ||
21 | #endif | 22 | #endif |
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 133fd089..8270b958 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
1 | #ifdef __linux__ | 2 | #ifdef __linux__ |
2 | #include <linux/input-event-codes.h> | 3 | #include <linux/input-event-codes.h> |
3 | #elif __FreeBSD__ | 4 | #elif __FreeBSD__ |
@@ -5,9 +6,11 @@ | |||
5 | #endif | 6 | #endif |
6 | #include <xkbcommon/xkbcommon.h> | 7 | #include <xkbcommon/xkbcommon.h> |
7 | #include <xkbcommon/xkbcommon-names.h> | 8 | #include <xkbcommon/xkbcommon-names.h> |
9 | #include <string.h> | ||
8 | #include <strings.h> | 10 | #include <strings.h> |
9 | #include "sway/commands.h" | 11 | #include "sway/commands.h" |
10 | #include "sway/config.h" | 12 | #include "sway/config.h" |
13 | #include "sway/ipc-server.h" | ||
11 | #include "list.h" | 14 | #include "list.h" |
12 | #include "log.h" | 15 | #include "log.h" |
13 | #include "stringop.h" | 16 | #include "stringop.h" |
@@ -27,6 +30,33 @@ void free_sway_binding(struct sway_binding *binding) { | |||
27 | free(binding); | 30 | free(binding); |
28 | } | 31 | } |
29 | 32 | ||
33 | static struct sway_binding *sway_binding_dup(struct sway_binding *sb) { | ||
34 | struct sway_binding *new_sb = calloc(1, sizeof(struct sway_binding)); | ||
35 | if (!new_sb) { | ||
36 | return NULL; | ||
37 | } | ||
38 | |||
39 | new_sb->type = sb->type; | ||
40 | new_sb->order = sb->order; | ||
41 | new_sb->flags = sb->flags; | ||
42 | new_sb->modifiers = sb->modifiers; | ||
43 | new_sb->command = strdup(sb->command); | ||
44 | |||
45 | new_sb->keys = create_list(); | ||
46 | int i; | ||
47 | for (i = 0; i < sb->keys->length; ++i) { | ||
48 | xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); | ||
49 | if (!key) { | ||
50 | free_sway_binding(new_sb); | ||
51 | return NULL; | ||
52 | } | ||
53 | *key = *(xkb_keysym_t *)sb->keys->items[i]; | ||
54 | list_add(new_sb->keys, key); | ||
55 | } | ||
56 | |||
57 | return new_sb; | ||
58 | } | ||
59 | |||
30 | /** | 60 | /** |
31 | * Returns true if the bindings have the same key and modifier combinations. | 61 | * Returns true if the bindings have the same key and modifier combinations. |
32 | * Note that keyboard layout is not considered, so the bindings might actually | 62 | * Note that keyboard layout is not considered, so the bindings might actually |
@@ -275,11 +305,31 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { | |||
275 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) { | 305 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) { |
276 | wlr_log(WLR_DEBUG, "running command for binding: %s", | 306 | wlr_log(WLR_DEBUG, "running command for binding: %s", |
277 | binding->command); | 307 | binding->command); |
308 | |||
309 | struct sway_binding *binding_copy = binding; | ||
310 | bool reload = false; | ||
311 | // if this is a reload command we need to make a duplicate of the | ||
312 | // binding since it will be gone after the reload has completed. | ||
313 | if (strcasecmp(binding->command, "reload") == 0) { | ||
314 | reload = true; | ||
315 | binding_copy = sway_binding_dup(binding); | ||
316 | if (!binding_copy) { | ||
317 | wlr_log(WLR_ERROR, "Failed to duplicate binding during reload"); | ||
318 | return; | ||
319 | } | ||
320 | } | ||
321 | |||
278 | config->handler_context.seat = seat; | 322 | config->handler_context.seat = seat; |
279 | struct cmd_results *results = execute_command(binding->command, NULL); | 323 | struct cmd_results *results = execute_command(binding->command, NULL); |
280 | if (results->status != CMD_SUCCESS) { | 324 | if (results->status == CMD_SUCCESS) { |
325 | ipc_event_binding(binding_copy); | ||
326 | } else { | ||
281 | wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", | 327 | wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", |
282 | binding->command, results->error); | 328 | binding->command, results->error); |
283 | } | 329 | } |
330 | |||
331 | if (reload) { // free the binding if we made a copy | ||
332 | free_sway_binding(binding_copy); | ||
333 | } | ||
284 | free_cmd_results(results); | 334 | free_cmd_results(results); |
285 | } | 335 | } |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 72031e24..8fceafa2 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 | ||
32 | static int ipc_socket = -1; | 39 | static int ipc_socket = -1; |
33 | static struct wl_event_source *ipc_event_source = NULL; | 40 | static struct wl_event_source *ipc_event_source = NULL; |
@@ -367,6 +374,75 @@ void ipc_event_shutdown(const char *reason) { | |||
367 | json_object_put(json); | 374 | json_object_put(json); |
368 | } | 375 | } |
369 | 376 | ||
377 | void ipc_event_binding(struct sway_binding *binding) { | ||
378 | if (!ipc_has_event_listeners(IPC_EVENT_BINDING)) { | ||
379 | return; | ||
380 | } | ||
381 | wlr_log(WLR_DEBUG, "Sending binding event"); | ||
382 | |||
383 | json_object *json_binding = json_object_new_object(); | ||
384 | json_object_object_add(json_binding, "command", json_object_new_string(binding->command)); | ||
385 | |||
386 | const char *names[10]; | ||
387 | int len = get_modifier_names(names, binding->modifiers); | ||
388 | json_object *modifiers = json_object_new_array(); | ||
389 | for (int i = 0; i < len; ++i) { | ||
390 | json_object_array_add(modifiers, json_object_new_string(names[i])); | ||
391 | } | ||
392 | json_object_object_add(json_binding, "event_state_mask", modifiers); | ||
393 | |||
394 | json_object *input_codes = json_object_new_array(); | ||
395 | int input_code = 0; | ||
396 | json_object *symbols = json_object_new_array(); | ||
397 | json_object *symbol = NULL; | ||
398 | |||
399 | if (binding->type == BINDING_KEYCODE) { // bindcode: populate input_codes | ||
400 | uint32_t keycode; | ||
401 | for (int i = 0; i < binding->keys->length; ++i) { | ||
402 | keycode = *(uint32_t *)binding->keys->items[i]; | ||
403 | json_object_array_add(input_codes, json_object_new_int(keycode)); | ||
404 | if (i == 0) { | ||
405 | input_code = keycode; | ||
406 | } | ||
407 | } | ||
408 | } else { // bindsym/mouse: populate symbols | ||
409 | uint32_t keysym; | ||
410 | char buffer[64]; | ||
411 | for (int i = 0; i < binding->keys->length; ++i) { | ||
412 | keysym = *(uint32_t *)binding->keys->items[i]; | ||
413 | if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) { | ||
414 | snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1); | ||
415 | } else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) { | ||
416 | continue; | ||
417 | } | ||
418 | |||
419 | json_object *str = json_object_new_string(buffer); | ||
420 | if (i == 0) { | ||
421 | // str is owned by both symbol and symbols. Make sure | ||
422 | // to bump the ref count. | ||
423 | json_object_array_add(symbols, json_object_get(str)); | ||
424 | symbol = str; | ||
425 | } else { | ||
426 | json_object_array_add(symbols, str); | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | |||
431 | json_object_object_add(json_binding, "input_codes", input_codes); | ||
432 | json_object_object_add(json_binding, "input_code", json_object_new_int(input_code)); | ||
433 | json_object_object_add(json_binding, "symbols", symbols); | ||
434 | json_object_object_add(json_binding, "symbol", symbol); | ||
435 | json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ? | ||
436 | json_object_new_string("mouse") : json_object_new_string("keyboard")); | ||
437 | |||
438 | json_object *json = json_object_new_object(); | ||
439 | json_object_object_add(json, "change", json_object_new_string("run")); | ||
440 | json_object_object_add(json, "binding", json_binding); | ||
441 | const char *json_string = json_object_to_json_string(json); | ||
442 | ipc_send_event(json_string, IPC_EVENT_BINDING); | ||
443 | json_object_put(json); | ||
444 | } | ||
445 | |||
370 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | 446 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { |
371 | struct ipc_client *client = data; | 447 | struct ipc_client *client = data; |
372 | 448 | ||