diff options
author | Ryan Dwyer <RyanDwyer@users.noreply.github.com> | 2018-07-24 19:48:27 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-24 19:48:27 +1000 |
commit | 1a9179dbab91490c4a8dc45f8630ac139c96efe6 (patch) | |
tree | 429de47906f0ba1f114689c48cbabc5be8bb6e71 /sway/input | |
parent | 6ccf2a2c66c1264450a4b3ab3dd344e1b3b44ca3 (diff) | |
parent | e02a6718c2c7313309b45e499034d614ee6207fc (diff) |
Merge pull request #2303 from frsfnrrg/mouse-bindings
Implement mouse bindings
Diffstat (limited to 'sway/input')
-rw-r--r-- | sway/input/cursor.c | 102 | ||||
-rw-r--r-- | sway/input/keyboard.c | 42 |
2 files changed, 117 insertions, 27 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 65d04cac..f1481936 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -469,6 +469,83 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor, seat_pointer_notify_button(seat, time_msec, button, state); } +/** + * Remove a button (and duplicates) to the sorted list of currently pressed buttons + */ +static void state_erase_button(struct sway_cursor *cursor, uint32_t button) { + size_t j = 0; + for (size_t i = 0; i < cursor->pressed_button_count; ++i) { + if (i > j) { + cursor->pressed_buttons[j] = cursor->pressed_buttons[i]; + } + if (cursor->pressed_buttons[i] != button) { + ++j; + } + } + while (cursor->pressed_button_count > j) { + --cursor->pressed_button_count; + cursor->pressed_buttons[cursor->pressed_button_count] = 0; + } +} + +/** + * Add a button to the sorted list of currently pressed buttons, if there + * is space. + */ +static void state_add_button(struct sway_cursor *cursor, uint32_t button) { + if (cursor->pressed_button_count >= SWAY_CURSOR_PRESSED_BUTTONS_CAP) { + return; + } + size_t i = 0; + while (i < cursor->pressed_button_count && cursor->pressed_buttons[i] < button) { + ++i; + } + size_t j = cursor->pressed_button_count; + while (j > i) { + cursor->pressed_buttons[j] = cursor->pressed_buttons[j - 1]; + --j; + } + cursor->pressed_buttons[i] = button; + cursor->pressed_button_count++; +} + +/** + * 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) { + uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) | + (on_border ? BINDING_BORDER : 0) | + (on_content ? BINDING_CONTENTS : 0); + + 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)) { + continue; + } + + bool match = true; + for (size_t j = 0; j < cursor->pressed_button_count; j++) { + uint32_t key = *(uint32_t *)binding->keys->items[j]; + if (key != cursor->pressed_buttons[j]) { + match = false; + break; + } + } + if (!match) { + continue; + } + + return binding; + } + return NULL; +} + void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, uint32_t button, enum wlr_button_state state) { if (cursor->seat->operation != OP_NONE && @@ -485,6 +562,31 @@ void dispatch_cursor_button(struct sway_cursor *cursor, double sx, sy; struct sway_container *cont = container_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + + // Handle mouse bindings + bool on_border = find_resize_edge(cont, cursor) != WLR_EDGE_NONE; + bool on_contents = !on_border && surface; + bool on_titlebar = !on_border && !surface; + struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat); + uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + + 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); + } else { + binding = get_active_mouse_binding(cursor, + config->current_mode->mouse_bindings, modifiers, true, + on_titlebar, on_border, on_contents); + state_erase_button(cursor, button); + } + if (binding) { + seat_execute_command(cursor->seat, binding); + // TODO: do we want to pass on the event? + } + if (surface && wlr_surface_is_layer_surface(surface)) { struct wlr_layer_surface *layer = wlr_layer_surface_from_wlr_surface(surface); diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index ede38519..49241db8 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -3,11 +3,11 @@ #include <wlr/backend/multi.h> #include <wlr/backend/session.h> #include <wlr/types/wlr_idle.h> +#include "sway/commands.h" #include "sway/desktop/transaction.h" -#include "sway/input/seat.h" -#include "sway/input/keyboard.h" #include "sway/input/input-manager.h" -#include "sway/commands.h" +#include "sway/input/keyboard.h" +#include "sway/input/seat.h" #include "log.h" /** @@ -88,11 +88,13 @@ static void get_active_binding(const struct sway_shortcut_state *state, uint32_t modifiers, bool release, bool locked) { for (int i = 0; i < bindings->length; ++i) { struct sway_binding *binding = bindings->items[i]; + bool binding_locked = binding->flags & BINDING_LOCKED; + bool binding_release = binding->flags & BINDING_RELEASE; if (modifiers ^ binding->modifiers || state->npressed != (size_t)binding->keys->length || - locked > binding->locked || - release != binding->release) { + release != binding_release || + locked > binding_locked) { continue; } @@ -119,23 +121,6 @@ static void get_active_binding(const struct sway_shortcut_state *state, } /** - * Execute the command associated to a binding - */ -static void keyboard_execute_command(struct sway_keyboard *keyboard, - struct sway_binding *binding) { - wlr_log(WLR_DEBUG, "running command for binding: %s", - binding->command); - config->handler_context.seat = keyboard->seat_device->sway_seat; - struct cmd_results *results = execute_command(binding->command, NULL); - transaction_commit_dirty(); - if (results->status != CMD_SUCCESS) { - wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", - binding->command, results->error); - } - free_cmd_results(results); -} - -/** * Execute a built-in, hardcoded compositor binding. These are triggered from a * single keysym. * @@ -211,12 +196,13 @@ static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, static void handle_keyboard_key(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = wl_container_of(listener, keyboard, keyboard_key); - struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; + struct sway_seat* seat = keyboard->seat_device->sway_seat; + struct wlr_seat *wlr_seat = seat->wlr_seat; struct wlr_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(seat->input->server->idle, wlr_seat); struct wlr_event_keyboard_key *event = data; - bool input_inhibited = keyboard->seat_device->sway_seat->exclusive_client != NULL; + bool input_inhibited = seat->exclusive_client != NULL; // Identify new keycode, raw keysym(s), and translated keysym(s) xkb_keycode_t keycode = event->keycode + 8; @@ -266,7 +252,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { // Execute stored release binding once no longer active if (keyboard->held_binding && binding_released != keyboard->held_binding && event->state == WLR_KEY_RELEASED) { - keyboard_execute_command(keyboard, keyboard->held_binding); + seat_execute_command(seat, keyboard->held_binding); handled = true; } if (binding_released != keyboard->held_binding) { @@ -290,7 +276,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { raw_modifiers, false, input_inhibited); if (binding_pressed) { - keyboard_execute_command(keyboard, binding_pressed); + seat_execute_command(seat, binding_pressed); handled = true; } } @@ -312,6 +298,8 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, event->keycode, event->state); } + + transaction_commit_dirty(); } static void handle_keyboard_modifiers(struct wl_listener *listener, |