aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,