summaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-07 21:43:00 +0100
committerLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-07 21:43:00 +0100
commit55f63935ab9319da8e145b49edc1a7ae3e6782c6 (patch)
treea854f1068b7360952835b38bc38a1138bf1de7f0 /sway
parentMerge pull request #434 from mikkeloscar/detect-modifier (diff)
downloadsway-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.c16
-rw-r--r--sway/handlers.c85
-rw-r--r--sway/input_state.c14
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
339static 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
361static 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
340static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, 377static 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
23static struct key_state key_state_array[KEY_STATE_MAX_LENGTH]; 23static struct key_state key_state_array[KEY_STATE_MAX_LENGTH];
24 24
25static struct key_state last_released;
26
25static uint32_t modifiers_state; 27static uint32_t modifiers_state;
26 28
27void input_init(void) { 29void 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
84bool 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
79void press_key(uint32_t key_sym, uint32_t key_code) { 90void 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) {
94void release_key(uint32_t key_sym, uint32_t key_code) { 105void 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 }