diff --git a/include/sway/config.h b/include/sway/config.h index 33f52156..118981e3 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -28,6 +28,7 @@ struct sway_variable { struct sway_binding { int order; bool release; + bool locked; bool bindcode; list_t *keys; uint32_t modifiers; diff --git a/sway/commands/bind.c b/sway/commands/bind.c index cbabb07b..c6b3368a 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -83,20 +83,26 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { binding->keys = create_list(); binding->modifiers = 0; binding->release = false; + binding->locked = false; binding->bindcode = false; - // Handle --release - if (strcmp("--release", argv[0]) == 0) { - if (argc >= 3) { + // Handle --release and --locked + while (argc > 0) { + if (strcmp("--release", argv[0]) == 0) { binding->release = true; - argv++; - argc--; + } else if (strcmp("--locked", argv[0]) == 0) { + binding->locked = true; } else { - free_sway_binding(binding); - return cmd_results_new(CMD_FAILURE, "bindsym", - "Invalid bindsym command " - "(expected more than 2 arguments, got %d)", argc); + break; } + 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); @@ -176,20 +182,26 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { binding->keys = create_list(); binding->modifiers = 0; binding->release = false; + binding->locked = false; binding->bindcode = true; - // Handle --release - if (strcmp("--release", argv[0]) == 0) { - if (argc >= 3) { + // Handle --release and --locked + while (argc > 0) { + if (strcmp("--release", argv[0]) == 0) { binding->release = true; - argv++; - argc--; + } else if (strcmp("--locked", argv[0]) == 0) { + binding->locked = true; } else { - free_sway_binding(binding); - return cmd_results_new(CMD_FAILURE, "bindcode", - "Invalid bindcode command " - "(expected more than 2 arguments, got %d)", argc); + break; } + 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); diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index c07557db..e873eea3 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -141,7 +141,7 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, */ static bool keyboard_execute_bindsym(struct sway_keyboard *keyboard, xkb_keysym_t *pressed_keysyms, uint32_t modifiers, - enum wlr_key_state key_state) { + enum wlr_key_state key_state, bool locked) { // configured bindings int n = pressed_keysyms_length(pressed_keysyms); 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]; if (!binding_matches_key_state(binding, key_state) || modifiers ^ binding->modifiers || - n != binding->keys->length) { + n != binding->keys->length || locked > binding->locked) { continue; } @@ -174,7 +174,7 @@ static bool keyboard_execute_bindsym(struct sway_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); uint32_t keycode = event->keycode + 8; @@ -183,6 +183,10 @@ static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, return false; } + if (locked > binding->locked) { + return false; + } + uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard); if (modifiers ^ binding->modifiers) { return false; @@ -265,13 +269,13 @@ static bool binding_matches_keycodes(struct wlr_keyboard *keyboard, * should be propagated to clients. */ 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 = keyboard->seat_device->input_device->wlr_device->keyboard; list_t *keycode_bindings = config->current_mode->keycode_bindings; for (int i = 0; i < keycode_bindings->length; ++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); return true; } @@ -333,19 +337,20 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { keyboard->seat_device->input_device->wlr_device; wlr_idle_notify_activity(keyboard->seat_device->sway_seat->input->server->idle, wlr_seat); 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; bool handled = false; // handle keycodes - handled = keyboard_execute_bindcode(keyboard, event); + handled = keyboard_execute_bindcode(keyboard, event, input_inhibited); // handle translated keysyms if (!handled && event->state == WLR_KEY_RELEASED) { handled = keyboard_execute_bindsym(keyboard, keyboard->pressed_keysyms_translated, keyboard->modifiers_translated, - event->state); + event->state, input_inhibited); } const xkb_keysym_t *translated_keysyms; 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, keyboard->pressed_keysyms_translated, keyboard->modifiers_translated, - event->state); + event->state, input_inhibited); } // Handle raw keysyms if (!handled && event->state == WLR_KEY_RELEASED) { handled = keyboard_execute_bindsym(keyboard, keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, - event->state); + event->state, input_inhibited); } const xkb_keysym_t *raw_keysyms; 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) { handled = keyboard_execute_bindsym(keyboard, keyboard->pressed_keysyms_raw, keyboard->modifiers_raw, - event->state); + event->state, input_inhibited); } // Compositor bindings diff --git a/sway/sway.5.scd b/sway/sway.5.scd index e6bc5a1e..5d99c9d6 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -186,17 +186,20 @@ runtime. for\_window move container to workspace -*bindsym* +*bindsym* [--release|--locked] 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). + 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: # Execute firefox when alt, shift, and f are pressed together bindsym Mod1+Shift+f exec firefox - *bindcode* is also available for binding with key codes - instead of key names. + *bindcode* [--release|--locked] is also available for + binding with key codes instead of key names. *client.* Configures the color of window borders and title bars. All 5 colors are