aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/cursor.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-10 16:51:24 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-12 10:45:54 +1000
commitf4280e506b9369d21769ee14bd2ab5e484fe4e76 (patch)
treef4c6951aca394d980b01e7d215eb8580d07c9492 /sway/input/cursor.c
parentImplement resizing tiled containers via cursor (diff)
downloadsway-f4280e506b9369d21769ee14bd2ab5e484fe4e76.tar.gz
sway-f4280e506b9369d21769ee14bd2ab5e484fe4e76.tar.zst
sway-f4280e506b9369d21769ee14bd2ab5e484fe4e76.zip
Refactor dispatch_cursor_button
There was a separate function dispatch_cursor_button_floating which dealt with the resize and move operations, but as resize is not really limited to floating views, it doesn't make as much sense to have this separate. So both functions are now combined into one. Additionally, dispatch_cursor_button now uses a pattern of returning early instead of using else-ifs.
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r--sway/input/cursor.c190
1 files changed, 94 insertions, 96 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 4b689535..d4dc617a 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -175,7 +175,7 @@ static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) {
175 return true; 175 return true;
176} 176}
177 177
178static enum wlr_edges find_resize_edge(struct sway_container *cont, 178static enum wlr_edges find_edge(struct sway_container *cont,
179 struct sway_cursor *cursor) { 179 struct sway_cursor *cursor) {
180 if (cont->type != C_VIEW) { 180 if (cont->type != C_VIEW) {
181 return WLR_EDGE_NONE; 181 return WLR_EDGE_NONE;
@@ -199,10 +199,19 @@ static enum wlr_edges find_resize_edge(struct sway_container *cont,
199 edge |= WLR_EDGE_BOTTOM; 199 edge |= WLR_EDGE_BOTTOM;
200 } 200 }
201 201
202 return edge;
203}
204
205/**
206 * If the cursor is over a _resizable_ edge, return the edge.
207 * Edges that can't be resized are edges of the workspace.
208 */
209static enum wlr_edges find_resize_edge(struct sway_container *cont,
210 struct sway_cursor *cursor) {
211 enum wlr_edges edge = find_edge(cont, cursor);
202 if (edge && !container_is_floating(cont) && edge_is_external(cont, edge)) { 212 if (edge && !container_is_floating(cont) && edge_is_external(cont, edge)) {
203 return WLR_EDGE_NONE; 213 return WLR_EDGE_NONE;
204 } 214 }
205
206 return edge; 215 return edge;
207} 216}
208 217
@@ -500,57 +509,6 @@ static void handle_cursor_motion_absolute(
500 transaction_commit_dirty(); 509 transaction_commit_dirty();
501} 510}
502 511
503static void dispatch_cursor_button_floating(struct sway_cursor *cursor,
504 uint32_t time_msec, uint32_t button, enum wlr_button_state state,
505 struct wlr_surface *surface, double sx, double sy,
506 struct sway_container *cont) {
507 struct sway_seat *seat = cursor->seat;
508
509 seat_set_focus(seat, cont);
510
511 // Deny moving or resizing a fullscreen container
512 if (container_is_fullscreen_or_child(cont)) {
513 seat_pointer_notify_button(seat, time_msec, button, state);
514 return;
515 }
516 struct sway_container *floater = cont;
517 while (floater->parent->layout != L_FLOATING) {
518 floater = floater->parent;
519 }
520
521 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
522 bool mod_pressed = keyboard &&
523 (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod);
524 enum wlr_edges edge = find_resize_edge(floater, cursor);
525 bool over_title = edge == WLR_EDGE_NONE && !surface;
526
527 // Check for beginning move
528 uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
529 if (button == btn_move && state == WLR_BUTTON_PRESSED &&
530 (mod_pressed || over_title)) {
531 seat_begin_move(seat, floater, button);
532 return;
533 }
534
535 // Check for beginning resize
536 bool resizing_via_border = button == BTN_LEFT && edge != WLR_EDGE_NONE;
537 uint32_t btn_resize = config->floating_mod_inverse ? BTN_LEFT : BTN_RIGHT;
538 bool resizing_via_mod = button == btn_resize && mod_pressed;
539 if ((resizing_via_border || resizing_via_mod) &&
540 state == WLR_BUTTON_PRESSED) {
541 if (edge == WLR_EDGE_NONE) {
542 edge |= cursor->cursor->x > floater->x + floater->width / 2 ?
543 WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
544 edge |= cursor->cursor->y > floater->y + floater->height / 2 ?
545 WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
546 }
547 seat_begin_resize_floating(seat, floater, button, edge);
548 return;
549 }
550
551 seat_pointer_notify_button(seat, time_msec, button, state);
552}
553
554/** 512/**
555 * Remove a button (and duplicates) to the sorted list of currently pressed buttons 513 * Remove a button (and duplicates) to the sorted list of currently pressed buttons
556 */ 514 */
@@ -630,26 +588,36 @@ static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *c
630 588
631void dispatch_cursor_button(struct sway_cursor *cursor, 589void dispatch_cursor_button(struct sway_cursor *cursor,
632 uint32_t time_msec, uint32_t button, enum wlr_button_state state) { 590 uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
591 if (time_msec == 0) {
592 time_msec = get_current_time_msec();
593 }
594 struct sway_seat *seat = cursor->seat;
595
596 // Handle ending seat operation
633 if (cursor->seat->operation != OP_NONE && 597 if (cursor->seat->operation != OP_NONE &&
634 button == cursor->seat->op_button && state == WLR_BUTTON_RELEASED) { 598 button == cursor->seat->op_button && state == WLR_BUTTON_RELEASED) {
635 seat_end_mouse_operation(cursor->seat); 599 seat_end_mouse_operation(seat);
636 seat_pointer_notify_button(cursor->seat, time_msec, button, state); 600 seat_pointer_notify_button(seat, time_msec, button, state);
637 return; 601 return;
638 } 602 }
639 if (time_msec == 0) {
640 time_msec = get_current_time_msec();
641 }
642 603
604 // Determine what's under the cursor
643 struct wlr_surface *surface = NULL; 605 struct wlr_surface *surface = NULL;
644 double sx, sy; 606 double sx, sy;
645 struct sway_container *cont = container_at_coords(cursor->seat, 607 struct sway_container *cont = container_at_coords(seat,
646 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); 608 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
609 bool is_floating = cont && container_is_floating(cont);
610 bool is_floating_or_child = cont && container_is_floating_or_child(cont);
611 bool is_fullscreen_or_child = cont && container_is_fullscreen_or_child(cont);
612 enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE;
613 enum wlr_edges resize_edge = edge ?
614 find_resize_edge(cont, cursor) : WLR_EDGE_NONE;
615 bool on_border = edge != WLR_EDGE_NONE;
616 bool on_contents = cont && !on_border && surface;
617 bool on_titlebar = cont && !on_border && !surface;
647 618
648 // Handle mouse bindings 619 // Handle mouse bindings
649 bool on_border = cont && (find_resize_edge(cont, cursor) != WLR_EDGE_NONE); 620 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
650 bool on_contents = !on_border && surface;
651 bool on_titlebar = !on_border && !surface;
652 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);
653 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; 621 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
654 622
655 struct sway_binding *binding = NULL; 623 struct sway_binding *binding = NULL;
@@ -665,51 +633,78 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
665 state_erase_button(cursor, button); 633 state_erase_button(cursor, button);
666 } 634 }
667 if (binding) { 635 if (binding) {
668 seat_execute_command(cursor->seat, binding); 636 seat_execute_command(seat, binding);
669 // TODO: do we want to pass on the event? 637 return;
670 } 638 }
671 639
672 enum wlr_edges edge = cont ? find_resize_edge(cont, cursor) : WLR_EDGE_NONE; 640 // Handle clicking a layer surface
673
674 if (surface && wlr_surface_is_layer_surface(surface)) { 641 if (surface && wlr_surface_is_layer_surface(surface)) {
675 struct wlr_layer_surface *layer = 642 struct wlr_layer_surface *layer =
676 wlr_layer_surface_from_wlr_surface(surface); 643 wlr_layer_surface_from_wlr_surface(surface);
677 if (layer->current.keyboard_interactive) { 644 if (layer->current.keyboard_interactive) {
678 seat_set_focus_layer(cursor->seat, layer); 645 seat_set_focus_layer(seat, layer);
646 }
647 seat_pointer_notify_button(seat, time_msec, button, state);
648 return;
649 }
650
651 // Handle tiling resize via border
652 if (resize_edge && button == BTN_LEFT && !is_floating) {
653 seat_set_focus(seat, cont);
654 seat_begin_resize_tiling(seat, cont, button, edge);
655 return;
656 }
657
658 // Handle beginning floating move
659 bool mod_pressed = keyboard &&
660 (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod);
661
662 if (is_floating_or_child && !is_fullscreen_or_child) {
663 uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
664 if (button == btn_move && state == WLR_BUTTON_PRESSED &&
665 (mod_pressed || on_titlebar)) {
666 while (cont->parent->layout != L_FLOATING) {
667 cont = cont->parent;
668 }
669 seat_begin_move(seat, cont, button);
670 return;
679 } 671 }
680 seat_pointer_notify_button(cursor->seat, time_msec, button, state); 672 }
681 } else if (edge && button == BTN_LEFT && 673
682 !container_is_floating(cont)) { 674 // Handle beginning floating resize
683 seat_set_focus(cursor->seat, cont); 675 if (is_floating_or_child && !is_fullscreen_or_child &&
684 seat_begin_resize_tiling(cursor->seat, cont, BTN_LEFT, edge); 676 state == WLR_BUTTON_PRESSED) {
685 } else if (cont && container_is_floating_or_child(cont)) { 677 // Via border
686 dispatch_cursor_button_floating(cursor, time_msec, button, state, 678 if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) {
687 surface, sx, sy, cont); 679 seat_begin_resize_floating(seat, cont, button, resize_edge);
688 } else if (surface && cont && cont->type != C_VIEW) { 680 return;
689 // Avoid moving keyboard focus from a surface that accepts it to one
690 // that does not unless the change would move us to a new workspace.
691 //
692 // This prevents, for example, losing focus when clicking on swaybar.
693 struct sway_container *new_ws = cont;
694 if (new_ws && new_ws->type != C_WORKSPACE) {
695 new_ws = container_parent(new_ws, C_WORKSPACE);
696 } 681 }
697 struct sway_container *old_ws = seat_get_focus(cursor->seat); 682
698 if (old_ws && old_ws->type != C_WORKSPACE) { 683 // Via mod+click
699 old_ws = container_parent(old_ws, C_WORKSPACE); 684 struct sway_container *floater = cont;
685 while (floater->parent->layout != L_FLOATING) {
686 floater = floater->parent;
700 } 687 }
701 if (new_ws != old_ws) { 688 uint32_t btn_resize = config->floating_mod_inverse ?
702 seat_set_focus(cursor->seat, cont); 689 BTN_LEFT : BTN_RIGHT;
690 if (button == btn_resize) {
691 edge |= cursor->cursor->x > floater->x + floater->width / 2 ?
692 WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
693 edge |= cursor->cursor->y > floater->y + floater->height / 2 ?
694 WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
695 seat_begin_resize_floating(seat, floater, button, edge);
696 return;
703 } 697 }
704 seat_pointer_notify_button(cursor->seat, time_msec, button, state);
705 } else if (cont) {
706 seat_set_focus(cursor->seat, cont);
707 seat_pointer_notify_button(cursor->seat, time_msec, button, state);
708 } else {
709 seat_pointer_notify_button(cursor->seat, time_msec, button, state);
710 } 698 }
711 699
712 transaction_commit_dirty(); 700 // Handle clicking a container surface
701 if (cont) {
702 seat_set_focus(seat, cont);
703 seat_pointer_notify_button(seat, time_msec, button, state);
704 return;
705 }
706
707 seat_pointer_notify_button(seat, time_msec, button, state);
713} 708}
714 709
715static void handle_cursor_button(struct wl_listener *listener, void *data) { 710static void handle_cursor_button(struct wl_listener *listener, void *data) {
@@ -718,6 +713,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
718 struct wlr_event_pointer_button *event = data; 713 struct wlr_event_pointer_button *event = data;
719 dispatch_cursor_button(cursor, 714 dispatch_cursor_button(cursor,
720 event->time_msec, event->button, event->state); 715 event->time_msec, event->button, event->state);
716 transaction_commit_dirty();
721} 717}
722 718
723static void handle_cursor_axis(struct wl_listener *listener, void *data) { 719static void handle_cursor_axis(struct wl_listener *listener, void *data) {
@@ -865,6 +861,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
865 dispatch_cursor_button(cursor, event->time_msec, 861 dispatch_cursor_button(cursor, event->time_msec,
866 BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ? 862 BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ?
867 WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED); 863 WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED);
864 transaction_commit_dirty();
868} 865}
869 866
870static void handle_tool_button(struct wl_listener *listener, void *data) { 867static void handle_tool_button(struct wl_listener *listener, void *data) {
@@ -889,6 +886,7 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
889 cursor->tool_buttons--; 886 cursor->tool_buttons--;
890 break; 887 break;
891 } 888 }
889 transaction_commit_dirty();
892} 890}
893 891
894static void handle_request_set_cursor(struct wl_listener *listener, 892static void handle_request_set_cursor(struct wl_listener *listener,