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