mirror of
https://github.com/swaywm/sway.git
synced 2024-11-22 07:51:28 +00:00
commands: Add shortcuts_inhibitor command
Add a command to influence keyboard shortcuts inhibitors. In its current form it can be used to activate, deactivate or toggle an existing inhibitor on the surface currently receiving input. This can be used to define an escape shortcut such as: bindsym --inhibited $mod+Escape seat - shortcuts_inhibitor deactivate It also allows the user to configure a per-seat default of whether keyboard inhibitors are honoured by default (the default) or not. Using the activate/toggle command they can then enable the lingering inhibitor at a later time of their choosing. As a side effect this allows to specifically address a named seat for actions as well, whatever use-case that might serve. Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
This commit is contained in:
parent
eeac0aa170
commit
3ee5aace33
|
@ -288,6 +288,7 @@ sway_cmd seat_cmd_idle_inhibit;
|
||||||
sway_cmd seat_cmd_idle_wake;
|
sway_cmd seat_cmd_idle_wake;
|
||||||
sway_cmd seat_cmd_keyboard_grouping;
|
sway_cmd seat_cmd_keyboard_grouping;
|
||||||
sway_cmd seat_cmd_pointer_constraint;
|
sway_cmd seat_cmd_pointer_constraint;
|
||||||
|
sway_cmd seat_cmd_shortcuts_inhibitor;
|
||||||
sway_cmd seat_cmd_xcursor_theme;
|
sway_cmd seat_cmd_xcursor_theme;
|
||||||
|
|
||||||
sway_cmd cmd_ipc_cmd;
|
sway_cmd cmd_ipc_cmd;
|
||||||
|
|
|
@ -177,6 +177,12 @@ enum seat_config_allow_constrain {
|
||||||
CONSTRAIN_DISABLE
|
CONSTRAIN_DISABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum seat_config_shortcuts_inhibit {
|
||||||
|
SHORTCUTS_INHIBIT_DEFAULT, // the default is currently enabled
|
||||||
|
SHORTCUTS_INHIBIT_ENABLE,
|
||||||
|
SHORTCUTS_INHIBIT_DISABLE
|
||||||
|
};
|
||||||
|
|
||||||
enum seat_keyboard_grouping {
|
enum seat_keyboard_grouping {
|
||||||
KEYBOARD_GROUP_DEFAULT, // the default is currently smart
|
KEYBOARD_GROUP_DEFAULT, // the default is currently smart
|
||||||
KEYBOARD_GROUP_NONE,
|
KEYBOARD_GROUP_NONE,
|
||||||
|
@ -201,6 +207,7 @@ struct seat_config {
|
||||||
list_t *attachments; // list of seat_attachment configs
|
list_t *attachments; // list of seat_attachment configs
|
||||||
int hide_cursor_timeout;
|
int hide_cursor_timeout;
|
||||||
enum seat_config_allow_constrain allow_constrain;
|
enum seat_config_allow_constrain allow_constrain;
|
||||||
|
enum seat_config_shortcuts_inhibit shortcuts_inhibit;
|
||||||
enum seat_keyboard_grouping keyboard_grouping;
|
enum seat_keyboard_grouping keyboard_grouping;
|
||||||
uint32_t idle_inhibit_sources, idle_wake_sources;
|
uint32_t idle_inhibit_sources, idle_wake_sources;
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -22,6 +22,7 @@ static struct cmd_handler seat_handlers[] = {
|
||||||
{ "idle_wake", seat_cmd_idle_wake },
|
{ "idle_wake", seat_cmd_idle_wake },
|
||||||
{ "keyboard_grouping", seat_cmd_keyboard_grouping },
|
{ "keyboard_grouping", seat_cmd_keyboard_grouping },
|
||||||
{ "pointer_constraint", seat_cmd_pointer_constraint },
|
{ "pointer_constraint", seat_cmd_pointer_constraint },
|
||||||
|
{ "shortcuts_inhibitor", seat_cmd_shortcuts_inhibitor },
|
||||||
{ "xcursor_theme", seat_cmd_xcursor_theme },
|
{ "xcursor_theme", seat_cmd_xcursor_theme },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
96
sway/commands/seat/shortcuts_inhibitor.c
Normal file
96
sway/commands/seat/shortcuts_inhibitor.c
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
#include "log.h"
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/input/seat.h"
|
||||||
|
#include "sway/input/input-manager.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static struct cmd_results *handle_action(struct seat_config *sc,
|
||||||
|
struct sway_seat *seat, const char *action) {
|
||||||
|
struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = NULL;
|
||||||
|
if (strcmp(action, "disable") == 0) {
|
||||||
|
sc->shortcuts_inhibit = SHORTCUTS_INHIBIT_DISABLE;
|
||||||
|
|
||||||
|
wl_list_for_each(sway_inhibitor,
|
||||||
|
&seat->keyboard_shortcuts_inhibitors, link) {
|
||||||
|
wlr_keyboard_shortcuts_inhibitor_v1_deactivate(
|
||||||
|
sway_inhibitor->inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_log(SWAY_DEBUG, "Deactivated all keyboard shortcuts inhibitors");
|
||||||
|
} else {
|
||||||
|
sway_inhibitor = keyboard_shortcuts_inhibitor_get_for_focused_surface(seat);
|
||||||
|
if (!sway_inhibitor) {
|
||||||
|
return cmd_results_new(CMD_FAILURE,
|
||||||
|
"No inhibitor found for focused surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor =
|
||||||
|
sway_inhibitor->inhibitor;
|
||||||
|
bool inhibit;
|
||||||
|
if (strcmp(action, "activate") == 0) {
|
||||||
|
inhibit = true;
|
||||||
|
} else if (strcmp(action, "deactivate") == 0) {
|
||||||
|
inhibit = false;
|
||||||
|
} else if (strcmp(action, "toggle") == 0) {
|
||||||
|
inhibit = !inhibitor->active;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "Expected enable|"
|
||||||
|
"disable|activate|deactivate|toggle");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inhibit) {
|
||||||
|
wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor);
|
||||||
|
} else {
|
||||||
|
wlr_keyboard_shortcuts_inhibitor_v1_deactivate(inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_log(SWAY_DEBUG, "%sctivated keyboard shortcuts inhibitor",
|
||||||
|
inhibit ? "A" : "Dea");
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shortcuts_inhibitor [enable|disable|activate|deactivate|toggle]
|
||||||
|
struct cmd_results *seat_cmd_shortcuts_inhibitor(int argc, char **argv) {
|
||||||
|
struct cmd_results *error =
|
||||||
|
checkarg(argc, "shortcuts_inhibitor", EXPECTED_EQUAL_TO, 1);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct seat_config *sc = config->handler_context.seat_config;
|
||||||
|
if (!sc) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "No seat defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[0], "enable") == 0) {
|
||||||
|
sc->shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
||||||
|
// at runtime disable is an action that also deactivates all active
|
||||||
|
// inhibitors handled in handle_action()
|
||||||
|
} else if (strcmp(argv[0], "disable") == 0 && !config->active) {
|
||||||
|
sc->shortcuts_inhibit = SHORTCUTS_INHIBIT_DISABLE;
|
||||||
|
} else if (!config->active) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "only enable and disable "
|
||||||
|
"can be used in the config");
|
||||||
|
} else {
|
||||||
|
if (strcmp(sc->name, "*") != 0) {
|
||||||
|
struct sway_seat *seat = input_manager_get_seat(sc->name, false);
|
||||||
|
if (!seat) {
|
||||||
|
return cmd_results_new(CMD_FAILURE,
|
||||||
|
"Seat %s does not exist", sc->name);
|
||||||
|
}
|
||||||
|
error = handle_action(sc, seat, argv[0]);
|
||||||
|
} else {
|
||||||
|
struct sway_seat *seat = NULL;
|
||||||
|
wl_list_for_each(seat, &server.input->seats, link) {
|
||||||
|
error = handle_action(sc, seat, argv[0]);
|
||||||
|
if (error && error->status != CMD_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error ? error : cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ struct seat_config *new_seat_config(const char* name) {
|
||||||
}
|
}
|
||||||
seat->hide_cursor_timeout = -1;
|
seat->hide_cursor_timeout = -1;
|
||||||
seat->allow_constrain = CONSTRAIN_DEFAULT;
|
seat->allow_constrain = CONSTRAIN_DEFAULT;
|
||||||
|
seat->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT;
|
||||||
seat->keyboard_grouping = KEYBOARD_GROUP_DEFAULT;
|
seat->keyboard_grouping = KEYBOARD_GROUP_DEFAULT;
|
||||||
seat->xcursor_theme.name = NULL;
|
seat->xcursor_theme.name = NULL;
|
||||||
seat->xcursor_theme.size = 24;
|
seat->xcursor_theme.size = 24;
|
||||||
|
@ -154,6 +155,10 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) {
|
||||||
dest->allow_constrain = source->allow_constrain;
|
dest->allow_constrain = source->allow_constrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (source->shortcuts_inhibit != SHORTCUTS_INHIBIT_DEFAULT) {
|
||||||
|
dest->shortcuts_inhibit = source->shortcuts_inhibit;
|
||||||
|
}
|
||||||
|
|
||||||
if (source->keyboard_grouping != KEYBOARD_GROUP_DEFAULT) {
|
if (source->keyboard_grouping != KEYBOARD_GROUP_DEFAULT) {
|
||||||
dest->keyboard_grouping = source->keyboard_grouping;
|
dest->keyboard_grouping = source->keyboard_grouping;
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,6 +333,26 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor(
|
||||||
struct sway_seat *seat = inhibitor->seat->data;
|
struct sway_seat *seat = inhibitor->seat->data;
|
||||||
wl_list_insert(&seat->keyboard_shortcuts_inhibitors, &sway_inhibitor->link);
|
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("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config && config->shortcuts_inhibit == SHORTCUTS_INHIBIT_DISABLE) {
|
||||||
|
/**
|
||||||
|
* Here we deny to honour the inhibitor by never sending the
|
||||||
|
* activate signal. We can not, however, destroy the inhibitor
|
||||||
|
* because the protocol doesn't allow for it. So it will linger
|
||||||
|
* until the client removes it im- or explicitly. But at least
|
||||||
|
* it can only be one inhibitor per surface and seat at a time.
|
||||||
|
*
|
||||||
|
* We also want to allow the user to activate the inhibitor
|
||||||
|
* manually later which is why we do this check here where the
|
||||||
|
* inhibitor is already attached to its seat and ready for use.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor);
|
wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ sway_sources = files(
|
||||||
'commands/seat/idle.c',
|
'commands/seat/idle.c',
|
||||||
'commands/seat/keyboard_grouping.c',
|
'commands/seat/keyboard_grouping.c',
|
||||||
'commands/seat/pointer_constraint.c',
|
'commands/seat/pointer_constraint.c',
|
||||||
|
'commands/seat/shortcuts_inhibitor.c',
|
||||||
'commands/seat/xcursor_theme.c',
|
'commands/seat/xcursor_theme.c',
|
||||||
'commands/set.c',
|
'commands/set.c',
|
||||||
'commands/show_marks.c',
|
'commands/show_marks.c',
|
||||||
|
|
|
@ -243,6 +243,25 @@ correct seat.
|
||||||
by default) for the seat. This is primarily useful for video games. The
|
by default) for the seat. This is primarily useful for video games. The
|
||||||
"escape" command can be used at runtime to escape from a captured client.
|
"escape" command can be used at runtime to escape from a captured client.
|
||||||
|
|
||||||
|
*seat* <name> shortcuts_inhibitor enable|disable|activate|deactivate|toggle
|
||||||
|
Enables or disables the ability of clients to inhibit keyboard
|
||||||
|
shortcuts for the seat. This is primarily useful for virtualization and
|
||||||
|
remote desktop software. Subcommands _enable_ and _disable_ affect
|
||||||
|
whether future inhibitors are honoured by default, i.e. activated
|
||||||
|
automatically, the default being _enable_. When used at runtime,
|
||||||
|
_disable_ also disables any currently active inhibitors. _activate_,
|
||||||
|
_deactivate_ and _toggle_ are only useable at runtime and change the
|
||||||
|
state of a potentially existing inhibitor on the currently focused
|
||||||
|
window. This can be used with the current seat alias (_-_) to affect
|
||||||
|
only the currently focused window of the current seat. Subcommand
|
||||||
|
_deactivate_ is particularly useful in an _--inhibited_ *bindsym* to
|
||||||
|
escape a state where shortcuts are inhibited and the client becomes
|
||||||
|
uncooperative. It is worth noting that whether disabled or deactivated
|
||||||
|
inhibitors are removed is entirely up to the client. Depending on the
|
||||||
|
client it may therefore be possible to (re-)activate them later. Any
|
||||||
|
visual indication that an inhibitor is present is currently left to the
|
||||||
|
client as well.
|
||||||
|
|
||||||
*seat* <name> xcursor_theme <theme> [<size>]
|
*seat* <name> xcursor_theme <theme> [<size>]
|
||||||
Override the system default XCursor theme. The default seat's
|
Override the system default XCursor theme. The default seat's
|
||||||
(_seat0_) theme is also used as the default cursor theme in
|
(_seat0_) theme is also used as the default cursor theme in
|
||||||
|
|
Loading…
Reference in a new issue