aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands/bind.c')
-rw-r--r--sway/commands/bind.c173
1 files changed, 62 insertions, 111 deletions
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index c6b3368a..d0e3e22f 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -69,22 +69,25 @@ bool binding_key_compare(struct sway_binding *binding_a,
69 return true; 69 return true;
70} 70}
71 71
72struct cmd_results *cmd_bindsym(int argc, char **argv) { 72static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
73 bool bindcode) {
74 const char *bindtype = bindcode ? "bindcode" : "bindsym";
75
73 struct cmd_results *error = NULL; 76 struct cmd_results *error = NULL;
74 if ((error = checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1))) { 77 if ((error = checkarg(argc, bindtype, EXPECTED_MORE_THAN, 1))) {
75 return error; 78 return error;
76 } 79 }
77 80
78 struct sway_binding *binding = calloc(1, sizeof(struct sway_binding)); 81 struct sway_binding *binding = calloc(1, sizeof(struct sway_binding));
79 if (!binding) { 82 if (!binding) {
80 return cmd_results_new(CMD_FAILURE, "bindsym", 83 return cmd_results_new(CMD_FAILURE, bindtype,
81 "Unable to allocate binding"); 84 "Unable to allocate binding");
82 } 85 }
83 binding->keys = create_list(); 86 binding->keys = create_list();
84 binding->modifiers = 0; 87 binding->modifiers = 0;
85 binding->release = false; 88 binding->release = false;
86 binding->locked = false; 89 binding->locked = false;
87 binding->bindcode = false; 90 binding->bindcode = bindcode;
88 91
89 // Handle --release and --locked 92 // Handle --release and --locked
90 while (argc > 0) { 93 while (argc > 0) {
@@ -100,9 +103,9 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) {
100 } 103 }
101 if (argc < 2) { 104 if (argc < 2) {
102 free_sway_binding(binding); 105 free_sway_binding(binding);
103 return cmd_results_new(CMD_FAILURE, "bindsym", 106 return cmd_results_new(CMD_FAILURE, bindtype,
104 "Invalid bindsym command " 107 "Invalid %s command "
105 "(expected at least 2 non-option arguments, got %d)", argc); 108 "(expected at least 2 non-option arguments, got %d)", bindtype, argc);
106 } 109 }
107 110
108 binding->command = join_args(argv + 1, argc - 1); 111 binding->command = join_args(argv + 1, argc - 1);
@@ -115,124 +118,63 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) {
115 binding->modifiers |= mod; 118 binding->modifiers |= mod;
116 continue; 119 continue;
117 } 120 }
118 // Check for xkb key
119 xkb_keysym_t sym = xkb_keysym_from_name(split->items[i],
120 XKB_KEYSYM_CASE_INSENSITIVE);
121 121
122 // Check for mouse binding 122 xkb_keycode_t keycode;
123 if (strncasecmp(split->items[i], "button", strlen("button")) == 0 && 123 xkb_keysym_t keysym;
124 strlen(split->items[i]) == strlen("button0")) { 124 if (bindcode) {
125 sym = ((char *)split->items[i])[strlen("button")] - '1' + BTN_LEFT; 125 // parse keycode
126 } 126 keycode = (int)strtol(split->items[i], NULL, 10);
127 if (!sym) { 127 if (!xkb_keycode_is_legal_ext(keycode)) {
128 struct cmd_results *ret = cmd_results_new(CMD_INVALID, "bindsym", 128 error =
129 "Unknown key '%s'", (char *)split->items[i]); 129 cmd_results_new(CMD_INVALID, "bindcode",
130 free_sway_binding(binding); 130 "Invalid keycode '%s'", (char *)split->items[i]);
131 free_flat_list(split); 131 free_sway_binding(binding);
132 return ret; 132 list_free(split);
133 return error;
134 }
135 } else {
136 // Check for xkb key
137 keysym = xkb_keysym_from_name(split->items[i],
138 XKB_KEYSYM_CASE_INSENSITIVE);
139
140 // Check for mouse binding
141 if (strncasecmp(split->items[i], "button", strlen("button")) == 0 &&
142 strlen(split->items[i]) == strlen("button0")) {
143 keysym = ((char *)split->items[i])[strlen("button")] - '1' + BTN_LEFT;
144 }
145 if (!keysym) {
146 struct cmd_results *ret = cmd_results_new(CMD_INVALID, "bindsym",
147 "Unknown key '%s'", (char *)split->items[i]);
148 free_sway_binding(binding);
149 free_flat_list(split);
150 return ret;
151 }
133 } 152 }
134 xkb_keysym_t *key = calloc(1, sizeof(xkb_keysym_t)); 153 uint32_t *key = calloc(1, sizeof(uint32_t));
135 if (!key) { 154 if (!key) {
136 free_sway_binding(binding); 155 free_sway_binding(binding);
137 free_flat_list(split); 156 free_flat_list(split);
138 return cmd_results_new(CMD_FAILURE, "bindsym", 157 return cmd_results_new(CMD_FAILURE, bindtype,
139 "Unable to allocate binding"); 158 "Unable to allocate binding");
140 } 159 }
141 *key = sym;
142 list_add(binding->keys, key);
143 }
144 free_flat_list(split);
145 binding->order = binding_order++;
146
147 list_t *mode_bindings = config->current_mode->keysym_bindings;
148
149 // overwrite the binding if it already exists
150 bool overwritten = false;
151 for (int i = 0; i < mode_bindings->length; ++i) {
152 struct sway_binding *config_binding = mode_bindings->items[i];
153 if (binding_key_compare(binding, config_binding)) {
154 wlr_log(L_DEBUG, "overwriting old binding with command '%s'",
155 config_binding->command);
156 free_sway_binding(config_binding);
157 mode_bindings->items[i] = binding;
158 overwritten = true;
159 }
160 }
161
162 if (!overwritten) {
163 list_add(mode_bindings, binding);
164 }
165
166 wlr_log(L_DEBUG, "bindsym - Bound %s to command %s",
167 argv[0], binding->command);
168 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
169}
170
171struct cmd_results *cmd_bindcode(int argc, char **argv) {
172 struct cmd_results *error = NULL;
173 if ((error = checkarg(argc, "bindcode", EXPECTED_MORE_THAN, 1))) {
174 return error;
175 }
176
177 struct sway_binding *binding = calloc(1, sizeof(struct sway_binding));
178 if (!binding) {
179 return cmd_results_new(CMD_FAILURE, "bindsym",
180 "Unable to allocate binding");
181 }
182 binding->keys = create_list();
183 binding->modifiers = 0;
184 binding->release = false;
185 binding->locked = false;
186 binding->bindcode = true;
187 160
188 // Handle --release and --locked 161 if (bindcode) {
189 while (argc > 0) { 162 *key = (uint32_t)keycode;
190 if (strcmp("--release", argv[0]) == 0) {
191 binding->release = true;
192 } else if (strcmp("--locked", argv[0]) == 0) {
193 binding->locked = true;
194 } else { 163 } else {
195 break; 164 *key = (uint32_t)keysym;
196 } 165 }
197 argv++;
198 argc--;
199 }
200 if (argc < 2) {
201 free_sway_binding(binding);
202 return cmd_results_new(CMD_FAILURE, "bindcode",
203 "Invalid bindcode command "
204 "(expected at least 2 non-option arguments, got %d)", argc);
205 }
206 166
207 binding->command = join_args(argv + 1, argc - 1);
208
209 list_t *split = split_string(argv[0], "+");
210 for (int i = 0; i < split->length; ++i) {
211 // Check for a modifier key
212 uint32_t mod;
213 if ((mod = get_modifier_mask_by_name(split->items[i])) > 0) {
214 binding->modifiers |= mod;
215 continue;
216 }
217 // parse keycode
218 xkb_keycode_t keycode = (int)strtol(split->items[i], NULL, 10);
219 if (!xkb_keycode_is_legal_ext(keycode)) {
220 error =
221 cmd_results_new(CMD_INVALID, "bindcode",
222 "Invalid keycode '%s'", (char *)split->items[i]);
223 free_sway_binding(binding);
224 list_free(split);
225 return error;
226 }
227 xkb_keycode_t *key = calloc(1, sizeof(xkb_keycode_t));
228 *key = keycode - 8;
229 list_add(binding->keys, key); 167 list_add(binding->keys, key);
230 } 168 }
231 free_flat_list(split); 169 free_flat_list(split);
232
233 binding->order = binding_order++; 170 binding->order = binding_order++;
234 171
235 list_t *mode_bindings = config->current_mode->keycode_bindings; 172 list_t *mode_bindings;
173 if (bindcode) {
174 mode_bindings = config->current_mode->keycode_bindings;
175 } else {
176 mode_bindings = config->current_mode->keysym_bindings;
177 }
236 178
237 // overwrite the binding if it already exists 179 // overwrite the binding if it already exists
238 bool overwritten = false; 180 bool overwritten = false;
@@ -251,7 +193,16 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) {
251 list_add(mode_bindings, binding); 193 list_add(mode_bindings, binding);
252 } 194 }
253 195
254 wlr_log(L_DEBUG, "bindcode - Bound %s to command %s", 196 wlr_log(L_DEBUG, "%s - Bound %s to command %s",
255 argv[0], binding->command); 197 bindtype, argv[0], binding->command);
256 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 198 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
199
200}
201
202struct cmd_results *cmd_bindsym(int argc, char **argv) {
203 return cmd_bindsym_or_bindcode(argc, argv, false);
204}
205
206struct cmd_results *cmd_bindcode(int argc, char **argv) {
207 return cmd_bindsym_or_bindcode(argc, argv, true);
257} 208}