summaryrefslogtreecommitdiffstats
path: root/sway/commands/bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands/bind.c')
-rw-r--r--sway/commands/bind.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
new file mode 100644
index 00000000..e8bb3ee8
--- /dev/null
+++ b/sway/commands/bind.c
@@ -0,0 +1,146 @@
1#include <xkbcommon/xkbcommon.h>
2#include <xkbcommon/xkbcommon-names.h>
3#include "sway/commands.h"
4#include "sway/config.h"
5#include "list.h"
6#include "log.h"
7#include "stringop.h"
8#include "util.h"
9
10int binding_order = 0;
11
12struct cmd_results *cmd_bindsym(int argc, char **argv) {
13 struct cmd_results *error = NULL;
14 if ((error = checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1))) {
15 return error;
16 }
17
18 struct sway_binding *binding = malloc(sizeof(struct sway_binding));
19 binding->keys = create_list();
20 binding->modifiers = 0;
21 binding->release = false;
22 binding->bindcode = false;
23
24 // Handle --release
25 if (strcmp("--release", argv[0]) == 0) {
26 if (argc >= 3) {
27 binding->release = true;
28 argv++;
29 argc--;
30 } else {
31 free_sway_binding(binding);
32 return cmd_results_new(CMD_FAILURE, "bindsym",
33 "Invalid bindsym command "
34 "(expected more than 2 arguments, got %d)", argc);
35 }
36 }
37
38 binding->command = join_args(argv + 1, argc - 1);
39
40 list_t *split = split_string(argv[0], "+");
41 for (int i = 0; i < split->length; ++i) {
42 // Check for a modifier key
43 uint32_t mod;
44 if ((mod = get_modifier_mask_by_name(split->items[i])) > 0) {
45 binding->modifiers |= mod;
46 continue;
47 }
48 // Check for xkb key
49 xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE);
50 if (!sym) {
51 error = cmd_results_new(CMD_INVALID, "bindsym", "Unknown key '%s'", (char *)split->items[i]);
52 free_sway_binding(binding);
53 list_free(split);
54 return error;
55 }
56 xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
57 *key = sym;
58 list_add(binding->keys, key);
59 }
60 free_flat_list(split);
61
62 struct sway_mode *mode = config->current_mode;
63 int i = list_seq_find(mode->bindings, sway_binding_cmp_keys, binding);
64 if (i > -1) {
65 sway_log(L_DEBUG, "bindsym - '%s' already exists, overwriting", argv[0]);
66 struct sway_binding *dup = mode->bindings->items[i];
67 free_sway_binding(dup);
68 list_del(mode->bindings, i);
69 }
70 binding->order = binding_order++;
71 list_add(mode->bindings, binding);
72 list_qsort(mode->bindings, sway_binding_cmp_qsort);
73
74 sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command);
75 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
76}
77
78struct cmd_results *cmd_bindcode(int argc, char **argv) {
79 struct cmd_results *error = NULL;
80 if ((error = checkarg(argc, "bindcode", EXPECTED_MORE_THAN, 1))) {
81 return error;
82 }
83
84 struct sway_binding *binding = malloc(sizeof(struct sway_binding));
85 binding->keys = create_list();
86 binding->modifiers = 0;
87 binding->release = false;
88 binding->bindcode = true;
89
90 // Handle --release
91 if (strcmp("--release", argv[0]) == 0) {
92 if (argc >= 3) {
93 binding->release = true;
94 argv++;
95 argc--;
96 } else {
97 free_sway_binding(binding);
98 return cmd_results_new(CMD_FAILURE, "bindcode",
99 "Invalid bindcode command "
100 "(expected more than 2 arguments, got %d)", argc);
101 }
102 }
103
104 binding->command = join_args(argv + 1, argc - 1);
105
106 list_t *split = split_string(argv[0], "+");
107 for (int i = 0; i < split->length; ++i) {
108 // Check for a modifier key
109 uint32_t mod;
110 if ((mod = get_modifier_mask_by_name(split->items[i])) > 0) {
111 binding->modifiers |= mod;
112 continue;
113 }
114 // parse keycode
115 xkb_keycode_t keycode = (int)strtol(split->items[i], NULL, 10);
116 if (!xkb_keycode_is_legal_ext(keycode)) {
117 error = cmd_results_new(CMD_INVALID, "bindcode", "Invalid keycode '%s'", (char *)split->items[i]);
118 free_sway_binding(binding);
119 list_free(split);
120 return error;
121 }
122 xkb_keycode_t *key = malloc(sizeof(xkb_keycode_t));
123 *key = keycode - 8;
124 list_add(binding->keys, key);
125 }
126 free_flat_list(split);
127
128 struct sway_mode *mode = config->current_mode;
129 int i = list_seq_find(mode->bindings, sway_binding_cmp_keys, binding);
130 if (i > -1) {
131 struct sway_binding *dup = mode->bindings->items[i];
132 if (dup->bindcode) {
133 sway_log(L_DEBUG, "bindcode - '%s' already exists, overwriting", argv[0]);
134 } else {
135 sway_log(L_DEBUG, "bindcode - '%s' already exists as bindsym, overwriting", argv[0]);
136 }
137 free_sway_binding(dup);
138 list_del(mode->bindings, i);
139 }
140 binding->order = binding_order++;
141 list_add(mode->bindings, binding);
142 list_qsort(mode->bindings, sway_binding_cmp_qsort);
143
144 sway_log(L_DEBUG, "bindcode - Bound %s to command %s", argv[0], binding->command);
145 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
146}