aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/input/seat.h8
-rw-r--r--include/sway/tree/view.h2
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/shortcuts_inhibitor.c49
-rw-r--r--sway/input/input-manager.c22
-rw-r--r--sway/input/seat.c16
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway.5.scd11
-rw-r--r--sway/tree/view.c1
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;
sway_cmd cmd_scratchpad;
sway_cmd cmd_seamless_mouse;
sway_cmd cmd_set;
+sway_cmd cmd_shortcuts_inhibitor;
sway_cmd cmd_show_marks;
sway_cmd cmd_smart_borders;
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,
bool seatop_allows_set_cursor(struct sway_seat *seat);
/**
+ * Returns the keyboard shortcuts inhibitor that applies to the given surface
+ * or NULL if none exists.
+ */
+struct sway_keyboard_shortcuts_inhibitor *
+keyboard_shortcuts_inhibitor_get_for_surface(const struct sway_seat *seat,
+ const struct wlr_surface *surface);
+
+/**
* Returns the keyboard shortcuts inhibitor that applies to the currently
* focused surface of a seat or NULL if none exists.
*/
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 {
struct wl_listener surface_new_subsurface;
int max_render_time; // In milliseconds
+
+ enum seat_config_shortcuts_inhibit shortcuts_inhibit;
};
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[] = {
{ "rename", cmd_rename },
{ "resize", cmd_resize },
{ "scratchpad", cmd_scratchpad },
+ { "shortcuts_inhibitor", cmd_shortcuts_inhibitor },
{ "split", cmd_split },
{ "splith", cmd_splith },
{ "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 @@
+#include <string.h>
+#include "log.h"
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "sway/input/seat.h"
+#include "sway/tree/container.h"
+#include "sway/tree/view.h"
+
+struct cmd_results *cmd_shortcuts_inhibitor(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "shortcuts_inhibitor", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ struct sway_container *con = config->handler_context.container;
+ if (!con || !con->view) {
+ return cmd_results_new(CMD_INVALID,
+ "Only views can have shortcuts inhibitors");
+ }
+
+ struct sway_view *view = con->view;
+ if (strcmp(argv[0], "enable") == 0) {
+ view->shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
+ } else if (strcmp(argv[0], "disable") == 0) {
+ view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DISABLE;
+
+ struct sway_seat *seat = NULL;
+ wl_list_for_each(seat, &server.input->seats, link) {
+ struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
+ keyboard_shortcuts_inhibitor_get_for_surface(
+ seat, view->surface);
+ if (!sway_inhibitor) {
+ continue;
+ }
+
+ wlr_keyboard_shortcuts_inhibitor_v1_deactivate(
+ sway_inhibitor->inhibitor);
+ sway_log(SWAY_DEBUG, "Deactivated keyboard shortcuts "
+ "inhibitor for seat %s on view",
+ seat->wlr_seat->name);
+
+ }
+ } else {
+ return cmd_results_new(CMD_INVALID,
+ "Expected `shortcuts_inhibitor enable|disable`");
+ }
+
+ return cmd_results_new(CMD_SUCCESS, NULL);
+}
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 @@
#include "sway/input/cursor.h"
#include "sway/ipc-server.h"
#include "sway/server.h"
+#include "sway/tree/view.h"
#include "stringop.h"
#include "list.h"
#include "log.h"
@@ -333,12 +334,25 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor(
struct sway_seat *seat = inhibitor->seat->data;
wl_list_insert(&seat->keyboard_shortcuts_inhibitors, &sway_inhibitor->link);
- struct seat_config *config = seat_get_config(seat);
- if (!config) {
- config = seat_get_config_by_name("*");
+ // per-view, seat-agnostic config via criteria
+ struct sway_view *view = view_from_wlr_surface(inhibitor->surface);
+ enum seat_config_shortcuts_inhibit inhibit = SHORTCUTS_INHIBIT_DEFAULT;
+ if (view) {
+ inhibit = view->shortcuts_inhibit;
}
- if (config && config->shortcuts_inhibit == SHORTCUTS_INHIBIT_DISABLE) {
+ if (inhibit == SHORTCUTS_INHIBIT_DEFAULT) {
+ struct seat_config *config = seat_get_config(seat);
+ if (!config) {
+ config = seat_get_config_by_name("*");
+ }
+
+ if (config) {
+ inhibit = config->shortcuts_inhibit;
+ }
+ }
+
+ if (inhibit == SHORTCUTS_INHIBIT_DISABLE) {
/**
* Here we deny to honour the inhibitor by never sending the
* 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) {
}
struct sway_keyboard_shortcuts_inhibitor *
-keyboard_shortcuts_inhibitor_get_for_focused_surface(
- const struct sway_seat *seat) {
- struct wlr_surface *focused_surface =
- seat->wlr_seat->keyboard_state.focused_surface;
+keyboard_shortcuts_inhibitor_get_for_surface(
+ const struct sway_seat *seat,
+ const struct wlr_surface *surface) {
struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = NULL;
wl_list_for_each(sway_inhibitor, &seat->keyboard_shortcuts_inhibitors, link) {
- if (sway_inhibitor->inhibitor->surface == focused_surface) {
+ if (sway_inhibitor->inhibitor->surface == surface) {
return sway_inhibitor;
}
}
return NULL;
}
+
+struct sway_keyboard_shortcuts_inhibitor *
+keyboard_shortcuts_inhibitor_get_for_focused_surface(
+ const struct sway_seat *seat) {
+ return keyboard_shortcuts_inhibitor_get_for_surface(seat,
+ seat->wlr_seat->keyboard_state.focused_surface);
+}
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(
'commands/seat/xcursor_theme.c',
'commands/set.c',
'commands/show_marks.c',
+ 'commands/shortcuts_inhibitor.c',
'commands/smart_borders.c',
'commands/smart_gaps.c',
'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>
Shows a window from the scratchpad. Repeatedly using this command will
cycle through the windows in the scratchpad.
+*shortcuts inhibitor* enable|disable
+ Enables or disables the ability of clients to inhibit keyboard
+ shortcuts for a view. This is primarily useful for virtualization and
+ remote desktop software. It affects either the currently focused view
+ or a set of views selected by criteria. Subcommand _disable_
+ additionally deactivates any active inhibitors for the given view(s).
+ Criteria are particularly useful with the *for_window* command to
+ configure a class of views differently from the per-seat defaults
+ established by the *seat* subcommand of the same name. See
+ *sway-input*(5) for more ways to affect inhibitors.
+
*split* vertical|v|horizontal|h|toggle|t
Splits the current container, vertically or horizontally. When _toggle_ is
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,
view->impl = impl;
view->executed_criteria = create_list();
view->allow_request_urgent = true;
+ view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT;
wl_signal_init(&view->events.unmap);
}