Implement bindsym/bindcode --locked

Adds the --locked flag to bindsym and bindcode commands.

When a keyboard's associated seat has an exclusive client
(i.e, a screenlocker), then bindings are only executed if
they have the locked flag. When there is no such client,
this restriction is lifted.
This commit is contained in:
frsfnrrg 2018-05-27 12:37:18 -04:00
parent 0743b21cc8
commit a78a5684ea
4 changed files with 52 additions and 31 deletions

View file

@ -28,6 +28,7 @@ struct sway_variable {
struct sway_binding { struct sway_binding {
int order; int order;
bool release; bool release;
bool locked;
bool bindcode; bool bindcode;
list_t *keys; list_t *keys;
uint32_t modifiers; uint32_t modifiers;

View file

@ -83,20 +83,26 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) {
binding->keys = create_list(); binding->keys = create_list();
binding->modifiers = 0; binding->modifiers = 0;
binding->release = false; binding->release = false;
binding->locked = false;
binding->bindcode = false; binding->bindcode = false;
// Handle --release // Handle --release and --locked
if (strcmp("--release", argv[0]) == 0) { while (argc > 0) {
if (argc >= 3) { if (strcmp("--release", argv[0]) == 0) {
binding->release = true; binding->release = true;
argv++; } else if (strcmp("--locked", argv[0]) == 0) {
argc--; binding->locked = true;
} else { } else {
free_sway_binding(binding); break;
return cmd_results_new(CMD_FAILURE, "bindsym",
"Invalid bindsym command "
"(expected more than 2 arguments, got %d)", argc);
} }
argv++;
argc--;
}
if (argc < 2) {
free_sway_binding(binding);
return cmd_results_new(CMD_FAILURE, "bindsym",
"Invalid bindsym command "
"(expected at least 2 non-option arguments, got %d)", argc);
} }
binding->command = join_args(argv + 1, argc - 1); binding->command = join_args(argv + 1, argc - 1);
@ -176,20 +182,26 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) {
binding->keys = create_list(); binding->keys = create_list();
binding->modifiers = 0; binding->modifiers = 0;
binding->release = false; binding->release = false;
binding->locked = false;
binding->bindcode = true; binding->bindcode = true;
// Handle --release // Handle --release and --locked
if (strcmp("--release", argv[0]) == 0) { while (argc > 0) {
if (argc >= 3) { if (strcmp("--release", argv[0]) == 0) {
binding->release = true; binding->release = true;
argv++; } else if (strcmp("--locked", argv[0]) == 0) {
argc--; binding->locked = true;
} else { } else {
free_sway_binding(binding); break;
return cmd_results_new(CMD_FAILURE, "bindcode",
"Invalid bindcode command "
"(expected more than 2 arguments, got %d)", argc);
} }
argv++;
argc--;
}
if (argc < 2) {
free_sway_binding(binding);
return cmd_results_new(CMD_FAILURE, "bindcode",
"Invalid bindcode command "
"(expected at least 2 non-option arguments, got %d)", argc);
} }
binding->command = join_args(argv + 1, argc - 1); binding->command = join_args(argv + 1, argc - 1);

View file

@ -141,7 +141,7 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
*/ */
static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard,
xkb_keysym_t *pressed_keysyms, uint32_t modifiers, xkb_keysym_t *pressed_keysyms, uint32_t modifiers,
enum wlr_key_state key_state) { enum wlr_key_state key_state, bool locked) {
// configured bindings // configured bindings
int n = pressed_keysyms_length(pressed_keysyms); int n = pressed_keysyms_length(pressed_keysyms);
list_t *keysym_bindings = config->current_mode->keysym_bindings; list_t *keysym_bindings = config->current_mode->keysym_bindings;
@ -149,7 +149,7 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard,
struct sway_binding *binding = keysym_bindings->items[i]; struct sway_binding *binding = keysym_bindings->items[i];
if (!binding_matches_key_state(binding, key_state) || if (!binding_matches_key_state(binding, key_state) ||
modifiers ^ binding->modifiers || modifiers ^ binding->modifiers ||
n != binding->keys->length) { n != binding->keys->length || locked > binding->locked) {
continue; continue;
} }
@ -174,7 +174,7 @@ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard,
} }
static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, static bool binding_matches_keycodes(struct wlr_keyboard *keyboard,
struct sway_binding *binding, struct wlr_event_keyboard_key *event) { struct sway_binding *binding, struct wlr_event_keyboard_key *event, bool locked) {
assert(binding->bindcode); assert(binding->bindcode);
uint32_t keycode = event->keycode + 8; uint32_t keycode = event->keycode + 8;
@ -183,6 +183,10 @@ static bool binding_matches_keycodes(struct wlr_keyboard *keyboard,
return false; return false;
} }
if (locked > binding->locked) {
return false;
}
uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard); uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard);
if (modifiers ^ binding->modifiers) { if (modifiers ^ binding->modifiers) {
return false; return false;
@ -265,13 +269,13 @@ static bool binding_matches_keycodes(struct wlr_keyboard *keyboard,
* should be propagated to clients. * should be propagated to clients.
*/ */
static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard, static bool keyboard_execute_bindcode(struct sway_keyboard *keyboard,
struct wlr_event_keyboard_key *event) { struct wlr_event_keyboard_key *event, bool locked) {
struct wlr_keyboard *wlr_keyboard = struct wlr_keyboard *wlr_keyboard =
keyboard->seat_device->input_device->wlr_device->keyboard; keyboard->seat_device->input_device->wlr_device->keyboard;
list_t *keycode_bindings = config->current_mode->keycode_bindings; list_t *keycode_bindings = config->current_mode->keycode_bindings;
for (int i = 0; i < keycode_bindings->length; ++i) { for (int i = 0; i < keycode_bindings->length; ++i) {
struct sway_binding *binding = keycode_bindings->items[i]; struct sway_binding *binding = keycode_bindings->items[i];
if (binding_matches_keycodes(wlr_keyboard, binding, event)) { if (binding_matches_keycodes(wlr_keyboard, binding, event, locked)) {
keyboard_execute_command(keyboard, binding); keyboard_execute_command(keyboard, binding);
return true; return true;
} }
@ -333,19 +337,20 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
keyboard->seat_device->input_device->wlr_device; keyboard->seat_device->input_device->wlr_device;
wlr_idle_notify_activity(keyboard->seat_device->sway_seat->input->server->idle, wlr_seat); wlr_idle_notify_activity(keyboard->seat_device->sway_seat->input->server->idle, wlr_seat);
struct wlr_event_keyboard_key *event = data; struct wlr_event_keyboard_key *event = data;
bool input_inhibited = keyboard->seat_device->sway_seat->exclusive_client != NULL;
xkb_keycode_t keycode = event->keycode + 8; xkb_keycode_t keycode = event->keycode + 8;
bool handled = false; bool handled = false;
// handle keycodes // handle keycodes
handled = keyboard_execute_bindcode(keyboard, event); handled = keyboard_execute_bindcode(keyboard, event, input_inhibited);
// handle translated keysyms // handle translated keysyms
if (!handled && event->state == WLR_KEY_RELEASED) { if (!handled && event->state == WLR_KEY_RELEASED) {
handled = keyboard_execute_bindsym(keyboard, handled = keyboard_execute_bindsym(keyboard,
keyboard->pressed_keysyms_translated, keyboard->pressed_keysyms_translated,
keyboard->modifiers_translated, keyboard->modifiers_translated,
event->state); event->state, input_inhibited);
} }
const xkb_keysym_t *translated_keysyms; const xkb_keysym_t *translated_keysyms;
size_t translated_keysyms_len = size_t translated_keysyms_len =
@ -357,14 +362,14 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
handled = keyboard_execute_bindsym(keyboard, handled = keyboard_execute_bindsym(keyboard,
keyboard->pressed_keysyms_translated, keyboard->pressed_keysyms_translated,
keyboard->modifiers_translated, keyboard->modifiers_translated,
event->state); event->state, input_inhibited);
} }
// Handle raw keysyms // Handle raw keysyms
if (!handled && event->state == WLR_KEY_RELEASED) { if (!handled && event->state == WLR_KEY_RELEASED) {
handled = keyboard_execute_bindsym(keyboard, handled = keyboard_execute_bindsym(keyboard,
keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, keyboard->pressed_keysyms_raw, keyboard->modifiers_raw,
event->state); event->state, input_inhibited);
} }
const xkb_keysym_t *raw_keysyms; const xkb_keysym_t *raw_keysyms;
size_t raw_keysyms_len = size_t raw_keysyms_len =
@ -374,7 +379,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
if (!handled && event->state == WLR_KEY_PRESSED) { if (!handled && event->state == WLR_KEY_PRESSED) {
handled = keyboard_execute_bindsym(keyboard, handled = keyboard_execute_bindsym(keyboard,
keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, keyboard->pressed_keysyms_raw, keyboard->modifiers_raw,
event->state); event->state, input_inhibited);
} }
// Compositor bindings // Compositor bindings

View file

@ -186,17 +186,20 @@ runtime.
for\_window <criteria> move container to workspace <workspace> for\_window <criteria> move container to workspace <workspace>
*bindsym* <key combo> <command> *bindsym* [--release|--locked] <key combo> <command>
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
released. Unless the flag _--locked_ is set, the command will not be run
when a screen locking program is active.
Example: Example:
# Execute firefox when alt, shift, and f are pressed together # Execute firefox when alt, shift, and f are pressed together
bindsym Mod1+Shift+f exec firefox bindsym Mod1+Shift+f exec firefox
*bindcode* <code> <command> is also available for binding with key codes *bindcode* [--release|--locked] <code> <command> is also available for
instead of key names. binding with key codes instead of key names.
*client.<class>* <border> <background> <text> <indicator> <child\_border> *client.<class>* <border> <background> <text> <indicator> <child\_border>
Configures the color of window borders and title bars. All 5 colors are Configures the color of window borders and title bars. All 5 colors are