diff options
author | 2020-03-12 22:10:04 +0100 | |
---|---|---|
committer | 2020-05-13 21:22:16 -0400 | |
commit | 0f11aa037ad8765abf66e0c90052f9e4c37d56db (patch) | |
tree | e78523c566a1a96d53098bfc7c1d1f104043d373 | |
parent | Implement pointer simulation if client hasn't bound to touch (diff) | |
download | sway-0f11aa037ad8765abf66e0c90052f9e4c37d56db.tar.gz sway-0f11aa037ad8765abf66e0c90052f9e4c37d56db.tar.zst sway-0f11aa037ad8765abf66e0c90052f9e4c37d56db.zip |
commands: Add per-view shortcuts_inhibitor command
Add a separate per-view shortcuts_inhibitor command that can be used
with criteria to override the per-seat defaults. This allows to e.g.
disable shortcuts inhibiting globally but enable it for specific,
known-good virtualization and remote desktop software or, alternatively,
to blacklist that one slightly broken piece of software that just
doesn't seem to get it right but insists on trying.
Add a flag to sway_view and handling logic in the input manager that
respects that flag if configured but falls back to per-seat config
otherwise. Add the actual command but with just enable and disable
subcommands since there's no value in duplicating the per-seat
activate/deactivate/toggle logic here. Split the inhibitor retrieval
helper in two so we can use the backend half in the command to retrieve
inhibitors for a specific surface and not just the currently focused
one. Extend the manual page with documentation of the command and
references to its per-seat sibling and usefulness with criteria.
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/input/seat.h | 8 | ||||
-rw-r--r-- | include/sway/tree/view.h | 2 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/shortcuts_inhibitor.c | 49 | ||||
-rw-r--r-- | sway/input/input-manager.c | 22 | ||||
-rw-r--r-- | sway/input/seat.c | 16 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway.5.scd | 11 | ||||
-rw-r--r-- | sway/tree/view.c | 1 |
10 files changed, 103 insertions, 9 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 3fde0893..4a2f8c20 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -164,6 +164,7 @@ sway_cmd cmd_resize; | |||
164 | sway_cmd cmd_scratchpad; | 164 | sway_cmd cmd_scratchpad; |
165 | sway_cmd cmd_seamless_mouse; | 165 | sway_cmd cmd_seamless_mouse; |
166 | sway_cmd cmd_set; | 166 | sway_cmd cmd_set; |
167 | sway_cmd cmd_shortcuts_inhibitor; | ||
167 | sway_cmd cmd_show_marks; | 168 | sway_cmd cmd_show_marks; |
168 | sway_cmd cmd_smart_borders; | 169 | sway_cmd cmd_smart_borders; |
169 | sway_cmd cmd_smart_gaps; | 170 | sway_cmd cmd_smart_gaps; |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index fa232aa2..6a46fa91 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -295,6 +295,14 @@ void seatop_render(struct sway_seat *seat, struct sway_output *output, | |||
295 | bool seatop_allows_set_cursor(struct sway_seat *seat); | 295 | bool seatop_allows_set_cursor(struct sway_seat *seat); |
296 | 296 | ||
297 | /** | 297 | /** |
298 | * Returns the keyboard shortcuts inhibitor that applies to the given surface | ||
299 | * or NULL if none exists. | ||
300 | */ | ||
301 | struct sway_keyboard_shortcuts_inhibitor * | ||
302 | keyboard_shortcuts_inhibitor_get_for_surface(const struct sway_seat *seat, | ||
303 | const struct wlr_surface *surface); | ||
304 | |||
305 | /** | ||
298 | * Returns the keyboard shortcuts inhibitor that applies to the currently | 306 | * Returns the keyboard shortcuts inhibitor that applies to the currently |
299 | * focused surface of a seat or NULL if none exists. | 307 | * focused surface of a seat or NULL if none exists. |
300 | */ | 308 | */ |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 4d3532d2..9230f456 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -110,6 +110,8 @@ struct sway_view { | |||
110 | struct wl_listener surface_new_subsurface; | 110 | struct wl_listener surface_new_subsurface; |
111 | 111 | ||
112 | int max_render_time; // In milliseconds | 112 | int max_render_time; // In milliseconds |
113 | |||
114 | enum seat_config_shortcuts_inhibit shortcuts_inhibit; | ||
113 | }; | 115 | }; |
114 | 116 | ||
115 | struct sway_xdg_shell_view { | 117 | struct sway_xdg_shell_view { |
diff --git a/sway/commands.c b/sway/commands.c index 6a56ff5a..afe05b26 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -127,6 +127,7 @@ static struct cmd_handler command_handlers[] = { | |||
127 | { "rename", cmd_rename }, | 127 | { "rename", cmd_rename }, |
128 | { "resize", cmd_resize }, | 128 | { "resize", cmd_resize }, |
129 | { "scratchpad", cmd_scratchpad }, | 129 | { "scratchpad", cmd_scratchpad }, |
130 | { "shortcuts_inhibitor", cmd_shortcuts_inhibitor }, | ||
130 | { "split", cmd_split }, | 131 | { "split", cmd_split }, |
131 | { "splith", cmd_splith }, | 132 | { "splith", cmd_splith }, |
132 | { "splitt", cmd_splitt }, | 133 | { "splitt", cmd_splitt }, |
diff --git a/sway/commands/shortcuts_inhibitor.c b/sway/commands/shortcuts_inhibitor.c new file mode 100644 index 00000000..ffa1a5c9 --- /dev/null +++ b/sway/commands/shortcuts_inhibitor.c | |||
@@ -0,0 +1,49 @@ | |||
1 | #include <string.h> | ||
2 | #include "log.h" | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/config.h" | ||
5 | #include "sway/input/seat.h" | ||
6 | #include "sway/tree/container.h" | ||
7 | #include "sway/tree/view.h" | ||
8 | |||
9 | struct cmd_results *cmd_shortcuts_inhibitor(int argc, char **argv) { | ||
10 | struct cmd_results *error = NULL; | ||
11 | if ((error = checkarg(argc, "shortcuts_inhibitor", EXPECTED_EQUAL_TO, 1))) { | ||
12 | return error; | ||
13 | } | ||
14 | |||
15 | struct sway_container *con = config->handler_context.container; | ||
16 | if (!con || !con->view) { | ||
17 | return cmd_results_new(CMD_INVALID, | ||
18 | "Only views can have shortcuts inhibitors"); | ||
19 | } | ||
20 | |||
21 | struct sway_view *view = con->view; | ||
22 | if (strcmp(argv[0], "enable") == 0) { | ||
23 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; | ||
24 | } else if (strcmp(argv[0], "disable") == 0) { | ||
25 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DISABLE; | ||
26 | |||
27 | struct sway_seat *seat = NULL; | ||
28 | wl_list_for_each(seat, &server.input->seats, link) { | ||
29 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = | ||
30 | keyboard_shortcuts_inhibitor_get_for_surface( | ||
31 | seat, view->surface); | ||
32 | if (!sway_inhibitor) { | ||
33 | continue; | ||
34 | } | ||
35 | |||
36 | wlr_keyboard_shortcuts_inhibitor_v1_deactivate( | ||
37 | sway_inhibitor->inhibitor); | ||
38 | sway_log(SWAY_DEBUG, "Deactivated keyboard shortcuts " | ||
39 | "inhibitor for seat %s on view", | ||
40 | seat->wlr_seat->name); | ||
41 | |||
42 | } | ||
43 | } else { | ||
44 | return cmd_results_new(CMD_INVALID, | ||
45 | "Expected `shortcuts_inhibitor enable|disable`"); | ||
46 | } | ||
47 | |||
48 | return cmd_results_new(CMD_SUCCESS, NULL); | ||
49 | } | ||
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 243f860b..dc07cbf0 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "sway/input/cursor.h" | 15 | #include "sway/input/cursor.h" |
16 | #include "sway/ipc-server.h" | 16 | #include "sway/ipc-server.h" |
17 | #include "sway/server.h" | 17 | #include "sway/server.h" |
18 | #include "sway/tree/view.h" | ||
18 | #include "stringop.h" | 19 | #include "stringop.h" |
19 | #include "list.h" | 20 | #include "list.h" |
20 | #include "log.h" | 21 | #include "log.h" |
@@ -333,12 +334,25 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor( | |||
333 | struct sway_seat *seat = inhibitor->seat->data; | 334 | struct sway_seat *seat = inhibitor->seat->data; |
334 | wl_list_insert(&seat->keyboard_shortcuts_inhibitors, &sway_inhibitor->link); | 335 | wl_list_insert(&seat->keyboard_shortcuts_inhibitors, &sway_inhibitor->link); |
335 | 336 | ||
336 | struct seat_config *config = seat_get_config(seat); | 337 | // per-view, seat-agnostic config via criteria |
337 | if (!config) { | 338 | struct sway_view *view = view_from_wlr_surface(inhibitor->surface); |
338 | config = seat_get_config_by_name("*"); | 339 | enum seat_config_shortcuts_inhibit inhibit = SHORTCUTS_INHIBIT_DEFAULT; |
340 | if (view) { | ||
341 | inhibit = view->shortcuts_inhibit; | ||
339 | } | 342 | } |
340 | 343 | ||
341 | if (config && config->shortcuts_inhibit == SHORTCUTS_INHIBIT_DISABLE) { | 344 | if (inhibit == SHORTCUTS_INHIBIT_DEFAULT) { |
345 | struct seat_config *config = seat_get_config(seat); | ||
346 | if (!config) { | ||
347 | config = seat_get_config_by_name("*"); | ||
348 | } | ||
349 | |||
350 | if (config) { | ||
351 | inhibit = config->shortcuts_inhibit; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if (inhibit == SHORTCUTS_INHIBIT_DISABLE) { | ||
342 | /** | 356 | /** |
343 | * Here we deny to honour the inhibitor by never sending the | 357 | * Here we deny to honour the inhibitor by never sending the |
344 | * activate signal. We can not, however, destroy the inhibitor | 358 | * activate signal. We can not, however, destroy the inhibitor |
diff --git a/sway/input/seat.c b/sway/input/seat.c index aa46940d..a4e06c57 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1499,16 +1499,22 @@ bool seatop_allows_set_cursor(struct sway_seat *seat) { | |||
1499 | } | 1499 | } |
1500 | 1500 | ||
1501 | struct sway_keyboard_shortcuts_inhibitor * | 1501 | struct sway_keyboard_shortcuts_inhibitor * |
1502 | keyboard_shortcuts_inhibitor_get_for_focused_surface( | 1502 | keyboard_shortcuts_inhibitor_get_for_surface( |
1503 | const struct sway_seat *seat) { | 1503 | const struct sway_seat *seat, |
1504 | struct wlr_surface *focused_surface = | 1504 | const struct wlr_surface *surface) { |
1505 | seat->wlr_seat->keyboard_state.focused_surface; | ||
1506 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = NULL; | 1505 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = NULL; |
1507 | wl_list_for_each(sway_inhibitor, &seat->keyboard_shortcuts_inhibitors, link) { | 1506 | wl_list_for_each(sway_inhibitor, &seat->keyboard_shortcuts_inhibitors, link) { |
1508 | if (sway_inhibitor->inhibitor->surface == focused_surface) { | 1507 | if (sway_inhibitor->inhibitor->surface == surface) { |
1509 | return sway_inhibitor; | 1508 | return sway_inhibitor; |
1510 | } | 1509 | } |
1511 | } | 1510 | } |
1512 | 1511 | ||
1513 | return NULL; | 1512 | return NULL; |
1514 | } | 1513 | } |
1514 | |||
1515 | struct sway_keyboard_shortcuts_inhibitor * | ||
1516 | keyboard_shortcuts_inhibitor_get_for_focused_surface( | ||
1517 | const struct sway_seat *seat) { | ||
1518 | return keyboard_shortcuts_inhibitor_get_for_surface(seat, | ||
1519 | seat->wlr_seat->keyboard_state.focused_surface); | ||
1520 | } | ||
diff --git a/sway/meson.build b/sway/meson.build index 226e6458..d71846a4 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -99,6 +99,7 @@ sway_sources = files( | |||
99 | 'commands/seat/xcursor_theme.c', | 99 | 'commands/seat/xcursor_theme.c', |
100 | 'commands/set.c', | 100 | 'commands/set.c', |
101 | 'commands/show_marks.c', | 101 | 'commands/show_marks.c', |
102 | 'commands/shortcuts_inhibitor.c', | ||
102 | 'commands/smart_borders.c', | 103 | 'commands/smart_borders.c', |
103 | 'commands/smart_gaps.c', | 104 | 'commands/smart_gaps.c', |
104 | 'commands/split.c', | 105 | 'commands/split.c', |
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index febf749f..9e42d897 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -304,6 +304,17 @@ set|plus|minus <amount> | |||
304 | Shows a window from the scratchpad. Repeatedly using this command will | 304 | Shows a window from the scratchpad. Repeatedly using this command will |
305 | cycle through the windows in the scratchpad. | 305 | cycle through the windows in the scratchpad. |
306 | 306 | ||
307 | *shortcuts inhibitor* enable|disable | ||
308 | Enables or disables the ability of clients to inhibit keyboard | ||
309 | shortcuts for a view. This is primarily useful for virtualization and | ||
310 | remote desktop software. It affects either the currently focused view | ||
311 | or a set of views selected by criteria. Subcommand _disable_ | ||
312 | additionally deactivates any active inhibitors for the given view(s). | ||
313 | Criteria are particularly useful with the *for_window* command to | ||
314 | configure a class of views differently from the per-seat defaults | ||
315 | established by the *seat* subcommand of the same name. See | ||
316 | *sway-input*(5) for more ways to affect inhibitors. | ||
317 | |||
307 | *split* vertical|v|horizontal|h|toggle|t | 318 | *split* vertical|v|horizontal|h|toggle|t |
308 | Splits the current container, vertically or horizontally. When _toggle_ is | 319 | Splits the current container, vertically or horizontally. When _toggle_ is |
309 | specified, the current container is split opposite to the parent | 320 | specified, the current container is split opposite to the parent |
diff --git a/sway/tree/view.c b/sway/tree/view.c index de1e936a..2b4b6c09 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -36,6 +36,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, | |||
36 | view->impl = impl; | 36 | view->impl = impl; |
37 | view->executed_criteria = create_list(); | 37 | view->executed_criteria = create_list(); |
38 | view->allow_request_urgent = true; | 38 | view->allow_request_urgent = true; |
39 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; | ||
39 | wl_signal_init(&view->events.unmap); | 40 | wl_signal_init(&view->events.unmap); |
40 | } | 41 | } |
41 | 42 | ||