diff options
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 159 |
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 | ||
603 | static int handle_urgent_timeout(void *data) { | ||
604 | struct sway_view *view = data; | ||
605 | view_set_urgent(view, false); | ||
606 | return 0; | ||
607 | } | ||
608 | |||
597 | void seat_set_focus_warp(struct sway_seat *seat, | 609 | void 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 | ||
728 | void seat_set_focus_surface(struct sway_seat *seat, | 768 | void 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 | ||
833 | struct 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 | |||
845 | struct sway_container *seat_get_focus(struct sway_seat *seat) { | 873 | struct 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 | |||
905 | void 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 | |||
917 | void 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 | |||
943 | void 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 | |||
963 | void 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 | } | ||