diff options
author | Ryan Walklin <ryan@testtoast.com> | 2019-03-20 14:47:29 +1100 |
---|---|---|
committer | Brian Ashworth <bosrsf04@gmail.com> | 2019-03-19 23:58:47 -0400 |
commit | bdb402404cd6d54242b0b1dc2360cfc5679e52f2 (patch) | |
tree | 5a355e025c24b3de0bc69db4b8cc9d002bbd1167 /sway/commands/bind.c | |
parent | Clean up focus follows mouse logic (diff) | |
download | sway-bdb402404cd6d54242b0b1dc2360cfc5679e52f2.tar.gz sway-bdb402404cd6d54242b0b1dc2360cfc5679e52f2.tar.zst sway-bdb402404cd6d54242b0b1dc2360cfc5679e52f2.zip |
Support WLR_INPUT_DEVICE_SWITCH in sway
This commit adds support for laptop lid and tablet
mode switches as provided by evdev/libinput and
handled by wlroots.
Adds a new bindswitch command with syntax:
bindswitch <switch>:<state> <command>
Where <switch> is one of:
tablet for WLR_SWITCH_TYPE_TABLET_MODE
lid for WLR_SWITCH_TYPE_LID
<state> is one of:
on for WLR_SWITCH_STATE_ON
off for WLR_SWITCH_STATE_OFF
toggle for WLR_SWITCH_STATE_TOGGLE
(Note that WLR_SWITCH_STATE_TOGGLE doesn't map to
libinput and will trigger at both on and off events)
Diffstat (limited to 'sway/commands/bind.c')
-rw-r--r-- | sway/commands/bind.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 172e6b8a..b3d391da 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c | |||
@@ -29,6 +29,28 @@ void free_sway_binding(struct sway_binding *binding) { | |||
29 | free(binding); | 29 | free(binding); |
30 | } | 30 | } |
31 | 31 | ||
32 | void free_switch_binding(struct sway_switch_binding *binding) { | ||
33 | if (!binding) { | ||
34 | return; | ||
35 | } | ||
36 | free(binding->command); | ||
37 | free(binding); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * Returns true if the bindings have the same switch type and state combinations. | ||
42 | */ | ||
43 | static bool binding_switch_compare(struct sway_switch_binding *binding_a, | ||
44 | struct sway_switch_binding *binding_b) { | ||
45 | if (binding_a->type != binding_b->type) { | ||
46 | return false; | ||
47 | } | ||
48 | if (binding_a->state != binding_b->state) { | ||
49 | return false; | ||
50 | } | ||
51 | return true; | ||
52 | } | ||
53 | |||
32 | /** | 54 | /** |
33 | * Returns true if the bindings have the same key and modifier combinations. | 55 | * Returns true if the bindings have the same key and modifier combinations. |
34 | * Note that keyboard layout is not considered, so the bindings might actually | 56 | * Note that keyboard layout is not considered, so the bindings might actually |
@@ -325,6 +347,102 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { | |||
325 | return cmd_bindsym_or_bindcode(argc, argv, true); | 347 | return cmd_bindsym_or_bindcode(argc, argv, true); |
326 | } | 348 | } |
327 | 349 | ||
350 | struct cmd_results *cmd_bindswitch(int argc, char **argv) { | ||
351 | |||
352 | struct cmd_results *error = NULL; | ||
353 | if ((error = checkarg(argc, "bindswitch", EXPECTED_AT_LEAST, 2))) { | ||
354 | return error; | ||
355 | } | ||
356 | struct sway_switch_binding *binding = calloc(1, sizeof(struct sway_switch_binding)); | ||
357 | if (!binding) { | ||
358 | return cmd_results_new(CMD_FAILURE, "Unable to allocate binding"); | ||
359 | } | ||
360 | |||
361 | bool warn = true; | ||
362 | |||
363 | // Handle flags | ||
364 | while (argc > 0) { | ||
365 | if (strcmp("--locked", argv[0]) == 0) { | ||
366 | binding->flags |= BINDING_LOCKED; | ||
367 | } else if (strcmp("--no-warn", argv[0]) == 0) { | ||
368 | warn = false; | ||
369 | } else { | ||
370 | break; | ||
371 | } | ||
372 | argv++; | ||
373 | argc--; | ||
374 | } | ||
375 | |||
376 | if (argc < 2) { | ||
377 | free(binding); | ||
378 | return cmd_results_new(CMD_FAILURE, | ||
379 | "Invalid bindswitch command (expected at least 2 " | ||
380 | "non-option arguments, got %d)", argc); | ||
381 | } | ||
382 | binding->command = join_args(argv + 1, argc - 1); | ||
383 | |||
384 | list_t *split = split_string(argv[0], ":"); | ||
385 | if (split->length != 2) { | ||
386 | free_switch_binding(binding); | ||
387 | return cmd_results_new(CMD_FAILURE, | ||
388 | "Invalid bindswitch command (expected two arguments with " | ||
389 | "format <switch>:<state> <action>, got %d)", argc); | ||
390 | } | ||
391 | if (strcmp(split->items[0], "tablet") == 0) { | ||
392 | binding->type = WLR_SWITCH_TYPE_TABLET_MODE; | ||
393 | } else if (strcmp(split->items[0], "lid") == 0) { | ||
394 | binding->type = WLR_SWITCH_TYPE_LID; | ||
395 | } else { | ||
396 | free_switch_binding(binding); | ||
397 | return cmd_results_new(CMD_FAILURE, | ||
398 | "Invalid bindswitch command (expected switch binding: " | ||
399 | "unknown switch %s)", split->items[0]); | ||
400 | } | ||
401 | if (strcmp(split->items[1], "on") == 0) { | ||
402 | binding->state = WLR_SWITCH_STATE_ON; | ||
403 | } else if (strcmp(split->items[1], "off") == 0) { | ||
404 | binding->state = WLR_SWITCH_STATE_OFF; | ||
405 | } else if (strcmp(split->items[1], "toggle") == 0) { | ||
406 | binding->state = WLR_SWITCH_STATE_TOGGLE; | ||
407 | } else { | ||
408 | free_switch_binding(binding); | ||
409 | return cmd_results_new(CMD_FAILURE, | ||
410 | "Invalid bindswitch command " | ||
411 | "(expected switch state: unknown state %d)", | ||
412 | split->items[0]); | ||
413 | } | ||
414 | list_free_items_and_destroy(split); | ||
415 | |||
416 | list_t *mode_bindings = config->current_mode->switch_bindings; | ||
417 | |||
418 | // overwrite the binding if it already exists | ||
419 | bool overwritten = false; | ||
420 | for (int i = 0; i < mode_bindings->length; ++i) { | ||
421 | struct sway_switch_binding *config_binding = mode_bindings->items[i]; | ||
422 | if (binding_switch_compare(binding, config_binding)) { | ||
423 | sway_log(SWAY_INFO, "Overwriting binding '%s' from `%s` to `%s`", | ||
424 | argv[0], binding->command, config_binding->command); | ||
425 | if (warn) { | ||
426 | config_add_swaynag_warning("Overwriting binding" | ||
427 | "'%s' to `%s` from `%s`", | ||
428 | argv[0], binding->command, | ||
429 | config_binding->command); | ||
430 | } | ||
431 | free_switch_binding(config_binding); | ||
432 | mode_bindings->items[i] = binding; | ||
433 | overwritten = true; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | if (!overwritten) { | ||
438 | list_add(mode_bindings, binding); | ||
439 | } | ||
440 | |||
441 | sway_log(SWAY_DEBUG, "bindswitch - Bound %s to command `%s`", | ||
442 | argv[0], binding->command); | ||
443 | return cmd_results_new(CMD_SUCCESS, NULL); | ||
444 | } | ||
445 | |||
328 | /** | 446 | /** |
329 | * Execute the command associated to a binding | 447 | * Execute the command associated to a binding |
330 | */ | 448 | */ |