summaryrefslogtreecommitdiffstats
path: root/sway/input/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r--sway/input/cursor.c158
1 files changed, 75 insertions, 83 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 00240e84..15993265 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -20,6 +20,7 @@
20#include "sway/layers.h" 20#include "sway/layers.h"
21#include "sway/output.h" 21#include "sway/output.h"
22#include "sway/tree/arrange.h" 22#include "sway/tree/arrange.h"
23#include "sway/tree/container.h"
23#include "sway/tree/root.h" 24#include "sway/tree/root.h"
24#include "sway/tree/view.h" 25#include "sway/tree/view.h"
25#include "sway/tree/workspace.h" 26#include "sway/tree/workspace.h"
@@ -50,15 +51,15 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output,
50} 51}
51 52
52/** 53/**
53 * Returns the container at the cursor's position. If there is a surface at that 54 * Returns the node at the cursor's position. If there is a surface at that
54 * location, it is stored in **surface (it may not be a view). 55 * location, it is stored in **surface (it may not be a view).
55 */ 56 */
56static struct sway_container *container_at_coords( 57static struct sway_node *node_at_coords(
57 struct sway_seat *seat, double lx, double ly, 58 struct sway_seat *seat, double lx, double ly,
58 struct wlr_surface **surface, double *sx, double *sy) { 59 struct wlr_surface **surface, double *sx, double *sy) {
59 // check for unmanaged views first 60 // check for unmanaged views first
60#ifdef HAVE_XWAYLAND 61#ifdef HAVE_XWAYLAND
61 struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; 62 struct wl_list *unmanaged = &root->xwayland_unmanaged;
62 struct sway_xwayland_unmanaged *unmanaged_surface; 63 struct sway_xwayland_unmanaged *unmanaged_surface;
63 wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { 64 wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) {
64 struct wlr_xwayland_surface *xsurface = 65 struct wlr_xwayland_surface *xsurface =
@@ -75,67 +76,64 @@ static struct sway_container *container_at_coords(
75 } 76 }
76#endif 77#endif
77 // find the output the cursor is on 78 // find the output the cursor is on
78 struct wlr_output_layout *output_layout =
79 root_container.sway_root->output_layout;
80 struct wlr_output *wlr_output = wlr_output_layout_output_at( 79 struct wlr_output *wlr_output = wlr_output_layout_output_at(
81 output_layout, lx, ly); 80 root->output_layout, lx, ly);
82 if (wlr_output == NULL) { 81 if (wlr_output == NULL) {
83 return NULL; 82 return NULL;
84 } 83 }
85 struct sway_output *output = wlr_output->data; 84 struct sway_output *output = wlr_output->data;
86 double ox = lx, oy = ly; 85 double ox = lx, oy = ly;
87 wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); 86 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
88 87
89 // find the focused workspace on the output for this seat 88 // find the focused workspace on the output for this seat
90 struct sway_container *ws = seat_get_focus_inactive(seat, output->swayc); 89 struct sway_workspace *ws = output_get_active_workspace(output);
91 if (ws && ws->type != C_WORKSPACE) {
92 ws = container_parent(ws, C_WORKSPACE);
93 }
94 if (!ws) {
95 return output->swayc;
96 }
97 90
98 if ((*surface = layer_surface_at(output, 91 if ((*surface = layer_surface_at(output,
99 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], 92 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
100 ox, oy, sx, sy))) { 93 ox, oy, sx, sy))) {
101 return ws; 94 return &ws->node;
102 } 95 }
103 if (ws->sway_workspace->fullscreen) { 96 if (ws->fullscreen) {
104 return tiling_container_at(ws->sway_workspace->fullscreen, lx, ly, 97 struct sway_container *con =
105 surface, sx, sy); 98 tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy);
99 if (con) {
100 return &con->node;
101 }
102 return NULL;
106 } 103 }
107 if ((*surface = layer_surface_at(output, 104 if ((*surface = layer_surface_at(output,
108 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], 105 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
109 ox, oy, sx, sy))) { 106 ox, oy, sx, sy))) {
110 return ws; 107 return &ws->node;
111 } 108 }
112 109
113 struct sway_container *c; 110 struct sway_container *c;
114 if ((c = container_at(ws, lx, ly, surface, sx, sy))) { 111 if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
115 return c; 112 return &c->node;
116 } 113 }
117 114
118 if ((*surface = layer_surface_at(output, 115 if ((*surface = layer_surface_at(output,
119 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], 116 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
120 ox, oy, sx, sy))) { 117 ox, oy, sx, sy))) {
121 return ws; 118 return &ws->node;
122 } 119 }
123 if ((*surface = layer_surface_at(output, 120 if ((*surface = layer_surface_at(output,
124 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], 121 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
125 ox, oy, sx, sy))) { 122 ox, oy, sx, sy))) {
126 return ws; 123 return &ws->node;
127 } 124 }
128 125
129 c = seat_get_active_child(seat, output->swayc); 126 return &ws->node;
130 if (c) { 127}
131 return c;
132 }
133 if (!c && output->swayc->children->length) {
134 c = output->swayc->children->items[0];
135 return c;
136 }
137 128
138 return output->swayc; 129static struct sway_container *container_at_coords(struct sway_seat *seat,
130 double lx, double ly,
131 struct wlr_surface **surface, double *sx, double *sy) {
132 struct sway_node *node = node_at_coords(seat, lx, ly, surface, sx, sy);
133 if (node && node->type == N_CONTAINER) {
134 return node->sway_container;
135 }
136 return NULL;
139} 137}
140 138
141/** 139/**
@@ -160,13 +158,14 @@ static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) {
160 158
161 // Iterate the parents until we find one with the layout we want, 159 // Iterate the parents until we find one with the layout we want,
162 // then check if the child has siblings between it and the edge. 160 // then check if the child has siblings between it and the edge.
163 while (cont->type != C_OUTPUT) { 161 while (cont) {
164 if (cont->parent->layout == layout) { 162 if (container_parent_layout(cont) == layout) {
165 int index = list_find(cont->parent->children, cont); 163 list_t *siblings = container_get_siblings(cont);
164 int index = list_find(siblings, cont);
166 if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { 165 if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) {
167 return false; 166 return false;
168 } 167 }
169 if (index < cont->parent->children->length - 1 && 168 if (index < siblings->length - 1 &&
170 (edge == WLR_EDGE_RIGHT || edge == WLR_EDGE_BOTTOM)) { 169 (edge == WLR_EDGE_RIGHT || edge == WLR_EDGE_BOTTOM)) {
171 return false; 170 return false;
172 } 171 }
@@ -178,10 +177,10 @@ static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) {
178 177
179static enum wlr_edges find_edge(struct sway_container *cont, 178static enum wlr_edges find_edge(struct sway_container *cont,
180 struct sway_cursor *cursor) { 179 struct sway_cursor *cursor) {
181 if (cont->type != C_VIEW) { 180 if (!cont->view) {
182 return WLR_EDGE_NONE; 181 return WLR_EDGE_NONE;
183 } 182 }
184 struct sway_view *view = cont->sway_view; 183 struct sway_view *view = cont->view;
185 if (view->border == B_NONE || !view->border_thickness || view->using_csd) { 184 if (view->border == B_NONE || !view->border_thickness || view->using_csd) {
186 return WLR_EDGE_NONE; 185 return WLR_EDGE_NONE;
187 } 186 }
@@ -219,7 +218,7 @@ static enum wlr_edges find_resize_edge(struct sway_container *cont,
219static void handle_down_motion(struct sway_seat *seat, 218static void handle_down_motion(struct sway_seat *seat,
220 struct sway_cursor *cursor, uint32_t time_msec) { 219 struct sway_cursor *cursor, uint32_t time_msec) {
221 struct sway_container *con = seat->op_container; 220 struct sway_container *con = seat->op_container;
222 if (seat_is_input_allowed(seat, con->sway_view->surface)) { 221 if (seat_is_input_allowed(seat, con->view->surface)) {
223 double moved_x = cursor->cursor->x - seat->op_ref_lx; 222 double moved_x = cursor->cursor->x - seat->op_ref_lx;
224 double moved_y = cursor->cursor->y - seat->op_ref_ly; 223 double moved_y = cursor->cursor->y - seat->op_ref_ly;
225 double sx = seat->op_ref_con_lx + moved_x; 224 double sx = seat->op_ref_con_lx + moved_x;
@@ -260,8 +259,7 @@ static void calculate_floating_constraints(struct sway_container *con,
260 if (config->floating_maximum_width == -1) { // no maximum 259 if (config->floating_maximum_width == -1) { // no maximum
261 *max_width = INT_MAX; 260 *max_width = INT_MAX;
262 } else if (config->floating_maximum_width == 0) { // automatic 261 } else if (config->floating_maximum_width == 0) { // automatic
263 struct sway_container *ws = container_parent(con, C_WORKSPACE); 262 *max_width = con->workspace->width;
264 *max_width = ws->width;
265 } else { 263 } else {
266 *max_width = config->floating_maximum_width; 264 *max_width = config->floating_maximum_width;
267 } 265 }
@@ -269,8 +267,7 @@ static void calculate_floating_constraints(struct sway_container *con,
269 if (config->floating_maximum_height == -1) { // no maximum 267 if (config->floating_maximum_height == -1) { // no maximum
270 *max_height = INT_MAX; 268 *max_height = INT_MAX;
271 } else if (config->floating_maximum_height == 0) { // automatic 269 } else if (config->floating_maximum_height == 0) { // automatic
272 struct sway_container *ws = container_parent(con, C_WORKSPACE); 270 *max_height = con->workspace->height;
273 *max_height = ws->height;
274 } else { 271 } else {
275 *max_height = config->floating_maximum_height; 272 *max_height = config->floating_maximum_height;
276 } 273 }
@@ -314,9 +311,9 @@ static void handle_resize_floating_motion(struct sway_seat *seat,
314 height = fmax(min_height, fmin(height, max_height)); 311 height = fmax(min_height, fmin(height, max_height));
315 312
316 // Apply the view's min/max size 313 // Apply the view's min/max size
317 if (con->type == C_VIEW) { 314 if (con->view) {
318 double view_min_width, view_max_width, view_min_height, view_max_height; 315 double view_min_width, view_max_width, view_min_height, view_max_height;
319 view_get_constraints(con->sway_view, &view_min_width, &view_max_width, 316 view_get_constraints(con->view, &view_min_width, &view_max_width,
320 &view_min_height, &view_max_height); 317 &view_min_height, &view_max_height);
321 width = fmax(view_min_width, fmin(width, view_max_width)); 318 width = fmax(view_min_width, fmin(width, view_max_width));
322 height = fmax(view_min_height, fmin(height, view_max_height)); 319 height = fmax(view_min_height, fmin(height, view_max_height));
@@ -357,15 +354,15 @@ static void handle_resize_floating_motion(struct sway_seat *seat,
357 con->width += relative_grow_width; 354 con->width += relative_grow_width;
358 con->height += relative_grow_height; 355 con->height += relative_grow_height;
359 356
360 if (con->type == C_VIEW) { 357 if (con->view) {
361 struct sway_view *view = con->sway_view; 358 struct sway_view *view = con->view;
362 view->x += relative_grow_x; 359 view->x += relative_grow_x;
363 view->y += relative_grow_y; 360 view->y += relative_grow_y;
364 view->width += relative_grow_width; 361 view->width += relative_grow_width;
365 view->height += relative_grow_height; 362 view->height += relative_grow_height;
366 } 363 }
367 364
368 arrange_windows(con); 365 arrange_container(con);
369} 366}
370 367
371static void handle_resize_tiling_motion(struct sway_seat *seat, 368static void handle_resize_tiling_motion(struct sway_seat *seat,
@@ -435,44 +432,40 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
435 struct wlr_surface *surface = NULL; 432 struct wlr_surface *surface = NULL;
436 double sx, sy; 433 double sx, sy;
437 434
438 // Find the container beneath the pointer's previous position 435 // Find the node beneath the pointer's previous position
439 struct sway_container *prev_c = container_at_coords(seat, 436 struct sway_node *prev_node = node_at_coords(seat,
440 cursor->previous.x, cursor->previous.y, &surface, &sx, &sy); 437 cursor->previous.x, cursor->previous.y, &surface, &sx, &sy);
441 // Update the stored previous position 438 // Update the stored previous position
442 cursor->previous.x = cursor->cursor->x; 439 cursor->previous.x = cursor->cursor->x;
443 cursor->previous.y = cursor->cursor->y; 440 cursor->previous.y = cursor->cursor->y;
444 441
445 struct sway_container *c = container_at_coords(seat, 442 struct sway_node *node = node_at_coords(seat,
446 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); 443 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
447 if (c && config->focus_follows_mouse && allow_refocusing) { 444 if (node && config->focus_follows_mouse && allow_refocusing) {
448 struct sway_container *focus = seat_get_focus(seat); 445 struct sway_node *focus = seat_get_focus(seat);
449 if (focus && c->type == C_WORKSPACE) { 446 if (focus && node->type == N_WORKSPACE) {
450 // Only follow the mouse if it would move to a new output 447 // Only follow the mouse if it would move to a new output
451 // Otherwise we'll focus the workspace, which is probably wrong 448 // Otherwise we'll focus the workspace, which is probably wrong
452 if (focus->type != C_OUTPUT) { 449 struct sway_output *focused_output = node_get_output(focus);
453 focus = container_parent(focus, C_OUTPUT); 450 struct sway_output *output = node_get_output(node);
454 } 451 if (output != focused_output) {
455 struct sway_container *output = c; 452 seat_set_focus_warp(seat, node, false, true);
456 if (output->type != C_OUTPUT) {
457 output = container_parent(c, C_OUTPUT);
458 }
459 if (output != focus) {
460 seat_set_focus_warp(seat, c, false, true);
461 } 453 }
462 } else if (c->type == C_VIEW) { 454 } else if (node->type == N_CONTAINER && node->sway_container->view) {
463 // Focus c if the following are true: 455 // Focus node if the following are true:
464 // - cursor is over a new view, i.e. entered a new window; and 456 // - cursor is over a new view, i.e. entered a new window; and
465 // - the new view is visible, i.e. not hidden in a stack or tab; and 457 // - the new view is visible, i.e. not hidden in a stack or tab; and
466 // - the seat does not have a keyboard grab 458 // - the seat does not have a keyboard grab
467 if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && 459 if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) &&
468 c != prev_c && 460 node != prev_node &&
469 view_is_visible(c->sway_view)) { 461 view_is_visible(node->sway_container->view)) {
470 seat_set_focus_warp(seat, c, false, true); 462 seat_set_focus_warp(seat, node, false, true);
471 } else { 463 } else {
472 struct sway_container *next_focus = 464 struct sway_node *next_focus =
473 seat_get_focus_inactive(seat, &root_container); 465 seat_get_focus_inactive(seat, &root->node);
474 if (next_focus && next_focus->type == C_VIEW && 466 if (next_focus && next_focus->type == N_CONTAINER &&
475 view_is_visible(next_focus->sway_view)) { 467 node->sway_container->view &&
468 view_is_visible(next_focus->sway_container->view)) {
476 seat_set_focus_warp(seat, next_focus, false, true); 469 seat_set_focus_warp(seat, next_focus, false, true);
477 } 470 }
478 } 471 }
@@ -486,12 +479,12 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
486 if (client != cursor->image_client) { 479 if (client != cursor->image_client) {
487 cursor_set_image(cursor, "left_ptr", client); 480 cursor_set_image(cursor, "left_ptr", client);
488 } 481 }
489 } else if (c) { 482 } else if (node && node->type == N_CONTAINER) {
490 // Try a container's resize edge 483 // Try a node's resize edge
491 enum wlr_edges edge = find_resize_edge(c, cursor); 484 enum wlr_edges edge = find_resize_edge(node->sway_container, cursor);
492 if (edge == WLR_EDGE_NONE) { 485 if (edge == WLR_EDGE_NONE) {
493 cursor_set_image(cursor, "left_ptr", NULL); 486 cursor_set_image(cursor, "left_ptr", NULL);
494 } else if (container_is_floating(c)) { 487 } else if (container_is_floating(node->sway_container)) {
495 cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); 488 cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL);
496 } else { 489 } else {
497 if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) { 490 if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
@@ -684,7 +677,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
684 // Handle tiling resize via border 677 // Handle tiling resize via border
685 if (resize_edge && button == BTN_LEFT && state == WLR_BUTTON_PRESSED && 678 if (resize_edge && button == BTN_LEFT && state == WLR_BUTTON_PRESSED &&
686 !is_floating) { 679 !is_floating) {
687 seat_set_focus(seat, cont); 680 seat_set_focus(seat, &cont->node);
688 seat_begin_resize_tiling(seat, cont, button, edge); 681 seat_begin_resize_tiling(seat, cont, button, edge);
689 return; 682 return;
690 } 683 }
@@ -713,7 +706,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
713 image = "sw-resize"; 706 image = "sw-resize";
714 } 707 }
715 cursor_set_image(seat->cursor, image, NULL); 708 cursor_set_image(seat->cursor, image, NULL);
716 seat_set_focus(seat, cont); 709 seat_set_focus(seat, &cont->node);
717 seat_begin_resize_tiling(seat, cont, button, edge); 710 seat_begin_resize_tiling(seat, cont, button, edge);
718 return; 711 return;
719 } 712 }
@@ -725,7 +718,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
725 uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; 718 uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
726 if (button == btn_move && state == WLR_BUTTON_PRESSED && 719 if (button == btn_move && state == WLR_BUTTON_PRESSED &&
727 (mod_pressed || on_titlebar)) { 720 (mod_pressed || on_titlebar)) {
728 while (cont->parent->type != C_WORKSPACE) { 721 while (cont->parent) {
729 cont = cont->parent; 722 cont = cont->parent;
730 } 723 }
731 seat_begin_move(seat, cont, button); 724 seat_begin_move(seat, cont, button);
@@ -747,7 +740,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
747 BTN_LEFT : BTN_RIGHT; 740 BTN_LEFT : BTN_RIGHT;
748 if (mod_pressed && button == btn_resize) { 741 if (mod_pressed && button == btn_resize) {
749 struct sway_container *floater = cont; 742 struct sway_container *floater = cont;
750 while (floater->parent->type != C_WORKSPACE) { 743 while (floater->parent) {
751 floater = floater->parent; 744 floater = floater->parent;
752 } 745 }
753 edge = 0; 746 edge = 0;
@@ -762,7 +755,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
762 755
763 // Handle mousedown on a container surface 756 // Handle mousedown on a container surface
764 if (surface && cont && state == WLR_BUTTON_PRESSED) { 757 if (surface && cont && state == WLR_BUTTON_PRESSED) {
765 seat_set_focus(seat, cont); 758 seat_set_focus(seat, &cont->node);
766 seat_pointer_notify_button(seat, time_msec, button, state); 759 seat_pointer_notify_button(seat, time_msec, button, state);
767 seat_begin_down(seat, cont, button, sx, sy); 760 seat_begin_down(seat, cont, button, sx, sy);
768 return; 761 return;
@@ -770,7 +763,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
770 763
771 // Handle clicking a container surface 764 // Handle clicking a container surface
772 if (cont) { 765 if (cont) {
773 seat_set_focus(seat, cont); 766 seat_set_focus(seat, &cont->node);
774 seat_pointer_notify_button(seat, time_msec, button, state); 767 seat_pointer_notify_button(seat, time_msec, button, state);
775 return; 768 return;
776 } 769 }
@@ -1025,8 +1018,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
1025 cursor->previous.y = wlr_cursor->y; 1018 cursor->previous.y = wlr_cursor->y;
1026 1019
1027 cursor->seat = seat; 1020 cursor->seat = seat;
1028 wlr_cursor_attach_output_layout(wlr_cursor, 1021 wlr_cursor_attach_output_layout(wlr_cursor, root->output_layout);
1029 root_container.sway_root->output_layout);
1030 1022
1031 // input events 1023 // input events
1032 wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); 1024 wl_signal_add(&wlr_cursor->events.motion, &cursor->motion);