mirror of
https://github.com/swaywm/sway.git
synced 2025-11-20 06:59:46 -05:00
Merge pull request #2875 from RedSoxFan/input-device-bindings
cmd_bind{sym,code}: Implement per-device bindings
This commit is contained in:
commit
96e3686ae8
9 changed files with 77 additions and 36 deletions
|
|
@ -727,19 +727,23 @@ static void state_add_button(struct sway_cursor *cursor, uint32_t button) {
|
|||
* Return the mouse binding which matches modifier, click location, release,
|
||||
* and pressed button state, otherwise return null.
|
||||
*/
|
||||
static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *cursor,
|
||||
list_t *bindings, uint32_t modifiers, bool release, bool on_titlebar,
|
||||
bool on_border, bool on_content) {
|
||||
static struct sway_binding* get_active_mouse_binding(
|
||||
const struct sway_cursor *cursor, list_t *bindings, uint32_t modifiers,
|
||||
bool release, bool on_titlebar, bool on_border, bool on_content,
|
||||
const char *identifier) {
|
||||
uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) |
|
||||
(on_border ? BINDING_BORDER : 0) |
|
||||
(on_content ? BINDING_CONTENTS : 0);
|
||||
|
||||
struct sway_binding *current = NULL;
|
||||
for (int i = 0; i < bindings->length; ++i) {
|
||||
struct sway_binding *binding = bindings->items[i];
|
||||
if (modifiers ^ binding->modifiers ||
|
||||
cursor->pressed_button_count != (size_t)binding->keys->length ||
|
||||
release != (binding->flags & BINDING_RELEASE) ||
|
||||
!(click_region & binding->flags)) {
|
||||
!(click_region & binding->flags) ||
|
||||
(strcmp(binding->input, identifier) != 0 &&
|
||||
strcmp(binding->input, "*") != 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -755,13 +759,20 @@ static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *c
|
|||
continue;
|
||||
}
|
||||
|
||||
return binding;
|
||||
if (!current || strcmp(current->input, "*") == 0) {
|
||||
current = binding;
|
||||
if (strcmp(current->input, identifier) == 0) {
|
||||
// If a binding is found for the exact input, quit searching
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return current;
|
||||
}
|
||||
|
||||
void dispatch_cursor_button(struct sway_cursor *cursor,
|
||||
uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
|
||||
struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
|
||||
enum wlr_button_state state) {
|
||||
if (time_msec == 0) {
|
||||
time_msec = get_current_time_msec();
|
||||
}
|
||||
|
|
@ -797,18 +808,21 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
|
|||
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
|
||||
uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||
|
||||
char *device_identifier = device ? input_device_get_identifier(device)
|
||||
: strdup("*");
|
||||
struct sway_binding *binding = NULL;
|
||||
if (state == WLR_BUTTON_PRESSED) {
|
||||
state_add_button(cursor, button);
|
||||
binding = get_active_mouse_binding(cursor,
|
||||
config->current_mode->mouse_bindings, modifiers, false,
|
||||
on_titlebar, on_border, on_contents);
|
||||
on_titlebar, on_border, on_contents, device_identifier);
|
||||
} else {
|
||||
binding = get_active_mouse_binding(cursor,
|
||||
config->current_mode->mouse_bindings, modifiers, true,
|
||||
on_titlebar, on_border, on_contents);
|
||||
on_titlebar, on_border, on_contents, device_identifier);
|
||||
state_erase_button(cursor, button);
|
||||
}
|
||||
free(device_identifier);
|
||||
if (binding) {
|
||||
seat_execute_command(seat, binding);
|
||||
return;
|
||||
|
|
@ -942,7 +956,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
|
|||
struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
|
||||
wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
|
||||
struct wlr_event_pointer_button *event = data;
|
||||
dispatch_cursor_button(cursor,
|
||||
dispatch_cursor_button(cursor, event->device,
|
||||
event->time_msec, event->button, event->state);
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
|
@ -1128,7 +1142,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
|
|||
struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip);
|
||||
wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
|
||||
struct wlr_event_tablet_tool_tip *event = data;
|
||||
dispatch_cursor_button(cursor, event->time_msec,
|
||||
dispatch_cursor_button(cursor, event->device, event->time_msec,
|
||||
BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ?
|
||||
WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED);
|
||||
transaction_commit_dirty();
|
||||
|
|
@ -1143,14 +1157,14 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
|
|||
switch (event->state) {
|
||||
case WLR_BUTTON_PRESSED:
|
||||
if (cursor->tool_buttons == 0) {
|
||||
dispatch_cursor_button(cursor,
|
||||
dispatch_cursor_button(cursor, event->device,
|
||||
event->time_msec, BTN_RIGHT, event->state);
|
||||
}
|
||||
cursor->tool_buttons++;
|
||||
break;
|
||||
case WLR_BUTTON_RELEASED:
|
||||
if (cursor->tool_buttons == 1) {
|
||||
dispatch_cursor_button(cursor,
|
||||
dispatch_cursor_button(cursor, event->device,
|
||||
event->time_msec, BTN_RIGHT, event->state);
|
||||
}
|
||||
cursor->tool_buttons--;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ struct sway_seat *input_manager_get_seat(
|
|||
return seat_create(input, seat_name);
|
||||
}
|
||||
|
||||
static char *get_device_identifier(struct wlr_input_device *device) {
|
||||
char *input_device_get_identifier(struct wlr_input_device *device) {
|
||||
int vendor = device->vendor;
|
||||
int product = device->product;
|
||||
char *name = strdup(device->name);
|
||||
|
|
@ -278,7 +278,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
|
|||
device->data = input_device;
|
||||
|
||||
input_device->wlr_device = device;
|
||||
input_device->identifier = get_device_identifier(device);
|
||||
input_device->identifier = input_device_get_identifier(device);
|
||||
wl_list_insert(&input->devices, &input_device->link);
|
||||
|
||||
wlr_log(WLR_DEBUG, "adding device: '%s'",
|
||||
|
|
@ -375,7 +375,7 @@ void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
|
|||
device->data = input_device;
|
||||
|
||||
input_device->wlr_device = device;
|
||||
input_device->identifier = get_device_identifier(device);
|
||||
input_device->identifier = input_device_get_identifier(device);
|
||||
wl_list_insert(&input_manager->devices, &input_device->link);
|
||||
|
||||
wlr_log(WLR_DEBUG, "adding virtual keyboard: '%s'",
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static void 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) {
|
||||
uint32_t modifiers, bool release, bool locked, const char *input) {
|
||||
for (int i = 0; i < bindings->length; ++i) {
|
||||
struct sway_binding *binding = bindings->items[i];
|
||||
bool binding_locked = binding->flags & BINDING_LOCKED;
|
||||
|
|
@ -96,7 +96,9 @@ static void get_active_binding(const struct sway_shortcut_state *state,
|
|||
if (modifiers ^ binding->modifiers ||
|
||||
state->npressed != (size_t)binding->keys->length ||
|
||||
release != binding_release ||
|
||||
locked > binding_locked) {
|
||||
locked > binding_locked ||
|
||||
(strcmp(binding->input, input) != 0 &&
|
||||
strcmp(binding->input, "*") != 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -112,13 +114,19 @@ static void get_active_binding(const struct sway_shortcut_state *state,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (*current_binding && *current_binding != binding) {
|
||||
if (*current_binding && *current_binding != binding &&
|
||||
strcmp((*current_binding)->input, binding->input) == 0) {
|
||||
wlr_log(WLR_DEBUG, "encountered duplicate bindings %d and %d",
|
||||
(*current_binding)->order, binding->order);
|
||||
} else {
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,6 +210,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
|||
struct wlr_seat *wlr_seat = seat->wlr_seat;
|
||||
struct wlr_input_device *wlr_device =
|
||||
keyboard->seat_device->input_device->wlr_device;
|
||||
char *device_identifier = input_device_get_identifier(wlr_device);
|
||||
wlr_idle_notify_activity(seat->input->server->idle, wlr_seat);
|
||||
struct wlr_event_keyboard_key *event = data;
|
||||
bool input_inhibited = seat->exclusive_client != NULL;
|
||||
|
|
@ -242,13 +251,13 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
|||
struct sway_binding *binding_released = NULL;
|
||||
get_active_binding(&keyboard->state_keycodes,
|
||||
config->current_mode->keycode_bindings, &binding_released,
|
||||
code_modifiers, true, input_inhibited);
|
||||
code_modifiers, true, input_inhibited, device_identifier);
|
||||
get_active_binding(&keyboard->state_keysyms_translated,
|
||||
config->current_mode->keysym_bindings, &binding_released,
|
||||
translated_modifiers, true, input_inhibited);
|
||||
translated_modifiers, true, input_inhibited, device_identifier);
|
||||
get_active_binding(&keyboard->state_keysyms_raw,
|
||||
config->current_mode->keysym_bindings, &binding_released,
|
||||
raw_modifiers, true, input_inhibited);
|
||||
raw_modifiers, true, input_inhibited, device_identifier);
|
||||
|
||||
// Execute stored release binding once no longer active
|
||||
if (keyboard->held_binding && binding_released != keyboard->held_binding &&
|
||||
|
|
@ -268,13 +277,14 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
|||
if (event->state == WLR_KEY_PRESSED) {
|
||||
get_active_binding(&keyboard->state_keycodes,
|
||||
config->current_mode->keycode_bindings, &binding,
|
||||
code_modifiers, false, input_inhibited);
|
||||
code_modifiers, false, input_inhibited, device_identifier);
|
||||
get_active_binding(&keyboard->state_keysyms_translated,
|
||||
config->current_mode->keysym_bindings, &binding,
|
||||
translated_modifiers, false, input_inhibited);
|
||||
translated_modifiers, false, input_inhibited,
|
||||
device_identifier);
|
||||
get_active_binding(&keyboard->state_keysyms_raw,
|
||||
config->current_mode->keysym_bindings, &binding,
|
||||
raw_modifiers, false, input_inhibited);
|
||||
raw_modifiers, false, input_inhibited, device_identifier);
|
||||
|
||||
if (binding) {
|
||||
seat_execute_command(seat, binding);
|
||||
|
|
@ -315,6 +325,8 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
transaction_commit_dirty();
|
||||
|
||||
free(device_identifier);
|
||||
}
|
||||
|
||||
static int handle_keyboard_repeat(void *data) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue