diff options
-rw-r--r-- | sway/commands/input/xkb_switch_layout.c | 45 | ||||
-rw-r--r-- | sway/sway-input.5.scd | 12 |
2 files changed, 48 insertions, 9 deletions
diff --git a/sway/commands/input/xkb_switch_layout.c b/sway/commands/input/xkb_switch_layout.c index 286c040d..d6548a68 100644 --- a/sway/commands/input/xkb_switch_layout.c +++ b/sway/commands/input/xkb_switch_layout.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <assert.h> | ||
2 | #include "sway/config.h" | 3 | #include "sway/config.h" |
3 | #include "sway/commands.h" | 4 | #include "sway/commands.h" |
4 | #include "sway/input/input-manager.h" | 5 | #include "sway/input/input-manager.h" |
@@ -13,6 +14,26 @@ static void switch_layout(struct wlr_keyboard *kbd, xkb_layout_index_t idx) { | |||
13 | kbd->modifiers.latched, kbd->modifiers.locked, idx); | 14 | kbd->modifiers.latched, kbd->modifiers.locked, idx); |
14 | } | 15 | } |
15 | 16 | ||
17 | static xkb_layout_index_t get_current_layout_index(struct wlr_keyboard *kbd) { | ||
18 | xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(kbd->keymap); | ||
19 | assert(num_layouts > 0); | ||
20 | |||
21 | xkb_layout_index_t layout_idx; | ||
22 | for (layout_idx = 0; layout_idx < num_layouts; layout_idx++) { | ||
23 | if (xkb_state_layout_index_is_active(kbd->xkb_state, | ||
24 | layout_idx, XKB_STATE_LAYOUT_EFFECTIVE)) { | ||
25 | break; | ||
26 | } | ||
27 | } | ||
28 | return layout_idx; | ||
29 | } | ||
30 | |||
31 | static void switch_layout_relative(struct wlr_keyboard *kbd, int dir) { | ||
32 | xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(kbd->keymap); | ||
33 | xkb_layout_index_t idx = get_current_layout_index(kbd); | ||
34 | switch_layout(kbd, (idx + num_layouts + dir) % num_layouts); | ||
35 | } | ||
36 | |||
16 | struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) { | 37 | struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) { |
17 | struct cmd_results *error = NULL; | 38 | struct cmd_results *error = NULL; |
18 | if ((error = checkarg(argc, "xkb_switch_layout", EXPECTED_EQUAL_TO, 1))) { | 39 | if ((error = checkarg(argc, "xkb_switch_layout", EXPECTED_EQUAL_TO, 1))) { |
@@ -28,11 +49,21 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) { | |||
28 | } | 49 | } |
29 | 50 | ||
30 | const char *layout_str = argv[0]; | 51 | const char *layout_str = argv[0]; |
52 | int relative, layout; | ||
31 | 53 | ||
32 | char *end; | 54 | if (strcmp(layout_str, "next") == 0) { |
33 | int layout = strtol(layout_str, &end, 10); | 55 | relative = 1; |
34 | if (layout_str[0] == '\0' || end[0] != '\0' || layout < 0) { | 56 | } else if (strcmp(layout_str, "prev") == 0) { |
35 | return cmd_results_new(CMD_FAILURE, "Invalid layout index."); | 57 | relative = -1; |
58 | } else { | ||
59 | char *end; | ||
60 | layout = strtol(layout_str, &end, 10); | ||
61 | if (layout_str[0] == '\0' || end[0] != '\0') { | ||
62 | return cmd_results_new(CMD_FAILURE, "Invalid argument."); | ||
63 | } else if (layout < 0) { | ||
64 | return cmd_results_new(CMD_FAILURE, "Invalid layout index."); | ||
65 | } | ||
66 | relative = 0; | ||
36 | } | 67 | } |
37 | 68 | ||
38 | struct sway_input_device *dev; | 69 | struct sway_input_device *dev; |
@@ -45,7 +76,11 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) { | |||
45 | if (dev->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { | 76 | if (dev->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { |
46 | continue; | 77 | continue; |
47 | } | 78 | } |
48 | switch_layout(dev->wlr_device->keyboard, layout); | 79 | if (relative) { |
80 | switch_layout_relative(dev->wlr_device->keyboard, relative); | ||
81 | } else { | ||
82 | switch_layout(dev->wlr_device->keyboard, layout); | ||
83 | } | ||
49 | } | 84 | } |
50 | 85 | ||
51 | return cmd_results_new(CMD_SUCCESS, NULL); | 86 | return cmd_results_new(CMD_SUCCESS, NULL); |
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index e23e0b93..9edd9381 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd | |||
@@ -66,10 +66,14 @@ For more information on these xkb configuration options, see | |||
66 | *input* <identifier> xkb_rules <rules> | 66 | *input* <identifier> xkb_rules <rules> |
67 | Sets files of rules to be used for keyboard mapping composition. | 67 | Sets files of rules to be used for keyboard mapping composition. |
68 | 68 | ||
69 | *input* <identifier> xkb_switch_layout <index> | 69 | *input* <identifier> xkb_switch_layout <index>|next|prev |
70 | Changes the active keyboard layout index. This can be used when multiple | 70 | Changes the active keyboard layout to <index> counting from zero or to |
71 | layouts are configured with *xkb_layout*. A list of layouts you can switch | 71 | next or previous layout on the list. If there is no next or previous |
72 | between can be obtained with *swaymsg -t get_inputs*. | 72 | layout, this command hops to the other end of the list. |
73 | |||
74 | This can be used when multiple layouts are configured with *xkb_layout*. | ||
75 | A list of layouts you can switch between can be obtained with | ||
76 | *swaymsg -t get_inputs*. | ||
73 | 77 | ||
74 | *input* <identifier> xkb_variant <variant> | 78 | *input* <identifier> xkb_variant <variant> |
75 | Sets the variant of the keyboard like _dvorak_ or _colemak_. | 79 | Sets the variant of the keyboard like _dvorak_ or _colemak_. |