aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/seat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r--sway/input/seat.c159
1 files changed, 126 insertions, 33 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 2c2087da..fc9e54b6 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,6 +1,11 @@
1#define _XOPEN_SOURCE 700 1#define _XOPEN_SOURCE 700
2#define _POSIX_C_SOURCE 199309L 2#define _POSIX_C_SOURCE 199309L
3#include <assert.h> 3#include <assert.h>
4#ifdef __linux__
5#include <linux/input-event-codes.h>
6#elif __FreeBSD__
7#include <dev/evdev/input-event-codes.h>
8#endif
4#include <strings.h> 9#include <strings.h>
5#include <time.h> 10#include <time.h>
6#include <wlr/types/wlr_cursor.h> 11#include <wlr/types/wlr_cursor.h>
@@ -75,7 +80,7 @@ static void seat_send_activate(struct sway_container *con,
75 struct sway_seat *seat) { 80 struct sway_seat *seat) {
76 if (con->type == C_VIEW) { 81 if (con->type == C_VIEW) {
77 if (!seat_is_input_allowed(seat, con->sway_view->surface)) { 82 if (!seat_is_input_allowed(seat, con->sway_view->surface)) {
78 wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited"); 83 wlr_log(WLR_DEBUG, "Refusing to set focus, input is inhibited");
79 return; 84 return;
80 } 85 }
81 view_set_activated(con->sway_view, true); 86 view_set_activated(con->sway_view, true);
@@ -219,7 +224,7 @@ static struct sway_seat_container *seat_container_from_container(
219 224
220 seat_con = calloc(1, sizeof(struct sway_seat_container)); 225 seat_con = calloc(1, sizeof(struct sway_seat_container));
221 if (seat_con == NULL) { 226 if (seat_con == NULL) {
222 wlr_log(L_ERROR, "could not allocate seat container"); 227 wlr_log(WLR_ERROR, "could not allocate seat container");
223 return NULL; 228 return NULL;
224 } 229 }
225 230
@@ -301,7 +306,7 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) {
301 306
302 struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon)); 307 struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon));
303 if (icon == NULL) { 308 if (icon == NULL) {
304 wlr_log(L_ERROR, "Allocation failed"); 309 wlr_log(WLR_ERROR, "Allocation failed");
305 return; 310 return;
306 } 311 }
307 icon->seat = seat; 312 icon->seat = seat;
@@ -348,6 +353,7 @@ struct sway_seat *seat_create(struct sway_input_manager *input,
348 free(seat); 353 free(seat);
349 return NULL; 354 return NULL;
350 } 355 }
356 seat->wlr_seat->data = seat;
351 357
352 seat->cursor = sway_cursor_create(seat); 358 seat->cursor = sway_cursor_create(seat);
353 if (!seat->cursor) { 359 if (!seat->cursor) {
@@ -391,7 +397,7 @@ static void seat_apply_input_config(struct sway_seat *seat,
391 struct input_config *ic = input_device_get_config( 397 struct input_config *ic = input_device_get_config(
392 sway_device->input_device); 398 sway_device->input_device);
393 if (ic != NULL) { 399 if (ic != NULL) {
394 wlr_log(L_DEBUG, "Applying input config to %s", 400 wlr_log(WLR_DEBUG, "Applying input config to %s",
395 sway_device->input_device->identifier); 401 sway_device->input_device->identifier);
396 402
397 mapped_to_output = ic->mapped_to_output; 403 mapped_to_output = ic->mapped_to_output;
@@ -401,7 +407,7 @@ static void seat_apply_input_config(struct sway_seat *seat,
401 mapped_to_output = sway_device->input_device->wlr_device->output_name; 407 mapped_to_output = sway_device->input_device->wlr_device->output_name;
402 } 408 }
403 if (mapped_to_output != NULL) { 409 if (mapped_to_output != NULL) {
404 wlr_log(L_DEBUG, "Mapping input device %s to output %s", 410 wlr_log(WLR_DEBUG, "Mapping input device %s to output %s",
405 sway_device->input_device->identifier, mapped_to_output); 411 sway_device->input_device->identifier, mapped_to_output);
406 struct sway_container *output = NULL; 412 struct sway_container *output = NULL;
407 for (int i = 0; i < root_container.children->length; ++i) { 413 for (int i = 0; i < root_container.children->length; ++i) {
@@ -415,7 +421,7 @@ static void seat_apply_input_config(struct sway_seat *seat,
415 wlr_cursor_map_input_to_output(seat->cursor->cursor, 421 wlr_cursor_map_input_to_output(seat->cursor->cursor,
416 sway_device->input_device->wlr_device, 422 sway_device->input_device->wlr_device,
417 output->sway_output->wlr_output); 423 output->sway_output->wlr_output);
418 wlr_log(L_DEBUG, "Mapped to output %s", output->name); 424 wlr_log(WLR_DEBUG, "Mapped to output %s", output->name);
419 } 425 }
420 } 426 }
421} 427}
@@ -495,7 +501,7 @@ void seat_configure_device(struct sway_seat *seat,
495 seat_configure_tablet_tool(seat, seat_device); 501 seat_configure_tablet_tool(seat, seat_device);
496 break; 502 break;
497 case WLR_INPUT_DEVICE_TABLET_PAD: 503 case WLR_INPUT_DEVICE_TABLET_PAD:
498 wlr_log(L_DEBUG, "TODO: configure tablet pad"); 504 wlr_log(WLR_DEBUG, "TODO: configure tablet pad");
499 break; 505 break;
500 } 506 }
501} 507}
@@ -510,11 +516,11 @@ void seat_add_device(struct sway_seat *seat,
510 struct sway_seat_device *seat_device = 516 struct sway_seat_device *seat_device =
511 calloc(1, sizeof(struct sway_seat_device)); 517 calloc(1, sizeof(struct sway_seat_device));
512 if (!seat_device) { 518 if (!seat_device) {
513 wlr_log(L_DEBUG, "could not allocate seat device"); 519 wlr_log(WLR_DEBUG, "could not allocate seat device");
514 return; 520 return;
515 } 521 }
516 522
517 wlr_log(L_DEBUG, "adding device %s to seat %s", 523 wlr_log(WLR_DEBUG, "adding device %s to seat %s",
518 input_device->identifier, seat->wlr_seat->name); 524 input_device->identifier, seat->wlr_seat->name);
519 525
520 seat_device->sway_seat = seat; 526 seat_device->sway_seat = seat;
@@ -533,7 +539,7 @@ void seat_remove_device(struct sway_seat *seat,
533 return; 539 return;
534 } 540 }
535 541
536 wlr_log(L_DEBUG, "removing device %s from seat %s", 542 wlr_log(WLR_DEBUG, "removing device %s from seat %s",
537 input_device->identifier, seat->wlr_seat->name); 543 input_device->identifier, seat->wlr_seat->name);
538 544
539 seat_device_destroy(seat_device); 545 seat_device_destroy(seat_device);
@@ -594,6 +600,12 @@ static void seat_send_unfocus(struct sway_container *container,
594 } 600 }
595} 601}
596 602
603static int handle_urgent_timeout(void *data) {
604 struct sway_view *view = data;
605 view_set_urgent(view, false);
606 return 0;
607}
608
597void seat_set_focus_warp(struct sway_seat *seat, 609void seat_set_focus_warp(struct sway_seat *seat,
598 struct sway_container *container, bool warp) { 610 struct sway_container *container, bool warp) {
599 if (seat->focused_layer) { 611 if (seat->focused_layer) {
@@ -616,6 +628,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
616 628
617 if (last_workspace && last_workspace == new_workspace 629 if (last_workspace && last_workspace == new_workspace
618 && last_workspace->sway_workspace->fullscreen 630 && last_workspace->sway_workspace->fullscreen
631 && container && container->type == C_VIEW
619 && !container->sway_view->is_fullscreen) { 632 && !container->sway_view->is_fullscreen) {
620 return; 633 return;
621 } 634 }
@@ -649,6 +662,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
649 while (parent) { 662 while (parent) {
650 wl_list_remove(&parent->link); 663 wl_list_remove(&parent->link);
651 wl_list_insert(&seat->focus_stack, &parent->link); 664 wl_list_insert(&seat->focus_stack, &parent->link);
665 container_set_dirty(parent->container);
652 666
653 parent = 667 parent =
654 seat_container_from_container(seat, 668 seat_container_from_container(seat,
@@ -661,9 +675,39 @@ void seat_set_focus_warp(struct sway_seat *seat,
661 if (last_focus) { 675 if (last_focus) {
662 seat_send_unfocus(last_focus, seat); 676 seat_send_unfocus(last_focus, seat);
663 } 677 }
664
665 seat_send_focus(container, seat); 678 seat_send_focus(container, seat);
666 container_damage_whole(container); 679
680 container_set_dirty(container);
681 container_set_dirty(container->parent); // for focused_inactive_child
682 if (last_focus) {
683 container_set_dirty(last_focus);
684 }
685 }
686
687 // If urgent, either unset the urgency or start a timer to unset it
688 if (container && container->type == C_VIEW &&
689 view_is_urgent(container->sway_view) &&
690 !container->sway_view->urgent_timer) {
691 struct sway_view *view = container->sway_view;
692 if (last_workspace && last_workspace != new_workspace &&
693 config->urgent_timeout > 0) {
694 view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop,
695 handle_urgent_timeout, view);
696 wl_event_source_timer_update(view->urgent_timer,
697 config->urgent_timeout);
698 } else {
699 view_set_urgent(view, false);
700 }
701 }
702
703 // If we've focused a floating container, bring it to the front.
704 // We do this by putting it at the end of the floating list.
705 // This must happen for both the pending and current children lists.
706 if (container && container_is_floating(container)) {
707 list_move_to_end(container->parent->children, container);
708 if (container_has_ancestor(container, container->current.parent)) {
709 list_move_to_end(container->parent->current.children, container);
710 }
667 } 711 }
668 712
669 // clean up unfocused empty workspace on new output 713 // clean up unfocused empty workspace on new output
@@ -707,11 +751,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
707 } 751 }
708 } 752 }
709 753
710 if (last_focus) { 754 if (last_focus != NULL) {
711 container_damage_whole(last_focus);
712 }
713
714 if (last_workspace && last_workspace != new_workspace) {
715 cursor_send_pointer_motion(seat->cursor, 0, true); 755 cursor_send_pointer_motion(seat->cursor, 0, true);
716 } 756 }
717 757
@@ -726,11 +766,11 @@ void seat_set_focus(struct sway_seat *seat,
726} 766}
727 767
728void seat_set_focus_surface(struct sway_seat *seat, 768void seat_set_focus_surface(struct sway_seat *seat,
729 struct wlr_surface *surface) { 769 struct wlr_surface *surface, bool unfocus) {
730 if (seat->focused_layer != NULL) { 770 if (seat->focused_layer != NULL) {
731 return; 771 return;
732 } 772 }
733 if (seat->has_focus) { 773 if (seat->has_focus && unfocus) {
734 struct sway_container *focus = seat_get_focus(seat); 774 struct sway_container *focus = seat_get_focus(seat);
735 seat_send_unfocus(focus, seat); 775 seat_send_unfocus(focus, seat);
736 seat->has_focus = false; 776 seat->has_focus = false;
@@ -752,7 +792,7 @@ void seat_set_focus_layer(struct sway_seat *seat,
752 struct sway_container *previous = 792 struct sway_container *previous =
753 seat_get_focus_inactive(seat, &root_container); 793 seat_get_focus_inactive(seat, &root_container);
754 if (previous) { 794 if (previous) {
755 wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, 795 wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous,
756 container_type_to_str(previous->type), previous->name); 796 container_type_to_str(previous->type), previous->name);
757 // Hack to get seat to re-focus the return value of get_focus 797 // Hack to get seat to re-focus the return value of get_focus
758 seat_set_focus(seat, previous->parent); 798 seat_set_focus(seat, previous->parent);
@@ -762,7 +802,7 @@ void seat_set_focus_layer(struct sway_seat *seat,
762 } else if (!layer || seat->focused_layer == layer) { 802 } else if (!layer || seat->focused_layer == layer) {
763 return; 803 return;
764 } 804 }
765 seat_set_focus_surface(seat, layer->surface); 805 seat_set_focus_surface(seat, layer->surface, true);
766 if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { 806 if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
767 seat->focused_layer = layer; 807 seat->focused_layer = layer;
768 } 808 }
@@ -830,18 +870,6 @@ struct sway_container *seat_get_active_child(struct sway_seat *seat,
830 return NULL; 870 return NULL;
831} 871}
832 872
833struct sway_container *seat_get_active_current_child(struct sway_seat *seat,
834 struct sway_container *container) {
835 struct sway_container *child = seat_get_active_child(seat, container);
836 if (child) {
837 return child;
838 }
839 if (container->current.children->length == 1) {
840 return container->current.children->items[0];
841 }
842 return NULL;
843}
844
845struct sway_container *seat_get_focus(struct sway_seat *seat) { 873struct sway_container *seat_get_focus(struct sway_seat *seat) {
846 if (!seat->has_focus) { 874 if (!seat->has_focus) {
847 return NULL; 875 return NULL;
@@ -873,3 +901,68 @@ struct seat_config *seat_get_config(struct sway_seat *seat) {
873 901
874 return NULL; 902 return NULL;
875} 903}
904
905void seat_begin_move(struct sway_seat *seat, struct sway_container *con,
906 uint32_t button) {
907 if (!seat->cursor) {
908 wlr_log(WLR_DEBUG, "Ignoring move request due to no cursor device");
909 return;
910 }
911 seat->operation = OP_MOVE;
912 seat->op_container = con;
913 seat->op_button = button;
914 cursor_set_image(seat->cursor, "grab", NULL);
915}
916
917void seat_begin_resize(struct sway_seat *seat, struct sway_container *con,
918 uint32_t button, enum wlr_edges edge) {
919 if (!seat->cursor) {
920 wlr_log(WLR_DEBUG, "Ignoring resize request due to no cursor device");
921 return;
922 }
923 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
924 seat->operation = OP_RESIZE;
925 seat->op_container = con;
926 seat->op_resize_preserve_ratio = keyboard &&
927 (wlr_keyboard_get_modifiers(keyboard) & WLR_MODIFIER_SHIFT);
928 seat->op_resize_edge = edge == WLR_EDGE_NONE ?
929 RESIZE_EDGE_BOTTOM | RESIZE_EDGE_RIGHT : edge;
930 seat->op_button = button;
931 seat->op_ref_lx = seat->cursor->cursor->x;
932 seat->op_ref_ly = seat->cursor->cursor->y;
933 seat->op_ref_con_lx = con->x;
934 seat->op_ref_con_ly = con->y;
935 seat->op_ref_width = con->width;
936 seat->op_ref_height = con->height;
937
938 const char *image = edge == WLR_EDGE_NONE ?
939 "se-resize" : wlr_xcursor_get_resize_name(edge);
940 cursor_set_image(seat->cursor, image, NULL);
941}
942
943void seat_end_mouse_operation(struct sway_seat *seat) {
944 switch (seat->operation) {
945 case OP_MOVE:
946 {
947 // We "move" the container to its own location so it discovers its
948 // output again.
949 struct sway_container *con = seat->op_container;
950 container_floating_move_to(con, con->x, con->y);
951 }
952 case OP_RESIZE:
953 // Don't need to do anything here.
954 break;
955 case OP_NONE:
956 break;
957 }
958 seat->operation = OP_NONE;
959 seat->op_container = NULL;
960 cursor_set_image(seat->cursor, "left_ptr", NULL);
961}
962
963void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec,
964 uint32_t button, enum wlr_button_state state) {
965 seat->last_button = button;
966 seat->last_button_serial = wlr_seat_pointer_notify_button(seat->wlr_seat,
967 time_msec, button, state);
968}