aboutsummaryrefslogtreecommitdiff
path: root/sway/input
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input')
-rw-r--r--sway/input/input-manager.c47
-rw-r--r--sway/input/keyboard.c41
-rw-r--r--sway/input/seat.c16
3 files changed, 95 insertions, 9 deletions
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index 4cc07fe6..af0f5afa 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -296,6 +296,46 @@ static void handle_inhibit_deactivate(struct wl_listener *listener, void *data)
}
}
+static void handle_keyboard_shortcuts_inhibitor_destroy(
+ struct wl_listener *listener, void *data) {
+ struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
+ wl_container_of(listener, sway_inhibitor, destroy);
+
+ sway_log(SWAY_DEBUG, "Removing keyboard shortcuts inhibitor");
+
+ // sway_seat::keyboard_shortcuts_inhibitors
+ wl_list_remove(&sway_inhibitor->link);
+ wl_list_remove(&sway_inhibitor->destroy.link);
+ free(sway_inhibitor);
+}
+
+static void handle_keyboard_shortcuts_inhibit_new_inhibitor(
+ struct wl_listener *listener, void *data) {
+ struct sway_input_manager *input_manager =
+ wl_container_of(listener, input_manager,
+ keyboard_shortcuts_inhibit_new_inhibitor);
+ struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor = data;
+
+ sway_log(SWAY_DEBUG, "Adding keyboard shortcuts inhibitor");
+
+ struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
+ calloc(1, sizeof(struct sway_keyboard_shortcuts_inhibitor));
+ if (!sway_assert(sway_inhibitor, "could not allocate keyboard "
+ "shortcuts inhibitor")) {
+ return;
+ }
+ sway_inhibitor->inhibitor = inhibitor;
+
+ sway_inhibitor->destroy.notify = handle_keyboard_shortcuts_inhibitor_destroy;
+ wl_signal_add(&inhibitor->events.destroy, &sway_inhibitor->destroy);
+
+ // attach inhibitor to the seat it applies to
+ struct sway_seat *seat = inhibitor->seat->data;
+ wl_list_insert(&seat->keyboard_shortcuts_inhibitors, &sway_inhibitor->link);
+
+ wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor);
+}
+
void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
struct sway_input_manager *input_manager =
wl_container_of(listener, input_manager, virtual_keyboard_new);
@@ -397,6 +437,13 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
wl_signal_add(&input->inhibit->events.deactivate,
&input->inhibit_deactivate);
+ input->keyboard_shortcuts_inhibit =
+ wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display);
+ input->keyboard_shortcuts_inhibit_new_inhibitor.notify =
+ handle_keyboard_shortcuts_inhibit_new_inhibitor;
+ wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor,
+ &input->keyboard_shortcuts_inhibit_new_inhibitor);
+
return input;
}
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index 2cfcd126..9c5f190e 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -150,16 +150,18 @@ static bool update_shortcut_state(struct sway_shortcut_state *state,
*/
static void get_active_binding(const struct sway_shortcut_state *state,
list_t *bindings, struct sway_binding **current_binding,
- uint32_t modifiers, bool release, bool locked, const char *input,
- bool exact_input, xkb_layout_index_t group) {
+ uint32_t modifiers, bool release, bool locked, bool inhibited,
+ const char *input, bool exact_input, xkb_layout_index_t group) {
for (int i = 0; i < bindings->length; ++i) {
struct sway_binding *binding = bindings->items[i];
bool binding_locked = (binding->flags & BINDING_LOCKED) != 0;
+ bool binding_inhibited = (binding->flags & BINDING_INHIBITED) != 0;
bool binding_release = binding->flags & BINDING_RELEASE;
if (modifiers ^ binding->modifiers ||
release != binding_release ||
locked > binding_locked ||
+ inhibited > binding_inhibited ||
(binding->group != XKB_LAYOUT_INVALID &&
binding->group != group) ||
(strcmp(binding->input, input) != 0 &&
@@ -195,6 +197,8 @@ static void get_active_binding(const struct sway_shortcut_state *state,
bool current_locked =
((*current_binding)->flags & BINDING_LOCKED) != 0;
+ bool current_inhibited =
+ ((*current_binding)->flags & BINDING_INHIBITED) != 0;
bool current_input = strcmp((*current_binding)->input, input) == 0;
bool current_group_set =
(*current_binding)->group != XKB_LAYOUT_INVALID;
@@ -203,6 +207,7 @@ static void get_active_binding(const struct sway_shortcut_state *state,
if (current_input == binding_input
&& current_locked == binding_locked
+ && current_inhibited == binding_inhibited
&& current_group_set == binding_group_set) {
sway_log(SWAY_DEBUG,
"Encountered conflicting bindings %d and %d",
@@ -224,11 +229,21 @@ static void get_active_binding(const struct sway_shortcut_state *state,
current_locked == locked) {
continue; // Prefer correct lock state for matching input+group
}
+
+ if (current_input == binding_input &&
+ current_group_set == binding_group_set &&
+ current_locked == binding_locked &&
+ current_inhibited == inhibited) {
+ // Prefer correct inhibition state for matching
+ // input+group+locked
+ continue;
+ }
}
*current_binding = binding;
if (strcmp((*current_binding)->input, input) == 0 &&
(((*current_binding)->flags & BINDING_LOCKED) == locked) &&
+ (((*current_binding)->flags & BINDING_INHIBITED) == inhibited) &&
(*current_binding)->group == group) {
return; // If a perfect match is found, quit searching
}
@@ -328,6 +343,9 @@ static void handle_key_event(struct sway_keyboard *keyboard,
bool exact_identifier = wlr_device->keyboard->group != NULL;
seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD);
bool input_inhibited = seat->exclusive_client != NULL;
+ struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
+ keyboard_shortcuts_inhibitor_get_for_focused_surface(seat);
+ bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active;
// Identify new keycode, raw keysym(s), and translated keysym(s)
xkb_keycode_t keycode = event->keycode + 8;
@@ -364,15 +382,18 @@ static void handle_key_event(struct sway_keyboard *keyboard,
struct sway_binding *binding_released = NULL;
get_active_binding(&keyboard->state_keycodes,
config->current_mode->keycode_bindings, &binding_released,
- code_modifiers, true, input_inhibited, device_identifier,
+ code_modifiers, true, input_inhibited,
+ shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_raw,
config->current_mode->keysym_bindings, &binding_released,
- raw_modifiers, true, input_inhibited, device_identifier,
+ raw_modifiers, true, input_inhibited,
+ shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_translated,
config->current_mode->keysym_bindings, &binding_released,
- translated_modifiers, true, input_inhibited, device_identifier,
+ translated_modifiers, true, input_inhibited,
+ shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout);
// Execute stored release binding once no longer active
@@ -393,17 +414,19 @@ static void handle_key_event(struct sway_keyboard *keyboard,
if (event->state == WLR_KEY_PRESSED) {
get_active_binding(&keyboard->state_keycodes,
config->current_mode->keycode_bindings, &binding,
- code_modifiers, false, input_inhibited, device_identifier,
+ code_modifiers, false, input_inhibited,
+ shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_raw,
config->current_mode->keysym_bindings, &binding,
- raw_modifiers, false, input_inhibited, device_identifier,
+ raw_modifiers, false, input_inhibited,
+ shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_translated,
config->current_mode->keysym_bindings, &binding,
translated_modifiers, false, input_inhibited,
- device_identifier, exact_identifier,
- keyboard->effective_layout);
+ shortcuts_inhibited, device_identifier,
+ exact_identifier, keyboard->effective_layout);
}
// Set up (or clear) keyboard repeat for a pressed binding. Since the
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 371de56e..6739c163 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -557,6 +557,7 @@ struct sway_seat *seat_create(const char *seat_name) {
handle_request_set_primary_selection;
wl_list_init(&seat->keyboard_groups);
+ wl_list_init(&seat->keyboard_shortcuts_inhibitors);
wl_list_insert(&server.input->seats, &seat->link);
@@ -1473,3 +1474,18 @@ void seatop_render(struct sway_seat *seat, struct sway_output *output,
bool seatop_allows_set_cursor(struct sway_seat *seat) {
return seat->seatop_impl->allow_set_cursor;
}
+
+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;
+ 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) {
+ return sway_inhibitor;
+ }
+ }
+
+ return NULL;
+}