diff options
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 159 |
1 files changed, 101 insertions, 58 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index 57cc65f6..4077a8dd 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -124,42 +124,6 @@ static void seat_send_focus(struct sway_container *con, | |||
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | static struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, | ||
128 | struct sway_container *container, enum sway_container_type type, | ||
129 | bool only_tiling) { | ||
130 | if (container->type == C_VIEW) { | ||
131 | return container; | ||
132 | } | ||
133 | |||
134 | struct sway_container *floating = | ||
135 | container->type == C_WORKSPACE && !only_tiling ? | ||
136 | container->sway_workspace->floating : NULL; | ||
137 | if (container->children->length == 0 && | ||
138 | (!floating || floating->children->length == 0)) { | ||
139 | return container; | ||
140 | } | ||
141 | |||
142 | struct sway_seat_container *current = NULL; | ||
143 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
144 | if (current->container->type != type && type != C_TYPES) { | ||
145 | continue; | ||
146 | } | ||
147 | |||
148 | if (container_has_ancestor(current->container, container)) { | ||
149 | if (only_tiling && | ||
150 | container_is_floating_or_child(current->container)) { | ||
151 | continue; | ||
152 | } | ||
153 | return current->container; | ||
154 | } | ||
155 | if (floating && container_has_ancestor(current->container, floating)) { | ||
156 | return current->container; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | return NULL; | ||
161 | } | ||
162 | |||
163 | void seat_focus_inactive_children_for_each(struct sway_seat *seat, | 127 | void seat_focus_inactive_children_for_each(struct sway_seat *seat, |
164 | struct sway_container *container, | 128 | struct sway_container *container, |
165 | void (*f)(struct sway_container *container, void *data), void *data) { | 129 | void (*f)(struct sway_container *container, void *data), void *data) { |
@@ -175,8 +139,18 @@ void seat_focus_inactive_children_for_each(struct sway_seat *seat, | |||
175 | } | 139 | } |
176 | 140 | ||
177 | struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, | 141 | struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, |
178 | struct sway_container *container) { | 142 | struct sway_container *ancestor) { |
179 | return seat_get_focus_by_type(seat, container, C_VIEW, false); | 143 | if (ancestor->type == C_VIEW) { |
144 | return ancestor; | ||
145 | } | ||
146 | struct sway_seat_container *current; | ||
147 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
148 | struct sway_container *con = current->container; | ||
149 | if (con->type == C_VIEW && container_has_ancestor(con, ancestor)) { | ||
150 | return con; | ||
151 | } | ||
152 | } | ||
153 | return NULL; | ||
180 | } | 154 | } |
181 | 155 | ||
182 | static void handle_seat_container_destroy(struct wl_listener *listener, | 156 | static void handle_seat_container_destroy(struct wl_listener *listener, |
@@ -198,7 +172,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener, | |||
198 | if (set_focus) { | 172 | if (set_focus) { |
199 | struct sway_container *next_focus = NULL; | 173 | struct sway_container *next_focus = NULL; |
200 | while (next_focus == NULL) { | 174 | while (next_focus == NULL) { |
201 | next_focus = seat_get_focus_by_type(seat, parent, C_VIEW, false); | 175 | next_focus = seat_get_focus_inactive_view(seat, parent); |
202 | 176 | ||
203 | if (next_focus == NULL && parent->type == C_WORKSPACE) { | 177 | if (next_focus == NULL && parent->type == C_WORKSPACE) { |
204 | next_focus = parent; | 178 | next_focus = parent; |
@@ -339,9 +313,6 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) { | |||
339 | 313 | ||
340 | static void collect_focus_iter(struct sway_container *con, void *data) { | 314 | static void collect_focus_iter(struct sway_container *con, void *data) { |
341 | struct sway_seat *seat = data; | 315 | struct sway_seat *seat = data; |
342 | if (con->type > C_WORKSPACE) { | ||
343 | return; | ||
344 | } | ||
345 | struct sway_seat_container *seat_con = | 316 | struct sway_seat_container *seat_con = |
346 | seat_container_from_container(seat, con); | 317 | seat_container_from_container(seat, con); |
347 | if (!seat_con) { | 318 | if (!seat_con) { |
@@ -375,7 +346,8 @@ struct sway_seat *seat_create(struct sway_input_manager *input, | |||
375 | // init the focus stack | 346 | // init the focus stack |
376 | wl_list_init(&seat->focus_stack); | 347 | wl_list_init(&seat->focus_stack); |
377 | 348 | ||
378 | container_for_each_descendant(&root_container, collect_focus_iter, seat); | 349 | root_for_each_workspace(collect_focus_iter, seat); |
350 | root_for_each_container(collect_focus_iter, seat); | ||
379 | 351 | ||
380 | wl_signal_add(&root_container.sway_root->events.new_container, | 352 | wl_signal_add(&root_container.sway_root->events.new_container, |
381 | &seat->new_container); | 353 | &seat->new_container); |
@@ -653,8 +625,7 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
653 | // find new output's old workspace, which might have to be removed if empty | 625 | // find new output's old workspace, which might have to be removed if empty |
654 | struct sway_container *new_output_last_ws = NULL; | 626 | struct sway_container *new_output_last_ws = NULL; |
655 | if (last_output && new_output && last_output != new_output) { | 627 | if (last_output && new_output && last_output != new_output) { |
656 | new_output_last_ws = | 628 | new_output_last_ws = seat_get_active_child(seat, new_output); |
657 | seat_get_focus_by_type(seat, new_output, C_WORKSPACE, false); | ||
658 | } | 629 | } |
659 | 630 | ||
660 | if (container && container->parent) { | 631 | if (container && container->parent) { |
@@ -717,7 +688,8 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
717 | // If we've focused a floating container, bring it to the front. | 688 | // If we've focused a floating container, bring it to the front. |
718 | // We do this by putting it at the end of the floating list. | 689 | // We do this by putting it at the end of the floating list. |
719 | if (container && container_is_floating(container)) { | 690 | if (container && container_is_floating(container)) { |
720 | list_move_to_end(container->parent->children, container); | 691 | list_move_to_end( |
692 | container->parent->sway_workspace->floating, container); | ||
721 | } | 693 | } |
722 | 694 | ||
723 | // clean up unfocused empty workspace on new output | 695 | // clean up unfocused empty workspace on new output |
@@ -877,22 +849,66 @@ void seat_set_exclusive_client(struct sway_seat *seat, | |||
877 | } | 849 | } |
878 | 850 | ||
879 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, | 851 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, |
880 | struct sway_container *container) { | 852 | struct sway_container *con) { |
881 | return seat_get_focus_by_type(seat, container, C_TYPES, false); | 853 | if (con->type == C_WORKSPACE && !con->children->length && |
854 | !con->sway_workspace->floating->length) { | ||
855 | return con; | ||
856 | } | ||
857 | if (con->type == C_VIEW) { | ||
858 | return con; | ||
859 | } | ||
860 | struct sway_seat_container *current; | ||
861 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
862 | if (container_has_ancestor(current->container, con)) { | ||
863 | return current->container; | ||
864 | } | ||
865 | } | ||
866 | return NULL; | ||
882 | } | 867 | } |
883 | 868 | ||
884 | struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat, | 869 | struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat, |
885 | struct sway_container *container) { | 870 | struct sway_container *ancestor) { |
886 | return seat_get_focus_by_type(seat, container, C_TYPES, true); | 871 | if (ancestor->type == C_WORKSPACE && !ancestor->children->length) { |
872 | return ancestor; | ||
873 | } | ||
874 | struct sway_seat_container *current; | ||
875 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
876 | struct sway_container *con = current->container; | ||
877 | if (!container_is_floating_or_child(con) && | ||
878 | container_has_ancestor(current->container, ancestor)) { | ||
879 | return con; | ||
880 | } | ||
881 | } | ||
882 | return NULL; | ||
883 | } | ||
884 | |||
885 | struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat, | ||
886 | struct sway_container *ancestor) { | ||
887 | if (ancestor->type == C_WORKSPACE && | ||
888 | !ancestor->sway_workspace->floating->length) { | ||
889 | return NULL; | ||
890 | } | ||
891 | struct sway_seat_container *current; | ||
892 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
893 | struct sway_container *con = current->container; | ||
894 | if (container_is_floating_or_child(con) && | ||
895 | container_has_ancestor(current->container, ancestor)) { | ||
896 | return con; | ||
897 | } | ||
898 | } | ||
899 | return NULL; | ||
887 | } | 900 | } |
888 | 901 | ||
889 | struct sway_container *seat_get_active_child(struct sway_seat *seat, | 902 | struct sway_container *seat_get_active_child(struct sway_seat *seat, |
890 | struct sway_container *container) { | 903 | struct sway_container *parent) { |
891 | struct sway_seat_container *current = NULL; | 904 | if (parent->type == C_VIEW) { |
905 | return parent; | ||
906 | } | ||
907 | struct sway_seat_container *current; | ||
892 | wl_list_for_each(current, &seat->focus_stack, link) { | 908 | wl_list_for_each(current, &seat->focus_stack, link) { |
893 | if (current->container->parent == container && | 909 | struct sway_container *con = current->container; |
894 | current->container->layout != L_FLOATING) { | 910 | if (con->parent == parent) { |
895 | return current->container; | 911 | return con; |
896 | } | 912 | } |
897 | } | 913 | } |
898 | return NULL; | 914 | return NULL; |
@@ -902,7 +918,9 @@ struct sway_container *seat_get_focus(struct sway_seat *seat) { | |||
902 | if (!seat->has_focus) { | 918 | if (!seat->has_focus) { |
903 | return NULL; | 919 | return NULL; |
904 | } | 920 | } |
905 | return seat_get_focus_inactive(seat, &root_container); | 921 | struct sway_seat_container *current = |
922 | wl_container_of(seat->focus_stack.next, current, link); | ||
923 | return current->container; | ||
906 | } | 924 | } |
907 | 925 | ||
908 | void seat_apply_config(struct sway_seat *seat, | 926 | void seat_apply_config(struct sway_seat *seat, |
@@ -930,6 +948,18 @@ struct seat_config *seat_get_config(struct sway_seat *seat) { | |||
930 | return NULL; | 948 | return NULL; |
931 | } | 949 | } |
932 | 950 | ||
951 | void seat_begin_down(struct sway_seat *seat, struct sway_container *con, | ||
952 | uint32_t button, double sx, double sy) { | ||
953 | seat->operation = OP_DOWN; | ||
954 | seat->op_container = con; | ||
955 | seat->op_button = button; | ||
956 | seat->op_ref_lx = seat->cursor->cursor->x; | ||
957 | seat->op_ref_ly = seat->cursor->cursor->y; | ||
958 | seat->op_ref_con_lx = sx; | ||
959 | seat->op_ref_con_ly = sy; | ||
960 | seat->op_moved = false; | ||
961 | } | ||
962 | |||
933 | void seat_begin_move(struct sway_seat *seat, struct sway_container *con, | 963 | void seat_begin_move(struct sway_seat *seat, struct sway_container *con, |
934 | uint32_t button) { | 964 | uint32_t button) { |
935 | if (!seat->cursor) { | 965 | if (!seat->cursor) { |
@@ -954,7 +984,7 @@ void seat_begin_resize_floating(struct sway_seat *seat, | |||
954 | seat->op_resize_preserve_ratio = keyboard && | 984 | seat->op_resize_preserve_ratio = keyboard && |
955 | (wlr_keyboard_get_modifiers(keyboard) & WLR_MODIFIER_SHIFT); | 985 | (wlr_keyboard_get_modifiers(keyboard) & WLR_MODIFIER_SHIFT); |
956 | seat->op_resize_edge = edge == WLR_EDGE_NONE ? | 986 | seat->op_resize_edge = edge == WLR_EDGE_NONE ? |
957 | RESIZE_EDGE_BOTTOM | RESIZE_EDGE_RIGHT : edge; | 987 | WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT : edge; |
958 | seat->op_button = button; | 988 | seat->op_button = button; |
959 | seat->op_ref_lx = seat->cursor->cursor->x; | 989 | seat->op_ref_lx = seat->cursor->cursor->x; |
960 | seat->op_ref_ly = seat->cursor->cursor->y; | 990 | seat->op_ref_ly = seat->cursor->cursor->y; |
@@ -983,6 +1013,7 @@ void seat_begin_resize_tiling(struct sway_seat *seat, | |||
983 | } | 1013 | } |
984 | 1014 | ||
985 | void seat_end_mouse_operation(struct sway_seat *seat) { | 1015 | void seat_end_mouse_operation(struct sway_seat *seat) { |
1016 | enum sway_seat_operation operation = seat->operation; | ||
986 | if (seat->operation == OP_MOVE) { | 1017 | if (seat->operation == OP_MOVE) { |
987 | // We "move" the container to its own location so it discovers its | 1018 | // We "move" the container to its own location so it discovers its |
988 | // output again. | 1019 | // output again. |
@@ -991,7 +1022,19 @@ void seat_end_mouse_operation(struct sway_seat *seat) { | |||
991 | } | 1022 | } |
992 | seat->operation = OP_NONE; | 1023 | seat->operation = OP_NONE; |
993 | seat->op_container = NULL; | 1024 | seat->op_container = NULL; |
994 | cursor_set_image(seat->cursor, "left_ptr", NULL); | 1025 | if (operation == OP_DOWN) { |
1026 | // Set the cursor's previous coords to the x/y at the start of the | ||
1027 | // operation, so the container change will be detected if using | ||
1028 | // focus_follows_mouse and the cursor moved off the original container | ||
1029 | // during the operation. | ||
1030 | seat->cursor->previous.x = seat->op_ref_lx; | ||
1031 | seat->cursor->previous.y = seat->op_ref_ly; | ||
1032 | if (seat->op_moved) { | ||
1033 | cursor_send_pointer_motion(seat->cursor, 0, true); | ||
1034 | } | ||
1035 | } else { | ||
1036 | cursor_set_image(seat->cursor, "left_ptr", NULL); | ||
1037 | } | ||
995 | } | 1038 | } |
996 | 1039 | ||
997 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, | 1040 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, |