aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/cursor.c
diff options
context:
space:
mode:
authorLibravatar frsfnrrg <frsfnrrg@users.noreply.github.com>2018-07-23 21:38:29 -0400
committerLibravatar frsfnrrg <frsfnrrg@users.noreply.github.com>2018-07-23 21:38:29 -0400
commit94dd8823a0081f7983dce368d5d093d1d3eeaefe (patch)
treef2147f1ef4871edb4d989d26cd9b1104797d27bc /sway/input/cursor.c
parentParse mouse binding options (diff)
downloadsway-94dd8823a0081f7983dce368d5d093d1d3eeaefe.tar.gz
sway-94dd8823a0081f7983dce368d5d093d1d3eeaefe.tar.zst
sway-94dd8823a0081f7983dce368d5d093d1d3eeaefe.zip
Invoke mouse bindings
The mouse binding logic is inspired/copied from the keyboard binding logic; we store a sorted list of the currently pressed buttons, and trigger a binding when the currently pressed (or just recently pressed, in the case of a release binding) buttons, as well as modifiers/container region, match those of a given binding. As the code to execute a binding is not very keyboard specific, keyboard_execute_command is renamed to seat_execute_command and moved to where the other binding handling functions are. The call to transaction_commit_dirty has been lifted out.
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r--sway/input/cursor.c102
1 files changed, 102 insertions, 0 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,
469 seat_pointer_notify_button(seat, time_msec, button, state); 469 seat_pointer_notify_button(seat, time_msec, button, state);
470} 470}
471 471
472/**
473 * Remove a button (and duplicates) to the sorted list of currently pressed buttons
474 */
475static void state_erase_button(struct sway_cursor *cursor, uint32_t button) {
476 size_t j = 0;
477 for (size_t i = 0; i < cursor->pressed_button_count; ++i) {
478 if (i > j) {
479 cursor->pressed_buttons[j] = cursor->pressed_buttons[i];
480 }
481 if (cursor->pressed_buttons[i] != button) {
482 ++j;
483 }
484 }
485 while (cursor->pressed_button_count > j) {
486 --cursor->pressed_button_count;
487 cursor->pressed_buttons[cursor->pressed_button_count] = 0;
488 }
489}
490
491/**
492 * Add a button to the sorted list of currently pressed buttons, if there
493 * is space.
494 */
495static void state_add_button(struct sway_cursor *cursor, uint32_t button) {
496 if (cursor->pressed_button_count >= SWAY_CURSOR_PRESSED_BUTTONS_CAP) {
497 return;
498 }
499 size_t i = 0;
500 while (i < cursor->pressed_button_count && cursor->pressed_buttons[i] < button) {
501 ++i;
502 }
503 size_t j = cursor->pressed_button_count;
504 while (j > i) {
505 cursor->pressed_buttons[j] = cursor->pressed_buttons[j - 1];
506 --j;
507 }
508 cursor->pressed_buttons[i] = button;
509 cursor->pressed_button_count++;
510}
511
512/**
513 * Return the mouse binding which matches modifier, click location, release,
514 * and pressed button state, otherwise return null.
515 */
516static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *cursor,
517 list_t *bindings, uint32_t modifiers, bool release, bool on_titlebar,
518 bool on_border, bool on_content) {
519 uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) |
520 (on_border ? BINDING_BORDER : 0) |
521 (on_content ? BINDING_CONTENTS : 0);
522
523 for (int i = 0; i < bindings->length; ++i) {
524 struct sway_binding *binding = bindings->items[i];
525 if (modifiers ^ binding->modifiers ||
526 cursor->pressed_button_count != (size_t)binding->keys->length ||
527 release != (binding->flags & BINDING_RELEASE) ||
528 !(click_region & binding->flags)) {
529 continue;
530 }
531
532 bool match = true;
533 for (size_t j = 0; j < cursor->pressed_button_count; j++) {
534 uint32_t key = *(uint32_t *)binding->keys->items[j];
535 if (key != cursor->pressed_buttons[j]) {
536 match = false;
537 break;
538 }
539 }
540 if (!match) {
541 continue;
542 }
543
544 return binding;
545 }
546 return NULL;
547}
548
472void dispatch_cursor_button(struct sway_cursor *cursor, 549void dispatch_cursor_button(struct sway_cursor *cursor,
473 uint32_t time_msec, uint32_t button, enum wlr_button_state state) { 550 uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
474 if (cursor->seat->operation != OP_NONE && 551 if (cursor->seat->operation != OP_NONE &&
@@ -485,6 +562,31 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
485 double sx, sy; 562 double sx, sy;
486 struct sway_container *cont = container_at_coords(cursor->seat, 563 struct sway_container *cont = container_at_coords(cursor->seat,
487 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); 564 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
565
566 // Handle mouse bindings
567 bool on_border = find_resize_edge(cont, cursor) != WLR_EDGE_NONE;
568 bool on_contents = !on_border && surface;
569 bool on_titlebar = !on_border && !surface;
570 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);
571 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
572
573 struct sway_binding *binding = NULL;
574 if (state == WLR_BUTTON_PRESSED) {
575 state_add_button(cursor, button);
576 binding = get_active_mouse_binding(cursor,
577 config->current_mode->mouse_bindings, modifiers, false,
578 on_titlebar, on_border, on_contents);
579 } else {
580 binding = get_active_mouse_binding(cursor,
581 config->current_mode->mouse_bindings, modifiers, true,
582 on_titlebar, on_border, on_contents);
583 state_erase_button(cursor, button);
584 }
585 if (binding) {
586 seat_execute_command(cursor->seat, binding);
587 // TODO: do we want to pass on the event?
588 }
589
488 if (surface && wlr_surface_is_layer_surface(surface)) { 590 if (surface && wlr_surface_is_layer_surface(surface)) {
489 struct wlr_layer_surface *layer = 591 struct wlr_layer_surface *layer =
490 wlr_layer_surface_from_wlr_surface(surface); 592 wlr_layer_surface_from_wlr_surface(surface);