bindings: allow unlocked and locked bindings
This changes the behavior of bindings to make the `BINDING_LOCKED` flag conflicting, which will allow for both unlocked and locked bindings. If there are two matching bindings and one has `--locked` and the other does not, the one with `--locked` will be preferred when locked and the one without will be preferred when unlocked. If there are two matching bindings and one has both a matching `--input-device=<input>` and `--locked` and the other has neither, the former will be preferred for both unlocked and locked. This also refactors `get_active_binding` in `sway/input/keyboard.c` to make it easier to read.
This commit is contained in:
parent
2c6a10c4ba
commit
6afb392823
|
@ -49,6 +49,10 @@ static bool binding_switch_compare(struct sway_switch_binding *binding_a,
|
||||||
if (binding_a->state != binding_b->state) {
|
if (binding_a->state != binding_b->state) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ((binding_a->flags & BINDING_LOCKED) !=
|
||||||
|
(binding_b->flags & BINDING_LOCKED)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +72,7 @@ static bool binding_key_compare(struct sway_binding *binding_a,
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t conflict_generating_flags = BINDING_RELEASE | BINDING_BORDER
|
uint32_t conflict_generating_flags = BINDING_RELEASE | BINDING_BORDER
|
||||||
| BINDING_CONTENTS | BINDING_TITLEBAR;
|
| BINDING_CONTENTS | BINDING_TITLEBAR | BINDING_LOCKED;
|
||||||
if ((binding_a->flags & conflict_generating_flags) !=
|
if ((binding_a->flags & conflict_generating_flags) !=
|
||||||
(binding_b->flags & conflict_generating_flags)) {
|
(binding_b->flags & conflict_generating_flags)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -146,7 +146,7 @@ static void get_active_binding(const struct sway_shortcut_state *state,
|
||||||
uint32_t modifiers, bool release, bool locked, const char *input) {
|
uint32_t modifiers, bool release, bool locked, const char *input) {
|
||||||
for (int i = 0; i < bindings->length; ++i) {
|
for (int i = 0; i < bindings->length; ++i) {
|
||||||
struct sway_binding *binding = bindings->items[i];
|
struct sway_binding *binding = bindings->items[i];
|
||||||
bool binding_locked = binding->flags & BINDING_LOCKED;
|
bool binding_locked = (binding->flags & BINDING_LOCKED) != 0;
|
||||||
bool binding_release = binding->flags & BINDING_RELEASE;
|
bool binding_release = binding->flags & BINDING_RELEASE;
|
||||||
|
|
||||||
if (modifiers ^ binding->modifiers ||
|
if (modifiers ^ binding->modifiers ||
|
||||||
|
@ -178,18 +178,37 @@ static void get_active_binding(const struct sway_shortcut_state *state,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*current_binding && *current_binding != binding &&
|
if (*current_binding) {
|
||||||
strcmp((*current_binding)->input, binding->input) == 0) {
|
if (*current_binding == binding) {
|
||||||
sway_log(SWAY_DEBUG, "encountered duplicate bindings %d and %d",
|
continue;
|
||||||
(*current_binding)->order, binding->order);
|
|
||||||
} else if (!*current_binding ||
|
|
||||||
strcmp((*current_binding)->input, "*") == 0) {
|
|
||||||
*current_binding = binding;
|
|
||||||
|
|
||||||
if (strcmp((*current_binding)->input, input) == 0) {
|
|
||||||
// If a binding is found for the exact input, quit searching
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool current_locked =
|
||||||
|
((*current_binding)->flags & BINDING_LOCKED) != 0;
|
||||||
|
bool current_input = strcmp((*current_binding)->input, input) == 0;
|
||||||
|
bool binding_input = strcmp(binding->input, input) == 0;
|
||||||
|
|
||||||
|
if (current_input == binding_input
|
||||||
|
&& current_locked == binding_locked) {
|
||||||
|
sway_log(SWAY_DEBUG,
|
||||||
|
"Encountered conflicting bindings %d and %d",
|
||||||
|
(*current_binding)->order, binding->order);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_input && !binding_input) {
|
||||||
|
continue; // Prefer the correct input
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_input == binding_input && current_locked == locked) {
|
||||||
|
continue; // Prefer correct lock state for matching inputs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*current_binding = binding;
|
||||||
|
if (strcmp((*current_binding)->input, input) == 0 &&
|
||||||
|
(((*current_binding)->flags & BINDING_LOCKED) == locked)) {
|
||||||
|
return; // If a perfect match is found, quit searching
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ static void handle_switch_toggle(struct wl_listener *listener, void *data) {
|
||||||
sway_log(SWAY_DEBUG, "%s: type %d state %d", device_identifier, type, state);
|
sway_log(SWAY_DEBUG, "%s: type %d state %d", device_identifier, type, state);
|
||||||
|
|
||||||
list_t *bindings = config->current_mode->switch_bindings;
|
list_t *bindings = config->current_mode->switch_bindings;
|
||||||
|
struct sway_switch_binding *matched_binding = NULL;
|
||||||
for (int i = 0; i < bindings->length; ++i) {
|
for (int i = 0; i < bindings->length; ++i) {
|
||||||
struct sway_switch_binding *binding = bindings->items[i];
|
struct sway_switch_binding *binding = bindings->items[i];
|
||||||
if (binding->type != type) {
|
if (binding->type != type) {
|
||||||
|
@ -52,10 +53,19 @@ static void handle_switch_toggle(struct wl_listener *listener, void *data) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sway_binding *dummy_binding = calloc(1, sizeof(struct sway_binding));
|
matched_binding = binding;
|
||||||
|
|
||||||
|
if (binding_locked == input_inhibited) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched_binding) {
|
||||||
|
struct sway_binding *dummy_binding =
|
||||||
|
calloc(1, sizeof(struct sway_binding));
|
||||||
dummy_binding->type = BINDING_SWITCH;
|
dummy_binding->type = BINDING_SWITCH;
|
||||||
dummy_binding->flags = binding->flags;
|
dummy_binding->flags = matched_binding->flags;
|
||||||
dummy_binding->command = binding->command;
|
dummy_binding->command = matched_binding->command;
|
||||||
|
|
||||||
seat_execute_command(seat, dummy_binding);
|
seat_execute_command(seat, dummy_binding);
|
||||||
free(dummy_binding);
|
free(dummy_binding);
|
||||||
|
|
|
@ -331,12 +331,17 @@ runtime.
|
||||||
Binds _key combo_ to execute the sway command _command_ when pressed. You
|
Binds _key combo_ to execute the sway command _command_ when pressed. You
|
||||||
may use XKB key names here (*xev*(1) is a good tool for discovering these).
|
may use XKB key names here (*xev*(1) is a good tool for discovering these).
|
||||||
With the flag _--release_, the command is executed when the key combo is
|
With the flag _--release_, the command is executed when the key combo is
|
||||||
released. Unless the flag _--locked_ is set, the command will not be run
|
released. If _input-device_ is given, the binding will only be executed for
|
||||||
when a screen locking program is active. If _input-device_ is given, the
|
that input device and will be executed instead of any binding that is
|
||||||
binding will only be executed for that input device and will be executed
|
generic to all devices. By default, if you overwrite a binding, swaynag
|
||||||
instead of any binding that is generic to all devices. By default, if you
|
will give you a warning. To silence this, use the _--no-warn_ flag.
|
||||||
overwrite a binding, swaynag will give you a warning. To silence this, use
|
|
||||||
the _--no-warn_ flag.
|
Unless the flag _--locked_ is set, the command will not be run when a
|
||||||
|
screen locking program is active. If there is a matching binding with
|
||||||
|
and without _--locked_, the one with will be preferred when locked and the
|
||||||
|
one without will be preferred when unlocked. If there are matching bindings
|
||||||
|
and one has both _--input-device_ and _--locked_ and the other has neither,
|
||||||
|
the former will be preferred even when unlocked.
|
||||||
|
|
||||||
Bindings to keysyms are layout-dependent. This can be changed with the
|
Bindings to keysyms are layout-dependent. This can be changed with the
|
||||||
_--to-code_ flag. In this case, the keysyms will be translated into the
|
_--to-code_ flag. In this case, the keysyms will be translated into the
|
||||||
|
@ -380,10 +385,13 @@ runtime.
|
||||||
respectively. _toggle_ is also supported to run a command both when the
|
respectively. _toggle_ is also supported to run a command both when the
|
||||||
switch is toggled on or off.
|
switch is toggled on or off.
|
||||||
|
|
||||||
Unless the flag _--locked_ is set, the command will not be run
|
Unless the flag _--locked_ is set, the command will not be run when a
|
||||||
when a screen locking program is active. By default, if you
|
screen locking program is active. If there is a matching binding with
|
||||||
overwrite a binding, swaynag will give you a warning. To silence this, use
|
and without _--locked_, the one with will be preferred when locked and the
|
||||||
the _--no-warn_ flag.
|
one without will be preferred when unlocked.
|
||||||
|
|
||||||
|
By default, if you overwrite a binding, swaynag will give you a warning. To
|
||||||
|
silence this, use the _--no-warn_ flag.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in a new issue