diff options
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/config.h | 7 | ||||
-rw-r--r-- | sway/commands/seat.c | 1 | ||||
-rw-r--r-- | sway/commands/seat/shortcuts_inhibitor.c | 96 | ||||
-rw-r--r-- | sway/config/seat.c | 5 | ||||
-rw-r--r-- | sway/input/input-manager.c | 20 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway-input.5.scd | 19 |
8 files changed, 150 insertions, 0 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index bbbdfc80..3fde0893 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -288,6 +288,7 @@ sway_cmd seat_cmd_idle_inhibit; | |||
288 | sway_cmd seat_cmd_idle_wake; | 288 | sway_cmd seat_cmd_idle_wake; |
289 | sway_cmd seat_cmd_keyboard_grouping; | 289 | sway_cmd seat_cmd_keyboard_grouping; |
290 | sway_cmd seat_cmd_pointer_constraint; | 290 | sway_cmd seat_cmd_pointer_constraint; |
291 | sway_cmd seat_cmd_shortcuts_inhibitor; | ||
291 | sway_cmd seat_cmd_xcursor_theme; | 292 | sway_cmd seat_cmd_xcursor_theme; |
292 | 293 | ||
293 | sway_cmd cmd_ipc_cmd; | 294 | sway_cmd cmd_ipc_cmd; |
diff --git a/include/sway/config.h b/include/sway/config.h index fdd65efd..359f9604 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -177,6 +177,12 @@ enum seat_config_allow_constrain { | |||
177 | CONSTRAIN_DISABLE | 177 | CONSTRAIN_DISABLE |
178 | }; | 178 | }; |
179 | 179 | ||
180 | enum seat_config_shortcuts_inhibit { | ||
181 | SHORTCUTS_INHIBIT_DEFAULT, // the default is currently enabled | ||
182 | SHORTCUTS_INHIBIT_ENABLE, | ||
183 | SHORTCUTS_INHIBIT_DISABLE | ||
184 | }; | ||
185 | |||
180 | enum seat_keyboard_grouping { | 186 | enum seat_keyboard_grouping { |
181 | KEYBOARD_GROUP_DEFAULT, // the default is currently smart | 187 | KEYBOARD_GROUP_DEFAULT, // the default is currently smart |
182 | KEYBOARD_GROUP_NONE, | 188 | KEYBOARD_GROUP_NONE, |
@@ -201,6 +207,7 @@ struct seat_config { | |||
201 | list_t *attachments; // list of seat_attachment configs | 207 | list_t *attachments; // list of seat_attachment configs |
202 | int hide_cursor_timeout; | 208 | int hide_cursor_timeout; |
203 | enum seat_config_allow_constrain allow_constrain; | 209 | enum seat_config_allow_constrain allow_constrain; |
210 | enum seat_config_shortcuts_inhibit shortcuts_inhibit; | ||
204 | enum seat_keyboard_grouping keyboard_grouping; | 211 | enum seat_keyboard_grouping keyboard_grouping; |
205 | uint32_t idle_inhibit_sources, idle_wake_sources; | 212 | uint32_t idle_inhibit_sources, idle_wake_sources; |
206 | struct { | 213 | struct { |
diff --git a/sway/commands/seat.c b/sway/commands/seat.c index eba28cac..84c6ba53 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c | |||
@@ -22,6 +22,7 @@ static struct cmd_handler seat_handlers[] = { | |||
22 | { "idle_wake", seat_cmd_idle_wake }, | 22 | { "idle_wake", seat_cmd_idle_wake }, |
23 | { "keyboard_grouping", seat_cmd_keyboard_grouping }, | 23 | { "keyboard_grouping", seat_cmd_keyboard_grouping }, |
24 | { "pointer_constraint", seat_cmd_pointer_constraint }, | 24 | { "pointer_constraint", seat_cmd_pointer_constraint }, |
25 | { "shortcuts_inhibitor", seat_cmd_shortcuts_inhibitor }, | ||
25 | { "xcursor_theme", seat_cmd_xcursor_theme }, | 26 | { "xcursor_theme", seat_cmd_xcursor_theme }, |
26 | }; | 27 | }; |
27 | 28 | ||
diff --git a/sway/commands/seat/shortcuts_inhibitor.c b/sway/commands/seat/shortcuts_inhibitor.c new file mode 100644 index 00000000..7c7f99cf --- /dev/null +++ b/sway/commands/seat/shortcuts_inhibitor.c | |||
@@ -0,0 +1,96 @@ | |||
1 | #include "log.h" | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/input/seat.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "util.h" | ||
6 | |||
7 | static struct cmd_results *handle_action(struct seat_config *sc, | ||
8 | struct sway_seat *seat, const char *action) { | ||
9 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = NULL; | ||
10 | if (strcmp(action, "disable") == 0) { | ||
11 | sc->shortcuts_inhibit = SHORTCUTS_INHIBIT_DISABLE; | ||
12 | |||
13 | wl_list_for_each(sway_inhibitor, | ||
14 | &seat->keyboard_shortcuts_inhibitors, link) { | ||
15 | wlr_keyboard_shortcuts_inhibitor_v1_deactivate( | ||
16 | sway_inhibitor->inhibitor); | ||
17 | } | ||
18 | |||
19 | sway_log(SWAY_DEBUG, "Deactivated all keyboard shortcuts inhibitors"); | ||
20 | } else { | ||
21 | sway_inhibitor = keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); | ||
22 | if (!sway_inhibitor) { | ||
23 | return cmd_results_new(CMD_FAILURE, | ||
24 | "No inhibitor found for focused surface"); | ||
25 | } | ||
26 | |||
27 | struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor = | ||
28 | sway_inhibitor->inhibitor; | ||
29 | bool inhibit; | ||
30 | if (strcmp(action, "activate") == 0) { | ||
31 | inhibit = true; | ||
32 | } else if (strcmp(action, "deactivate") == 0) { | ||
33 | inhibit = false; | ||
34 | } else if (strcmp(action, "toggle") == 0) { | ||
35 | inhibit = !inhibitor->active; | ||
36 | } else { | ||
37 | return cmd_results_new(CMD_INVALID, "Expected enable|" | ||
38 | "disable|activate|deactivate|toggle"); | ||
39 | } | ||
40 | |||
41 | if (inhibit) { | ||
42 | wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor); | ||
43 | } else { | ||
44 | wlr_keyboard_shortcuts_inhibitor_v1_deactivate(inhibitor); | ||
45 | } | ||
46 | |||
47 | sway_log(SWAY_DEBUG, "%sctivated keyboard shortcuts inhibitor", | ||
48 | inhibit ? "A" : "Dea"); | ||
49 | } | ||
50 | |||
51 | return cmd_results_new(CMD_SUCCESS, NULL); | ||
52 | } | ||
53 | |||
54 | // shortcuts_inhibitor [enable|disable|activate|deactivate|toggle] | ||
55 | struct cmd_results *seat_cmd_shortcuts_inhibitor(int argc, char **argv) { | ||
56 | struct cmd_results *error = | ||
57 | checkarg(argc, "shortcuts_inhibitor", EXPECTED_EQUAL_TO, 1); | ||
58 | if (error) { | ||
59 | return error; | ||
60 | } | ||
61 | |||
62 | struct seat_config *sc = config->handler_context.seat_config; | ||
63 | if (!sc) { | ||
64 | return cmd_results_new(CMD_FAILURE, "No seat defined"); | ||
65 | } | ||
66 | |||
67 | if (strcmp(argv[0], "enable") == 0) { | ||
68 | sc->shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; | ||
69 | // at runtime disable is an action that also deactivates all active | ||
70 | // inhibitors handled in handle_action() | ||
71 | } else if (strcmp(argv[0], "disable") == 0 && !config->active) { | ||
72 | sc->shortcuts_inhibit = SHORTCUTS_INHIBIT_DISABLE; | ||
73 | } else if (!config->active) { | ||
74 | return cmd_results_new(CMD_INVALID, "only enable and disable " | ||
75 | "can be used in the config"); | ||
76 | } else { | ||
77 | if (strcmp(sc->name, "*") != 0) { | ||
78 | struct sway_seat *seat = input_manager_get_seat(sc->name, false); | ||
79 | if (!seat) { | ||
80 | return cmd_results_new(CMD_FAILURE, | ||
81 | "Seat %s does not exist", sc->name); | ||
82 | } | ||
83 | error = handle_action(sc, seat, argv[0]); | ||
84 | } else { | ||
85 | struct sway_seat *seat = NULL; | ||
86 | wl_list_for_each(seat, &server.input->seats, link) { | ||
87 | error = handle_action(sc, seat, argv[0]); | ||
88 | if (error && error->status != CMD_SUCCESS) { | ||
89 | break; | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | return error ? error : cmd_results_new(CMD_SUCCESS, NULL); | ||
96 | } | ||
diff --git a/sway/config/seat.c b/sway/config/seat.c index 6c916727..e2702de5 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c | |||
@@ -30,6 +30,7 @@ struct seat_config *new_seat_config(const char* name) { | |||
30 | } | 30 | } |
31 | seat->hide_cursor_timeout = -1; | 31 | seat->hide_cursor_timeout = -1; |
32 | seat->allow_constrain = CONSTRAIN_DEFAULT; | 32 | seat->allow_constrain = CONSTRAIN_DEFAULT; |
33 | seat->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; | ||
33 | seat->keyboard_grouping = KEYBOARD_GROUP_DEFAULT; | 34 | seat->keyboard_grouping = KEYBOARD_GROUP_DEFAULT; |
34 | seat->xcursor_theme.name = NULL; | 35 | seat->xcursor_theme.name = NULL; |
35 | seat->xcursor_theme.size = 24; | 36 | seat->xcursor_theme.size = 24; |
@@ -154,6 +155,10 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) { | |||
154 | dest->allow_constrain = source->allow_constrain; | 155 | dest->allow_constrain = source->allow_constrain; |
155 | } | 156 | } |
156 | 157 | ||
158 | if (source->shortcuts_inhibit != SHORTCUTS_INHIBIT_DEFAULT) { | ||
159 | dest->shortcuts_inhibit = source->shortcuts_inhibit; | ||
160 | } | ||
161 | |||
157 | if (source->keyboard_grouping != KEYBOARD_GROUP_DEFAULT) { | 162 | if (source->keyboard_grouping != KEYBOARD_GROUP_DEFAULT) { |
158 | dest->keyboard_grouping = source->keyboard_grouping; | 163 | dest->keyboard_grouping = source->keyboard_grouping; |
159 | } | 164 | } |
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index af0f5afa..124d57dc 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -333,6 +333,26 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor( | |||
333 | struct sway_seat *seat = inhibitor->seat->data; | 333 | struct sway_seat *seat = inhibitor->seat->data; |
334 | wl_list_insert(&seat->keyboard_shortcuts_inhibitors, &sway_inhibitor->link); | 334 | wl_list_insert(&seat->keyboard_shortcuts_inhibitors, &sway_inhibitor->link); |
335 | 335 | ||
336 | struct seat_config *config = seat_get_config(seat); | ||
337 | if (!config) { | ||
338 | config = seat_get_config_by_name("*"); | ||
339 | } | ||
340 | |||
341 | if (config && config->shortcuts_inhibit == SHORTCUTS_INHIBIT_DISABLE) { | ||
342 | /** | ||
343 | * Here we deny to honour the inhibitor by never sending the | ||
344 | * activate signal. We can not, however, destroy the inhibitor | ||
345 | * because the protocol doesn't allow for it. So it will linger | ||
346 | * until the client removes it im- or explicitly. But at least | ||
347 | * it can only be one inhibitor per surface and seat at a time. | ||
348 | * | ||
349 | * We also want to allow the user to activate the inhibitor | ||
350 | * manually later which is why we do this check here where the | ||
351 | * inhibitor is already attached to its seat and ready for use. | ||
352 | */ | ||
353 | return; | ||
354 | } | ||
355 | |||
336 | wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor); | 356 | wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor); |
337 | } | 357 | } |
338 | 358 | ||
diff --git a/sway/meson.build b/sway/meson.build index 6fdc4a7d..8a549108 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -94,6 +94,7 @@ sway_sources = files( | |||
94 | 'commands/seat/idle.c', | 94 | 'commands/seat/idle.c', |
95 | 'commands/seat/keyboard_grouping.c', | 95 | 'commands/seat/keyboard_grouping.c', |
96 | 'commands/seat/pointer_constraint.c', | 96 | 'commands/seat/pointer_constraint.c', |
97 | 'commands/seat/shortcuts_inhibitor.c', | ||
97 | 'commands/seat/xcursor_theme.c', | 98 | 'commands/seat/xcursor_theme.c', |
98 | 'commands/set.c', | 99 | 'commands/set.c', |
99 | 'commands/show_marks.c', | 100 | 'commands/show_marks.c', |
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 9edd9381..c0584241 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd | |||
@@ -243,6 +243,25 @@ correct seat. | |||
243 | by default) for the seat. This is primarily useful for video games. The | 243 | by default) for the seat. This is primarily useful for video games. The |
244 | "escape" command can be used at runtime to escape from a captured client. | 244 | "escape" command can be used at runtime to escape from a captured client. |
245 | 245 | ||
246 | *seat* <name> shortcuts_inhibitor enable|disable|activate|deactivate|toggle | ||
247 | Enables or disables the ability of clients to inhibit keyboard | ||
248 | shortcuts for the seat. This is primarily useful for virtualization and | ||
249 | remote desktop software. Subcommands _enable_ and _disable_ affect | ||
250 | whether future inhibitors are honoured by default, i.e. activated | ||
251 | automatically, the default being _enable_. When used at runtime, | ||
252 | _disable_ also disables any currently active inhibitors. _activate_, | ||
253 | _deactivate_ and _toggle_ are only useable at runtime and change the | ||
254 | state of a potentially existing inhibitor on the currently focused | ||
255 | window. This can be used with the current seat alias (_-_) to affect | ||
256 | only the currently focused window of the current seat. Subcommand | ||
257 | _deactivate_ is particularly useful in an _--inhibited_ *bindsym* to | ||
258 | escape a state where shortcuts are inhibited and the client becomes | ||
259 | uncooperative. It is worth noting that whether disabled or deactivated | ||
260 | inhibitors are removed is entirely up to the client. Depending on the | ||
261 | client it may therefore be possible to (re-)activate them later. Any | ||
262 | visual indication that an inhibitor is present is currently left to the | ||
263 | client as well. | ||
264 | |||
246 | *seat* <name> xcursor_theme <theme> [<size>] | 265 | *seat* <name> xcursor_theme <theme> [<size>] |
247 | Override the system default XCursor theme. The default seat's | 266 | Override the system default XCursor theme. The default seat's |
248 | (_seat0_) theme is also used as the default cursor theme in | 267 | (_seat0_) theme is also used as the default cursor theme in |