diff options
author | Mikkel Oscar Lyderik <mikkeloscar@gmail.com> | 2016-01-07 21:43:00 +0100 |
---|---|---|
committer | Mikkel Oscar Lyderik <mikkeloscar@gmail.com> | 2016-01-07 21:43:00 +0100 |
commit | 55f63935ab9319da8e145b49edc1a7ae3e6782c6 (patch) | |
tree | a854f1068b7360952835b38bc38a1138bf1de7f0 /sway | |
parent | Merge pull request #434 from mikkeloscar/detect-modifier (diff) | |
download | sway-55f63935ab9319da8e145b49edc1a7ae3e6782c6.tar.gz sway-55f63935ab9319da8e145b49edc1a7ae3e6782c6.tar.zst sway-55f63935ab9319da8e145b49edc1a7ae3e6782c6.zip |
Implement bindsym --release
This is a "simple" version of --release (same as i3) that only supports
a binding that contain one normal key. e.g.:
bindsym --release $mod+x exec somthing-fun
I didn't bother implementing it for a combination like `$mod+x+z` since
it is a bit tricky to get right and also a bit weird to actually do on a
keyboard.
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands.c | 16 | ||||
-rw-r--r-- | sway/handlers.c | 85 | ||||
-rw-r--r-- | sway/input_state.c | 14 |
3 files changed, 88 insertions, 27 deletions
diff --git a/sway/commands.c b/sway/commands.c index 4e5bc712..6a316596 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -163,9 +163,25 @@ static struct cmd_results *cmd_bindsym(int argc, char **argv) { | |||
163 | return cmd_results_new(CMD_FAILURE, "bindsym", "Can only be used in config file."); | 163 | return cmd_results_new(CMD_FAILURE, "bindsym", "Can only be used in config file."); |
164 | } | 164 | } |
165 | 165 | ||
166 | |||
166 | struct sway_binding *binding = malloc(sizeof(struct sway_binding)); | 167 | struct sway_binding *binding = malloc(sizeof(struct sway_binding)); |
167 | binding->keys = create_list(); | 168 | binding->keys = create_list(); |
168 | binding->modifiers = 0; | 169 | binding->modifiers = 0; |
170 | binding->release = false; | ||
171 | |||
172 | // Handle --release | ||
173 | if (strcmp("--release", argv[0]) == 0) { | ||
174 | if (argc >= 3) { | ||
175 | binding->release = true; | ||
176 | argv++; | ||
177 | argc--; | ||
178 | } else { | ||
179 | return cmd_results_new(CMD_FAILURE, "bindsym", | ||
180 | "Invalid bindsym command" | ||
181 | "(expected more than 2 arguments, got %d)", argc); | ||
182 | } | ||
183 | } | ||
184 | |||
169 | binding->command = join_args(argv + 1, argc - 1); | 185 | binding->command = join_args(argv + 1, argc - 1); |
170 | 186 | ||
171 | list_t *split = split_string(argv[0], "+"); | 187 | list_t *split = split_string(argv[0], "+"); |
diff --git a/sway/handlers.c b/sway/handlers.c index 470f3c95..e0acebea 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -336,6 +336,43 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s | |||
336 | return; | 336 | return; |
337 | } | 337 | } |
338 | 338 | ||
339 | static bool handle_bindsym(struct sway_binding *binding) { | ||
340 | bool match = false; | ||
341 | int i; | ||
342 | for (i = 0; i < binding->keys->length; ++i) { | ||
343 | xkb_keysym_t *key = binding->keys->items[i]; | ||
344 | if ((match = check_key(*key, 0)) == false) { | ||
345 | break; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | if (match) { | ||
350 | struct cmd_results *res = handle_command(binding->command); | ||
351 | if (res->status != CMD_SUCCESS) { | ||
352 | sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
353 | } | ||
354 | free_cmd_results(res); | ||
355 | return true; | ||
356 | } | ||
357 | |||
358 | return false; | ||
359 | } | ||
360 | |||
361 | static bool handle_bindsym_release(struct sway_binding *binding) { | ||
362 | if (binding->keys->length == 1) { | ||
363 | xkb_keysym_t *key = binding->keys->items[0]; | ||
364 | if (check_released_key(*key)) { | ||
365 | struct cmd_results *res = handle_command(binding->command); | ||
366 | if (res->status != CMD_SUCCESS) { | ||
367 | sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
368 | } | ||
369 | free_cmd_results(res); | ||
370 | return true; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | return false; | ||
375 | } | ||
339 | 376 | ||
340 | static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, | 377 | static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, |
341 | uint32_t key, enum wlc_key_state state) { | 378 | uint32_t key, enum wlc_key_state state) { |
@@ -366,33 +403,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
366 | release_key(sym, key); | 403 | release_key(sym, key); |
367 | } | 404 | } |
368 | 405 | ||
369 | for (i = 0; i < mode->bindings->length; ++i) { | ||
370 | struct sway_binding *binding = mode->bindings->items[i]; | ||
371 | |||
372 | if ((modifiers->mods ^ binding->modifiers) == 0) { | ||
373 | bool match = false; | ||
374 | int j; | ||
375 | for (j = 0; j < binding->keys->length; ++j) { | ||
376 | xkb_keysym_t *key = binding->keys->items[j]; | ||
377 | if ((match = check_key(*key, 0)) == false) { | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | if (match) { | ||
382 | if (state == WLC_KEY_STATE_PRESSED) { | ||
383 | struct cmd_results *res = handle_command(binding->command); | ||
384 | if (res->status != CMD_SUCCESS) { | ||
385 | sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
386 | } | ||
387 | free_cmd_results(res); | ||
388 | return EVENT_HANDLED; | ||
389 | } else if (state == WLC_KEY_STATE_RELEASED) { | ||
390 | // TODO: --released | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | |||
396 | // handle bar modifiers pressed/released | 406 | // handle bar modifiers pressed/released |
397 | uint32_t modifier; | 407 | uint32_t modifier; |
398 | for (i = 0; i < config->active_bar_modifiers->length; ++i) { | 408 | for (i = 0; i < config->active_bar_modifiers->length; ++i) { |
@@ -409,6 +419,27 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
409 | } | 419 | } |
410 | // update modifiers state | 420 | // update modifiers state |
411 | modifiers_state_update(modifiers->mods); | 421 | modifiers_state_update(modifiers->mods); |
422 | |||
423 | // handle bindings | ||
424 | for (i = 0; i < mode->bindings->length; ++i) { | ||
425 | struct sway_binding *binding = mode->bindings->items[i]; | ||
426 | if ((modifiers->mods ^ binding->modifiers) == 0) { | ||
427 | switch (state) { | ||
428 | case WLC_KEY_STATE_PRESSED: { | ||
429 | if (!binding->release && handle_bindsym(binding)) { | ||
430 | return EVENT_HANDLED; | ||
431 | } | ||
432 | break; | ||
433 | } | ||
434 | case WLC_KEY_STATE_RELEASED: | ||
435 | if (binding->release && handle_bindsym_release(binding)) { | ||
436 | return EVENT_HANDLED; | ||
437 | } | ||
438 | break; | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
412 | return EVENT_PASSTHROUGH; | 443 | return EVENT_PASSTHROUGH; |
413 | } | 444 | } |
414 | 445 | ||
diff --git a/sway/input_state.c b/sway/input_state.c index 2f40b6c2..86868083 100644 --- a/sway/input_state.c +++ b/sway/input_state.c | |||
@@ -22,6 +22,8 @@ struct key_state { | |||
22 | 22 | ||
23 | static struct key_state key_state_array[KEY_STATE_MAX_LENGTH]; | 23 | static struct key_state key_state_array[KEY_STATE_MAX_LENGTH]; |
24 | 24 | ||
25 | static struct key_state last_released; | ||
26 | |||
25 | static uint32_t modifiers_state; | 27 | static uint32_t modifiers_state; |
26 | 28 | ||
27 | void input_init(void) { | 29 | void input_init(void) { |
@@ -31,6 +33,9 @@ void input_init(void) { | |||
31 | key_state_array[i] = none; | 33 | key_state_array[i] = none; |
32 | } | 34 | } |
33 | 35 | ||
36 | struct key_state none = { 0, 0, 0 }; | ||
37 | last_released = none; | ||
38 | |||
34 | modifiers_state = 0; | 39 | modifiers_state = 0; |
35 | } | 40 | } |
36 | 41 | ||
@@ -76,6 +81,12 @@ bool check_key(uint32_t key_sym, uint32_t key_code) { | |||
76 | return find_key(key_sym, key_code, false) < KEY_STATE_MAX_LENGTH; | 81 | return find_key(key_sym, key_code, false) < KEY_STATE_MAX_LENGTH; |
77 | } | 82 | } |
78 | 83 | ||
84 | bool check_released_key(uint32_t key_sym) { | ||
85 | return (key_sym != 0 | ||
86 | && (last_released.key_sym == key_sym | ||
87 | || last_released.alt_sym == key_sym)); | ||
88 | } | ||
89 | |||
79 | void press_key(uint32_t key_sym, uint32_t key_code) { | 90 | void press_key(uint32_t key_sym, uint32_t key_code) { |
80 | if (key_code == 0) { | 91 | if (key_code == 0) { |
81 | return; | 92 | return; |
@@ -94,6 +105,9 @@ void press_key(uint32_t key_sym, uint32_t key_code) { | |||
94 | void release_key(uint32_t key_sym, uint32_t key_code) { | 105 | void release_key(uint32_t key_sym, uint32_t key_code) { |
95 | uint8_t index = find_key(key_sym, key_code, true); | 106 | uint8_t index = find_key(key_sym, key_code, true); |
96 | if (index < KEY_STATE_MAX_LENGTH) { | 107 | if (index < KEY_STATE_MAX_LENGTH) { |
108 | last_released.key_sym = key_state_array[index].key_sym; | ||
109 | last_released.alt_sym = key_state_array[index].alt_sym; | ||
110 | last_released.key_code = key_state_array[index].key_code; | ||
97 | struct key_state none = { 0, 0, 0 }; | 111 | struct key_state none = { 0, 0, 0 }; |
98 | key_state_array[index] = none; | 112 | key_state_array[index] = none; |
99 | } | 113 | } |