aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/config.h2
-rw-r--r--include/sway/ipc-server.h1
-rw-r--r--sway/commands/bind.c52
-rw-r--r--sway/ipc-server.c76
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
489void free_sway_binding(struct sway_binding *sb); 489void free_sway_binding(struct sway_binding *sb);
490 490
491struct sway_binding *sway_binding_dup(struct sway_binding *sb);
492
493void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding); 491void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding);
494 492
495void load_swaybars(); 493void 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);
17void ipc_event_barconfig_update(struct bar_config *bar); 17void ipc_event_barconfig_update(struct bar_config *bar);
18void ipc_event_mode(const char *mode, bool pango); 18void ipc_event_mode(const char *mode, bool pango);
19void ipc_event_shutdown(const char *reason); 19void ipc_event_shutdown(const char *reason);
20void 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
33static 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) {
275void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) { 305void 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
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;
@@ -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
377void 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
370int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { 446int 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