aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r--sway/input/cursor.c632
1 files changed, 325 insertions, 307 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index fa604426..404c1eed 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -4,10 +4,10 @@
4#include <libevdev/libevdev.h> 4#include <libevdev/libevdev.h>
5#include <linux/input-event-codes.h> 5#include <linux/input-event-codes.h>
6#include <errno.h> 6#include <errno.h>
7#include <time.h>
7#include <strings.h> 8#include <strings.h>
8#include <wlr/types/wlr_box.h>
9#include <wlr/types/wlr_cursor.h> 9#include <wlr/types/wlr_cursor.h>
10#include <wlr/types/wlr_idle.h> 10#include <wlr/types/wlr_cursor_shape_v1.h>
11#include <wlr/types/wlr_pointer.h> 11#include <wlr/types/wlr_pointer.h>
12#include <wlr/types/wlr_touch.h> 12#include <wlr/types/wlr_touch.h>
13#include <wlr/types/wlr_tablet_v2.h> 13#include <wlr/types/wlr_tablet_v2.h>
@@ -19,56 +19,22 @@
19#include "log.h" 19#include "log.h"
20#include "util.h" 20#include "util.h"
21#include "sway/commands.h" 21#include "sway/commands.h"
22#include "sway/desktop.h"
23#include "sway/desktop/transaction.h"
24#include "sway/input/cursor.h" 22#include "sway/input/cursor.h"
25#include "sway/input/keyboard.h" 23#include "sway/input/keyboard.h"
26#include "sway/input/tablet.h" 24#include "sway/input/tablet.h"
27#include "sway/layers.h" 25#include "sway/layers.h"
28#include "sway/output.h" 26#include "sway/output.h"
27#include "sway/scene_descriptor.h"
29#include "sway/tree/container.h" 28#include "sway/tree/container.h"
30#include "sway/tree/root.h" 29#include "sway/tree/root.h"
31#include "sway/tree/view.h" 30#include "sway/tree/view.h"
32#include "sway/tree/workspace.h" 31#include "sway/tree/workspace.h"
33#include "wlr-layer-shell-unstable-v1-protocol.h" 32#include "wlr-layer-shell-unstable-v1-protocol.h"
34 33
35static struct wlr_surface *layer_surface_at(struct sway_output *output, 34static uint32_t get_current_time_msec(void) {
36 struct wl_list *layer, double ox, double oy, double *sx, double *sy) { 35 struct timespec now;
37 struct sway_layer_surface *sway_layer; 36 clock_gettime(CLOCK_MONOTONIC, &now);
38 wl_list_for_each_reverse(sway_layer, layer, link) { 37 return now.tv_sec * 1000 + now.tv_nsec / 1000000;
39 double _sx = ox - sway_layer->geo.x;
40 double _sy = oy - sway_layer->geo.y;
41 struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
42 sway_layer->layer_surface, _sx, _sy, sx, sy);
43 if (sub) {
44 return sub;
45 }
46 }
47 return NULL;
48}
49
50static bool surface_is_xdg_popup(struct wlr_surface *surface) {
51 if (wlr_surface_is_xdg_surface(surface)) {
52 struct wlr_xdg_surface *xdg_surface =
53 wlr_xdg_surface_from_wlr_surface(surface);
54 return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP;
55 }
56 return false;
57}
58
59static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
60 struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
61 struct sway_layer_surface *sway_layer;
62 wl_list_for_each_reverse(sway_layer, layer, link) {
63 double _sx = ox - sway_layer->geo.x;
64 double _sy = oy - sway_layer->geo.y;
65 struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
66 sway_layer->layer_surface, _sx, _sy, sx, sy);
67 if (sub && surface_is_xdg_popup(sub)) {
68 return sub;
69 }
70 }
71 return NULL;
72} 38}
73 39
74/** 40/**
@@ -78,116 +44,101 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
78struct sway_node *node_at_coords( 44struct sway_node *node_at_coords(
79 struct sway_seat *seat, double lx, double ly, 45 struct sway_seat *seat, double lx, double ly,
80 struct wlr_surface **surface, double *sx, double *sy) { 46 struct wlr_surface **surface, double *sx, double *sy) {
81 // check for unmanaged views first 47 struct wlr_scene_node *scene_node = NULL;
82#if HAVE_XWAYLAND 48
83 struct wl_list *unmanaged = &root->xwayland_unmanaged; 49 struct wlr_scene_node *node;
84 struct sway_xwayland_unmanaged *unmanaged_surface; 50 wl_list_for_each_reverse(node, &root->layer_tree->children, link) {
85 wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { 51 struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node);
86 struct wlr_xwayland_surface *xsurface = 52
87 unmanaged_surface->wlr_xwayland_surface; 53 bool non_interactive = scene_descriptor_try_get(&layer->node,
88 54 SWAY_SCENE_DESC_NON_INTERACTIVE);
89 double _sx = lx - unmanaged_surface->lx; 55 if (non_interactive) {
90 double _sy = ly - unmanaged_surface->ly; 56 continue;
91 if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { 57 }
92 *surface = xsurface->surface; 58
93 *sx = _sx; 59 scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy);
94 *sy = _sy; 60 if (scene_node) {
95 return NULL; 61 break;
96 } 62 }
97 } 63 }
64
65 if (scene_node) {
66 // determine what wlr_surface we clicked on
67 if (scene_node->type == WLR_SCENE_NODE_BUFFER) {
68 struct wlr_scene_buffer *scene_buffer =
69 wlr_scene_buffer_from_node(scene_node);
70 struct wlr_scene_surface *scene_surface =
71 wlr_scene_surface_try_from_buffer(scene_buffer);
72
73 if (scene_surface) {
74 *surface = scene_surface->surface;
75 }
76 }
77
78 // determine what container we clicked on
79 struct wlr_scene_node *current = scene_node;
80 while (true) {
81 struct sway_container *con = scene_descriptor_try_get(current,
82 SWAY_SCENE_DESC_CONTAINER);
83
84 if (!con) {
85 struct sway_view *view = scene_descriptor_try_get(current,
86 SWAY_SCENE_DESC_VIEW);
87 if (view) {
88 con = view->container;
89 }
90 }
91
92 if (!con) {
93 struct sway_xdg_popup *popup =
94 scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP);
95 if (popup) {
96 con = popup->view->container;
97 }
98 }
99
100 if (con && (!con->view || con->view->surface)) {
101 return &con->node;
102 }
103
104 if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) {
105 // We don't want to feed through the current workspace on
106 // layer shells
107 return NULL;
108 }
109
110#if HAVE_XWAYLAND
111 if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) {
112 return NULL;
113 }
98#endif 114#endif
99 // find the output the cursor is on 115
116 if (!current->parent) {
117 break;
118 }
119
120 current = &current->parent->node;
121 }
122 }
123
124 // if we aren't on a container, determine what workspace we are on
100 struct wlr_output *wlr_output = wlr_output_layout_output_at( 125 struct wlr_output *wlr_output = wlr_output_layout_output_at(
101 root->output_layout, lx, ly); 126 root->output_layout, lx, ly);
102 if (wlr_output == NULL) { 127 if (wlr_output == NULL) {
103 return NULL; 128 return NULL;
104 } 129 }
130
105 struct sway_output *output = wlr_output->data; 131 struct sway_output *output = wlr_output->data;
106 if (!output || !output->enabled) { 132 if (!output || !output->enabled) {
107 // output is being destroyed or is being enabled 133 // output is being destroyed or is being enabled
108 return NULL; 134 return NULL;
109 } 135 }
110 double ox = lx, oy = ly;
111 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
112 136
113 if (root->fullscreen_global) {
114 // Try fullscreen container
115 struct sway_container *con = tiling_container_at(
116 &root->fullscreen_global->node, lx, ly, surface, sx, sy);
117 if (con) {
118 return &con->node;
119 }
120 return NULL;
121 }
122
123 // find the focused workspace on the output for this seat
124 struct sway_workspace *ws = output_get_active_workspace(output); 137 struct sway_workspace *ws = output_get_active_workspace(output);
125 if (!ws) { 138 if (!ws) {
126 return NULL; 139 return NULL;
127 } 140 }
128 141
129 if ((*surface = layer_surface_at(output,
130 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
131 ox, oy, sx, sy))) {
132 return NULL;
133 }
134 if (ws->fullscreen) {
135 // Try transient containers
136 for (int i = 0; i < ws->floating->length; ++i) {
137 struct sway_container *floater = ws->floating->items[i];
138 if (container_is_transient_for(floater, ws->fullscreen)) {
139 struct sway_container *con = tiling_container_at(
140 &floater->node, lx, ly, surface, sx, sy);
141 if (con) {
142 return &con->node;
143 }
144 }
145 }
146 // Try fullscreen container
147 struct sway_container *con =
148 tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy);
149 if (con) {
150 return &con->node;
151 }
152 return NULL;
153 }
154 if ((*surface = layer_surface_popup_at(output,
155 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
156 ox, oy, sx, sy))) {
157 return NULL;
158 }
159 if ((*surface = layer_surface_popup_at(output,
160 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
161 ox, oy, sx, sy))) {
162 return NULL;
163 }
164 if ((*surface = layer_surface_popup_at(output,
165 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
166 ox, oy, sx, sy))) {
167 return NULL;
168 }
169 if ((*surface = layer_surface_at(output,
170 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
171 ox, oy, sx, sy))) {
172 return NULL;
173 }
174
175 struct sway_container *c;
176 if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
177 return &c->node;
178 }
179
180 if ((*surface = layer_surface_at(output,
181 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
182 ox, oy, sx, sy))) {
183 return NULL;
184 }
185 if ((*surface = layer_surface_at(output,
186 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
187 ox, oy, sx, sy))) {
188 return NULL;
189 }
190
191 return &ws->node; 142 return &ws->node;
192} 143}
193 144
@@ -213,7 +164,7 @@ void cursor_update_image(struct sway_cursor *cursor,
213 // Try a node's resize edge 164 // Try a node's resize edge
214 enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor); 165 enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor);
215 if (edge == WLR_EDGE_NONE) { 166 if (edge == WLR_EDGE_NONE) {
216 cursor_set_image(cursor, "left_ptr", NULL); 167 cursor_set_image(cursor, "default", NULL);
217 } else if (container_is_floating(node->sway_container)) { 168 } else if (container_is_floating(node->sway_container)) {
218 cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); 169 cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL);
219 } else { 170 } else {
@@ -224,12 +175,12 @@ void cursor_update_image(struct sway_cursor *cursor,
224 } 175 }
225 } 176 }
226 } else { 177 } else {
227 cursor_set_image(cursor, "left_ptr", NULL); 178 cursor_set_image(cursor, "default", NULL);
228 } 179 }
229} 180}
230 181
231static void cursor_hide(struct sway_cursor *cursor) { 182static void cursor_hide(struct sway_cursor *cursor) {
232 wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); 183 wlr_cursor_unset_image(cursor->cursor);
233 cursor->hidden = true; 184 cursor->hidden = true;
234 wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); 185 wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat);
235} 186}
@@ -341,7 +292,7 @@ void cursor_unhide(struct sway_cursor *cursor) {
341 wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); 292 wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor));
342} 293}
343 294
344static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, 295void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
345 struct wlr_input_device *device, double dx, double dy, 296 struct wlr_input_device *device, double dx, double dy,
346 double dx_unaccel, double dy_unaccel) { 297 double dx_unaccel, double dy_unaccel) {
347 wlr_relative_pointer_manager_v1_send_relative_motion( 298 wlr_relative_pointer_manager_v1_send_relative_motion(
@@ -378,30 +329,29 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
378static void handle_pointer_motion_relative( 329static void handle_pointer_motion_relative(
379 struct wl_listener *listener, void *data) { 330 struct wl_listener *listener, void *data) {
380 struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); 331 struct sway_cursor *cursor = wl_container_of(listener, cursor, motion);
381 struct wlr_event_pointer_motion *e = data; 332 struct wlr_pointer_motion_event *e = data;
382 cursor_handle_activity_from_device(cursor, e->device); 333 cursor_handle_activity_from_device(cursor, &e->pointer->base);
383 334
384 pointer_motion(cursor, e->time_msec, e->device, e->delta_x, e->delta_y, 335 pointer_motion(cursor, e->time_msec, &e->pointer->base, e->delta_x,
385 e->unaccel_dx, e->unaccel_dy); 336 e->delta_y, e->unaccel_dx, e->unaccel_dy);
386 transaction_commit_dirty();
387} 337}
388 338
389static void handle_pointer_motion_absolute( 339static void handle_pointer_motion_absolute(
390 struct wl_listener *listener, void *data) { 340 struct wl_listener *listener, void *data) {
391 struct sway_cursor *cursor = 341 struct sway_cursor *cursor =
392 wl_container_of(listener, cursor, motion_absolute); 342 wl_container_of(listener, cursor, motion_absolute);
393 struct wlr_event_pointer_motion_absolute *event = data; 343 struct wlr_pointer_motion_absolute_event *event = data;
394 cursor_handle_activity_from_device(cursor, event->device); 344 cursor_handle_activity_from_device(cursor, &event->pointer->base);
395 345
396 double lx, ly; 346 double lx, ly;
397 wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, 347 wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->pointer->base,
398 event->x, event->y, &lx, &ly); 348 event->x, event->y, &lx, &ly);
399 349
400 double dx = lx - cursor->cursor->x; 350 double dx = lx - cursor->cursor->x;
401 double dy = ly - cursor->cursor->y; 351 double dy = ly - cursor->cursor->y;
402 352
403 pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); 353 pointer_motion(cursor, event->time_msec, &event->pointer->base, dx, dy,
404 transaction_commit_dirty(); 354 dx, dy);
405} 355}
406 356
407void dispatch_cursor_button(struct sway_cursor *cursor, 357void dispatch_cursor_button(struct sway_cursor *cursor,
@@ -416,7 +366,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
416 366
417static void handle_pointer_button(struct wl_listener *listener, void *data) { 367static void handle_pointer_button(struct wl_listener *listener, void *data) {
418 struct sway_cursor *cursor = wl_container_of(listener, cursor, button); 368 struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
419 struct wlr_event_pointer_button *event = data; 369 struct wlr_pointer_button_event *event = data;
420 370
421 if (event->state == WLR_BUTTON_PRESSED) { 371 if (event->state == WLR_BUTTON_PRESSED) {
422 cursor->pressed_button_count++; 372 cursor->pressed_button_count++;
@@ -428,23 +378,21 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) {
428 } 378 }
429 } 379 }
430 380
431 cursor_handle_activity_from_device(cursor, event->device); 381 cursor_handle_activity_from_device(cursor, &event->pointer->base);
432 dispatch_cursor_button(cursor, event->device, 382 dispatch_cursor_button(cursor, &event->pointer->base,
433 event->time_msec, event->button, event->state); 383 event->time_msec, event->button, event->state);
434 transaction_commit_dirty();
435} 384}
436 385
437void dispatch_cursor_axis(struct sway_cursor *cursor, 386void dispatch_cursor_axis(struct sway_cursor *cursor,
438 struct wlr_event_pointer_axis *event) { 387 struct wlr_pointer_axis_event *event) {
439 seatop_pointer_axis(cursor->seat, event); 388 seatop_pointer_axis(cursor->seat, event);
440} 389}
441 390
442static void handle_pointer_axis(struct wl_listener *listener, void *data) { 391static void handle_pointer_axis(struct wl_listener *listener, void *data) {
443 struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); 392 struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
444 struct wlr_event_pointer_axis *event = data; 393 struct wlr_pointer_axis_event *event = data;
445 cursor_handle_activity_from_device(cursor, event->device); 394 cursor_handle_activity_from_device(cursor, &event->pointer->base);
446 dispatch_cursor_axis(cursor, event); 395 dispatch_cursor_axis(cursor, event);
447 transaction_commit_dirty();
448} 396}
449 397
450static void handle_pointer_frame(struct wl_listener *listener, void *data) { 398static void handle_pointer_frame(struct wl_listener *listener, void *data) {
@@ -454,97 +402,76 @@ static void handle_pointer_frame(struct wl_listener *listener, void *data) {
454 402
455static void handle_touch_down(struct wl_listener *listener, void *data) { 403static void handle_touch_down(struct wl_listener *listener, void *data) {
456 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); 404 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down);
457 struct wlr_event_touch_down *event = data; 405 struct wlr_touch_down_event *event = data;
458 cursor_handle_activity_from_device(cursor, event->device); 406 cursor_handle_activity_from_device(cursor, &event->touch->base);
459 cursor_hide(cursor); 407 cursor_hide(cursor);
460 408
461 struct sway_seat *seat = cursor->seat; 409 struct sway_seat *seat = cursor->seat;
462 struct wlr_seat *wlr_seat = seat->wlr_seat;
463 struct wlr_surface *surface = NULL;
464 410
465 double lx, ly; 411 double lx, ly;
466 wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, 412 wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
467 event->x, event->y, &lx, &ly); 413 event->x, event->y, &lx, &ly);
468 double sx, sy;
469 struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy);
470 414
471 seat->touch_id = event->touch_id; 415 seat->touch_id = event->touch_id;
472 seat->touch_x = lx; 416 seat->touch_x = lx;
473 seat->touch_y = ly; 417 seat->touch_y = ly;
474 418
475 if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { 419 seatop_touch_down(seat, event, lx, ly);
476 if (seat_is_input_allowed(seat, surface)) { 420}
477 wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec,
478 event->touch_id, sx, sy);
479 421
480 if (focused_node) { 422static void handle_touch_up(struct wl_listener *listener, void *data) {
481 seat_set_focus(seat, focused_node); 423 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up);
482 } 424 struct wlr_touch_up_event *event = data;
425 cursor_handle_activity_from_device(cursor, &event->touch->base);
426
427 struct sway_seat *seat = cursor->seat;
428
429 if (cursor->simulating_pointer_from_touch) {
430 if (cursor->pointer_touch_id == cursor->seat->touch_id) {
431 cursor->pointer_touch_up = true;
432 dispatch_cursor_button(cursor, &event->touch->base,
433 event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED);
483 } 434 }
484 } else if (!cursor->simulating_pointer_from_touch && 435 } else {
485 (!surface || seat_is_input_allowed(seat, surface))) { 436 seatop_touch_up(seat, event);
486 // Fallback to cursor simulation.
487 // The pointer_touch_id state is needed, so drags are not aborted when over
488 // a surface supporting touch and multi touch events don't interfere.
489 cursor->simulating_pointer_from_touch = true;
490 cursor->pointer_touch_id = seat->touch_id;
491 double dx, dy;
492 dx = lx - cursor->cursor->x;
493 dy = ly - cursor->cursor->y;
494 pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy);
495 dispatch_cursor_button(cursor, event->device, event->time_msec,
496 BTN_LEFT, WLR_BUTTON_PRESSED);
497 wlr_seat_pointer_notify_frame(wlr_seat);
498 transaction_commit_dirty();
499 } 437 }
500} 438}
501 439
502static void handle_touch_up(struct wl_listener *listener, void *data) { 440static void handle_touch_cancel(struct wl_listener *listener, void *data) {
503 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); 441 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel);
504 struct wlr_event_touch_up *event = data; 442 struct wlr_touch_cancel_event *event = data;
505 cursor_handle_activity_from_device(cursor, event->device); 443 cursor_handle_activity_from_device(cursor, &event->touch->base);
506 444
507 struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; 445 struct sway_seat *seat = cursor->seat;
508 446
509 if (cursor->simulating_pointer_from_touch) { 447 if (cursor->simulating_pointer_from_touch) {
510 if (cursor->pointer_touch_id == cursor->seat->touch_id) { 448 if (cursor->pointer_touch_id == cursor->seat->touch_id) {
511 cursor->simulating_pointer_from_touch = false; 449 cursor->pointer_touch_up = true;
512 dispatch_cursor_button(cursor, event->device, event->time_msec, 450 dispatch_cursor_button(cursor, &event->touch->base,
513 BTN_LEFT, WLR_BUTTON_RELEASED); 451 event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED);
514 wlr_seat_pointer_notify_frame(wlr_seat);
515 transaction_commit_dirty();
516 } 452 }
517 } else { 453 } else {
518 wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); 454 seatop_touch_cancel(seat, event);
519 } 455 }
520} 456}
521 457
522static void handle_touch_motion(struct wl_listener *listener, void *data) { 458static void handle_touch_motion(struct wl_listener *listener, void *data) {
523 struct sway_cursor *cursor = 459 struct sway_cursor *cursor =
524 wl_container_of(listener, cursor, touch_motion); 460 wl_container_of(listener, cursor, touch_motion);
525 struct wlr_event_touch_motion *event = data; 461 struct wlr_touch_motion_event *event = data;
526 cursor_handle_activity_from_device(cursor, event->device); 462 cursor_handle_activity_from_device(cursor, &event->touch->base);
527 463
528 struct sway_seat *seat = cursor->seat; 464 struct sway_seat *seat = cursor->seat;
529 struct wlr_seat *wlr_seat = seat->wlr_seat;
530 struct wlr_surface *surface = NULL;
531 465
532 double lx, ly; 466 double lx, ly;
533 wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, 467 wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
534 event->x, event->y, &lx, &ly); 468 event->x, event->y, &lx, &ly);
535 double sx, sy;
536 node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy);
537 469
538 if (seat->touch_id == event->touch_id) { 470 if (seat->touch_id == event->touch_id) {
539 seat->touch_x = lx; 471 seat->touch_x = lx;
540 seat->touch_y = ly; 472 seat->touch_y = ly;
541 473
542 struct sway_drag_icon *drag_icon; 474 drag_icons_update_position(seat);
543 wl_list_for_each(drag_icon, &root->drag_icons, link) {
544 if (drag_icon->seat == seat) {
545 drag_icon_update_position(drag_icon);
546 }
547 }
548 } 475 }
549 476
550 if (cursor->simulating_pointer_from_touch) { 477 if (cursor->simulating_pointer_from_touch) {
@@ -552,12 +479,29 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
552 double dx, dy; 479 double dx, dy;
553 dx = lx - cursor->cursor->x; 480 dx = lx - cursor->cursor->x;
554 dy = ly - cursor->cursor->y; 481 dy = ly - cursor->cursor->y;
555 pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); 482 pointer_motion(cursor, event->time_msec, &event->touch->base,
556 transaction_commit_dirty(); 483 dx, dy, dx, dy);
484 }
485 } else {
486 seatop_touch_motion(seat, event, lx, ly);
487 }
488}
489
490static void handle_touch_frame(struct wl_listener *listener, void *data) {
491 struct sway_cursor *cursor =
492 wl_container_of(listener, cursor, touch_frame);
493
494 struct wlr_seat *wlr_seat = cursor->seat->wlr_seat;
495
496 if (cursor->simulating_pointer_from_touch) {
497 wlr_seat_pointer_notify_frame(wlr_seat);
498
499 if (cursor->pointer_touch_up) {
500 cursor->pointer_touch_up = false;
501 cursor->simulating_pointer_from_touch = false;
557 } 502 }
558 } else if (surface) { 503 } else {
559 wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, 504 wlr_seat_touch_notify_frame(wlr_seat);
560 event->touch_id, sx, sy);
561 } 505 }
562} 506}
563 507
@@ -574,14 +518,15 @@ static void apply_mapping_from_region(struct wlr_input_device *device,
574 double x1 = region->x1, x2 = region->x2; 518 double x1 = region->x1, x2 = region->x2;
575 double y1 = region->y1, y2 = region->y2; 519 double y1 = region->y1, y2 = region->y2;
576 520
577 if (region->mm) { 521 if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET_TOOL) {
578 if (device->width_mm == 0 || device->height_mm == 0) { 522 struct wlr_tablet *tablet = wlr_tablet_from_input_device(device);
523 if (tablet->width_mm == 0 || tablet->height_mm == 0) {
579 return; 524 return;
580 } 525 }
581 x1 /= device->width_mm; 526 x1 /= tablet->width_mm;
582 x2 /= device->width_mm; 527 x2 /= tablet->width_mm;
583 y1 /= device->height_mm; 528 y1 /= tablet->height_mm;
584 y2 /= device->height_mm; 529 y2 /= tablet->height_mm;
585 } 530 }
586 531
587 *x = apply_mapping_from_coord(x1, x2, *x); 532 *x = apply_mapping_from_coord(x1, x2, *x);
@@ -639,14 +584,12 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
639 wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); 584 wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool);
640 pointer_motion(cursor, time_msec, input_device->wlr_device, dx, dy, dx, dy); 585 pointer_motion(cursor, time_msec, input_device->wlr_device, dx, dy, dx, dy);
641 } 586 }
642
643 transaction_commit_dirty();
644} 587}
645 588
646static void handle_tool_axis(struct wl_listener *listener, void *data) { 589static void handle_tool_axis(struct wl_listener *listener, void *data) {
647 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); 590 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis);
648 struct wlr_event_tablet_tool_axis *event = data; 591 struct wlr_tablet_tool_axis_event *event = data;
649 cursor_handle_activity_from_device(cursor, event->device); 592 cursor_handle_activity_from_device(cursor, &event->tablet->base);
650 593
651 struct sway_tablet_tool *sway_tool = event->tool->data; 594 struct sway_tablet_tool *sway_tool = event->tool->data;
652 if (!sway_tool) { 595 if (!sway_tool) {
@@ -701,8 +644,8 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) {
701 644
702static void handle_tool_tip(struct wl_listener *listener, void *data) { 645static void handle_tool_tip(struct wl_listener *listener, void *data) {
703 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); 646 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip);
704 struct wlr_event_tablet_tool_tip *event = data; 647 struct wlr_tablet_tool_tip_event *event = data;
705 cursor_handle_activity_from_device(cursor, event->device); 648 cursor_handle_activity_from_device(cursor, &event->tablet->base);
706 649
707 struct sway_tablet_tool *sway_tool = event->tool->data; 650 struct sway_tablet_tool *sway_tool = event->tool->data;
708 struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; 651 struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2;
@@ -717,10 +660,9 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
717 if (cursor->simulating_pointer_from_tool_tip && 660 if (cursor->simulating_pointer_from_tool_tip &&
718 event->state == WLR_TABLET_TOOL_TIP_UP) { 661 event->state == WLR_TABLET_TOOL_TIP_UP) {
719 cursor->simulating_pointer_from_tool_tip = false; 662 cursor->simulating_pointer_from_tool_tip = false;
720 dispatch_cursor_button(cursor, event->device, event->time_msec, 663 dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
721 BTN_LEFT, WLR_BUTTON_RELEASED); 664 BTN_LEFT, WLR_BUTTON_RELEASED);
722 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 665 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
723 transaction_commit_dirty();
724 } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { 666 } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
725 // If we started holding the tool tip down on a surface that accepts 667 // If we started holding the tool tip down on a surface that accepts
726 // tablet v2, we should notify that surface if it gets released over a 668 // tablet v2, we should notify that surface if it gets released over a
@@ -730,10 +672,9 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
730 WLR_TABLET_TOOL_TIP_UP); 672 WLR_TABLET_TOOL_TIP_UP);
731 } else { 673 } else {
732 cursor->simulating_pointer_from_tool_tip = true; 674 cursor->simulating_pointer_from_tool_tip = true;
733 dispatch_cursor_button(cursor, event->device, event->time_msec, 675 dispatch_cursor_button(cursor, &event->tablet->base,
734 BTN_LEFT, WLR_BUTTON_PRESSED); 676 event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED);
735 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 677 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
736 transaction_commit_dirty();
737 } 678 }
738 } else { 679 } else {
739 seatop_tablet_tool_tip(seat, sway_tool, event->time_msec, event->state); 680 seatop_tablet_tool_tip(seat, sway_tool, event->time_msec, event->state);
@@ -754,12 +695,13 @@ static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor,
754static void handle_tool_proximity(struct wl_listener *listener, void *data) { 695static void handle_tool_proximity(struct wl_listener *listener, void *data) {
755 struct sway_cursor *cursor = 696 struct sway_cursor *cursor =
756 wl_container_of(listener, cursor, tool_proximity); 697 wl_container_of(listener, cursor, tool_proximity);
757 struct wlr_event_tablet_tool_proximity *event = data; 698 struct wlr_tablet_tool_proximity_event *event = data;
758 cursor_handle_activity_from_device(cursor, event->device); 699 cursor_handle_activity_from_device(cursor, &event->tablet->base);
759 700
760 struct wlr_tablet_tool *tool = event->tool; 701 struct wlr_tablet_tool *tool = event->tool;
761 if (!tool->data) { 702 if (!tool->data) {
762 struct sway_tablet *tablet = get_tablet_for_device(cursor, event->device); 703 struct sway_tablet *tablet = get_tablet_for_device(cursor,
704 &event->tablet->base);
763 if (!tablet) { 705 if (!tablet) {
764 sway_log(SWAY_ERROR, "no tablet for tablet tool"); 706 sway_log(SWAY_ERROR, "no tablet for tablet tool");
765 return; 707 return;
@@ -784,8 +726,8 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) {
784 726
785static void handle_tool_button(struct wl_listener *listener, void *data) { 727static void handle_tool_button(struct wl_listener *listener, void *data) {
786 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); 728 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button);
787 struct wlr_event_tablet_tool_button *event = data; 729 struct wlr_tablet_tool_button_event *event = data;
788 cursor_handle_activity_from_device(cursor, event->device); 730 cursor_handle_activity_from_device(cursor, &event->tablet->base);
789 731
790 struct sway_tablet_tool *sway_tool = event->tool->data; 732 struct sway_tablet_tool *sway_tool = event->tool->data;
791 if (!sway_tool) { 733 if (!sway_tool) {
@@ -800,32 +742,71 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
800 node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, 742 node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y,
801 &surface, &sx, &sy); 743 &surface, &sx, &sy);
802 744
803 if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { 745 // TODO: floating resize should support graphics tablet events
746 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);
747 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
748 bool mod_pressed = modifiers & config->floating_mod;
749
750 bool surface_supports_tablet_events =
751 surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface);
752
753 // Simulate pointer when:
754 // 1. The modifier key is pressed, OR
755 // 2. The surface under the cursor does not support tablet events.
756 bool should_simulate_pointer = mod_pressed || !surface_supports_tablet_events;
757
758 // Similar to tool tip, we need to selectively simulate mouse events, but we
759 // want to make sure that it is always consistent. Because all tool buttons
760 // currently map to BTN_RIGHT, we need to keep count of how many tool
761 // buttons are currently pressed down so we can send consistent events.
762 //
763 // The logic follows:
764 // - If we are already simulating the pointer, we should continue to do so
765 // until at least no tool button is held down.
766 // - If we should simulate the pointer and no tool button is currently held
767 // down, begin simulating the pointer.
768 // - If neither of the above are true, send the tablet events.
769 if ((cursor->tool_buttons > 0 && cursor->simulating_pointer_from_tool_button)
770 || (cursor->tool_buttons == 0 && should_simulate_pointer)) {
771 cursor->simulating_pointer_from_tool_button = true;
772
804 // TODO: the user may want to configure which tool buttons are mapped to 773 // TODO: the user may want to configure which tool buttons are mapped to
805 // which simulated pointer buttons 774 // which simulated pointer buttons
806 switch (event->state) { 775 switch (event->state) {
807 case WLR_BUTTON_PRESSED: 776 case WLR_BUTTON_PRESSED:
808 if (cursor->tool_buttons == 0) { 777 if (cursor->tool_buttons == 0) {
809 dispatch_cursor_button(cursor, event->device, 778 dispatch_cursor_button(cursor, &event->tablet->base,
810 event->time_msec, BTN_RIGHT, event->state); 779 event->time_msec, BTN_RIGHT, event->state);
811 } 780 }
812 cursor->tool_buttons++;
813 break; 781 break;
814 case WLR_BUTTON_RELEASED: 782 case WLR_BUTTON_RELEASED:
815 if (cursor->tool_buttons == 1) { 783 if (cursor->tool_buttons <= 1) {
816 dispatch_cursor_button(cursor, event->device, 784 dispatch_cursor_button(cursor, &event->tablet->base,
817 event->time_msec, BTN_RIGHT, event->state); 785 event->time_msec, BTN_RIGHT, event->state);
818 } 786 }
819 cursor->tool_buttons--;
820 break; 787 break;
821 } 788 }
822 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 789 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
823 transaction_commit_dirty(); 790 } else {
824 return; 791 cursor->simulating_pointer_from_tool_button = false;
792
793 wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool,
794 event->button, (enum zwp_tablet_pad_v2_button_state)event->state);
825 } 795 }
826 796
827 wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, 797 // Update tool button count.
828 event->button, (enum zwp_tablet_pad_v2_button_state)event->state); 798 switch (event->state) {
799 case WLR_BUTTON_PRESSED:
800 cursor->tool_buttons++;
801 break;
802 case WLR_BUTTON_RELEASED:
803 if (cursor->tool_buttons == 0) {
804 sway_log(SWAY_ERROR, "inconsistent tablet tool button events");
805 } else {
806 cursor->tool_buttons--;
807 }
808 break;
809 }
829} 810}
830 811
831static void check_constraint_region(struct sway_cursor *cursor) { 812static void check_constraint_region(struct sway_cursor *cursor) {
@@ -837,8 +818,8 @@ static void check_constraint_region(struct sway_cursor *cursor) {
837 818
838 struct sway_container *con = view->container; 819 struct sway_container *con = view->container;
839 820
840 double sx = cursor->cursor->x - con->content_x + view->geometry.x; 821 double sx = cursor->cursor->x - con->pending.content_x + view->geometry.x;
841 double sy = cursor->cursor->y - con->content_y + view->geometry.y; 822 double sy = cursor->cursor->y - con->pending.content_y + view->geometry.y;
842 823
843 if (!pixman_region32_contains_point(region, 824 if (!pixman_region32_contains_point(region,
844 floor(sx), floor(sy), NULL)) { 825 floor(sx), floor(sy), NULL)) {
@@ -849,8 +830,8 @@ static void check_constraint_region(struct sway_cursor *cursor) {
849 double sy = (boxes[0].y1 + boxes[0].y2) / 2.; 830 double sy = (boxes[0].y1 + boxes[0].y2) / 2.;
850 831
851 wlr_cursor_warp_closest(cursor->cursor, NULL, 832 wlr_cursor_warp_closest(cursor->cursor, NULL,
852 sx + con->content_x - view->geometry.x, 833 sx + con->pending.content_x - view->geometry.x,
853 sy + con->content_y - view->geometry.y); 834 sy + con->pending.content_y - view->geometry.y);
854 835
855 cursor_rebase(cursor); 836 cursor_rebase(cursor);
856 } 837 }
@@ -911,59 +892,68 @@ static void handle_request_pointer_set_cursor(struct wl_listener *listener,
911 event->hotspot_y, focused_client); 892 event->hotspot_y, focused_client);
912} 893}
913 894
895static void handle_pointer_hold_begin(struct wl_listener *listener, void *data) {
896 struct sway_cursor *cursor = wl_container_of(
897 listener, cursor, hold_begin);
898 struct wlr_pointer_hold_begin_event *event = data;
899 cursor_handle_activity_from_device(cursor, &event->pointer->base);
900 seatop_hold_begin(cursor->seat, event);
901}
902
903static void handle_pointer_hold_end(struct wl_listener *listener, void *data) {
904 struct sway_cursor *cursor = wl_container_of(
905 listener, cursor, hold_end);
906 struct wlr_pointer_hold_end_event *event = data;
907 cursor_handle_activity_from_device(cursor, &event->pointer->base);
908 seatop_hold_end(cursor->seat, event);
909}
910
914static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { 911static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) {
915 struct sway_cursor *cursor = wl_container_of( 912 struct sway_cursor *cursor = wl_container_of(
916 listener, cursor, pinch_begin); 913 listener, cursor, pinch_begin);
917 struct wlr_event_pointer_pinch_begin *event = data; 914 struct wlr_pointer_pinch_begin_event *event = data;
918 wlr_pointer_gestures_v1_send_pinch_begin( 915 cursor_handle_activity_from_device(cursor, &event->pointer->base);
919 cursor->pointer_gestures, cursor->seat->wlr_seat, 916 seatop_pinch_begin(cursor->seat, event);
920 event->time_msec, event->fingers);
921} 917}
922 918
923static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { 919static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) {
924 struct sway_cursor *cursor = wl_container_of( 920 struct sway_cursor *cursor = wl_container_of(
925 listener, cursor, pinch_update); 921 listener, cursor, pinch_update);
926 struct wlr_event_pointer_pinch_update *event = data; 922 struct wlr_pointer_pinch_update_event *event = data;
927 wlr_pointer_gestures_v1_send_pinch_update( 923 cursor_handle_activity_from_device(cursor, &event->pointer->base);
928 cursor->pointer_gestures, cursor->seat->wlr_seat, 924 seatop_pinch_update(cursor->seat, event);
929 event->time_msec, event->dx, event->dy,
930 event->scale, event->rotation);
931} 925}
932 926
933static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { 927static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) {
934 struct sway_cursor *cursor = wl_container_of( 928 struct sway_cursor *cursor = wl_container_of(
935 listener, cursor, pinch_end); 929 listener, cursor, pinch_end);
936 struct wlr_event_pointer_pinch_end *event = data; 930 struct wlr_pointer_pinch_end_event *event = data;
937 wlr_pointer_gestures_v1_send_pinch_end( 931 cursor_handle_activity_from_device(cursor, &event->pointer->base);
938 cursor->pointer_gestures, cursor->seat->wlr_seat, 932 seatop_pinch_end(cursor->seat, event);
939 event->time_msec, event->cancelled);
940} 933}
941 934
942static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { 935static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) {
943 struct sway_cursor *cursor = wl_container_of( 936 struct sway_cursor *cursor = wl_container_of(
944 listener, cursor, swipe_begin); 937 listener, cursor, swipe_begin);
945 struct wlr_event_pointer_swipe_begin *event = data; 938 struct wlr_pointer_swipe_begin_event *event = data;
946 wlr_pointer_gestures_v1_send_swipe_begin( 939 cursor_handle_activity_from_device(cursor, &event->pointer->base);
947 cursor->pointer_gestures, cursor->seat->wlr_seat, 940 seatop_swipe_begin(cursor->seat, event);
948 event->time_msec, event->fingers);
949} 941}
950 942
951static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { 943static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) {
952 struct sway_cursor *cursor = wl_container_of( 944 struct sway_cursor *cursor = wl_container_of(
953 listener, cursor, swipe_update); 945 listener, cursor, swipe_update);
954 struct wlr_event_pointer_swipe_update *event = data; 946 struct wlr_pointer_swipe_update_event *event = data;
955 wlr_pointer_gestures_v1_send_swipe_update( 947 cursor_handle_activity_from_device(cursor, &event->pointer->base);
956 cursor->pointer_gestures, cursor->seat->wlr_seat, 948 seatop_swipe_update(cursor->seat, event);
957 event->time_msec, event->dx, event->dy);
958} 949}
959 950
960static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { 951static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) {
961 struct sway_cursor *cursor = wl_container_of( 952 struct sway_cursor *cursor = wl_container_of(
962 listener, cursor, swipe_end); 953 listener, cursor, swipe_end);
963 struct wlr_event_pointer_swipe_end *event = data; 954 struct wlr_pointer_swipe_end_event *event = data;
964 wlr_pointer_gestures_v1_send_swipe_end( 955 cursor_handle_activity_from_device(cursor, &event->pointer->base);
965 cursor->pointer_gestures, cursor->seat->wlr_seat, 956 seatop_swipe_end(cursor->seat, event);
966 event->time_msec, event->cancelled);
967} 957}
968 958
969static void handle_image_surface_destroy(struct wl_listener *listener, 959static void handle_image_surface_destroy(struct wl_listener *listener,
@@ -1002,10 +992,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image,
1002 } 992 }
1003 993
1004 if (!image) { 994 if (!image) {
1005 wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); 995 wlr_cursor_unset_image(cursor->cursor);
1006 } else if (!current_image || strcmp(current_image, image) != 0) { 996 } else if (!current_image || strcmp(current_image, image) != 0) {
1007 wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, 997 wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image);
1008 cursor->cursor);
1009 } 998 }
1010} 999}
1011 1000
@@ -1037,6 +1026,8 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
1037 wl_event_source_remove(cursor->hide_source); 1026 wl_event_source_remove(cursor->hide_source);
1038 1027
1039 wl_list_remove(&cursor->image_surface_destroy.link); 1028 wl_list_remove(&cursor->image_surface_destroy.link);
1029 wl_list_remove(&cursor->hold_begin.link);
1030 wl_list_remove(&cursor->hold_end.link);
1040 wl_list_remove(&cursor->pinch_begin.link); 1031 wl_list_remove(&cursor->pinch_begin.link);
1041 wl_list_remove(&cursor->pinch_update.link); 1032 wl_list_remove(&cursor->pinch_update.link);
1042 wl_list_remove(&cursor->pinch_end.link); 1033 wl_list_remove(&cursor->pinch_end.link);
@@ -1050,7 +1041,9 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
1050 wl_list_remove(&cursor->frame.link); 1041 wl_list_remove(&cursor->frame.link);
1051 wl_list_remove(&cursor->touch_down.link); 1042 wl_list_remove(&cursor->touch_down.link);
1052 wl_list_remove(&cursor->touch_up.link); 1043 wl_list_remove(&cursor->touch_up.link);
1044 wl_list_remove(&cursor->touch_cancel.link);
1053 wl_list_remove(&cursor->touch_motion.link); 1045 wl_list_remove(&cursor->touch_motion.link);
1046 wl_list_remove(&cursor->touch_frame.link);
1054 wl_list_remove(&cursor->tool_axis.link); 1047 wl_list_remove(&cursor->tool_axis.link);
1055 wl_list_remove(&cursor->tool_tip.link); 1048 wl_list_remove(&cursor->tool_tip.link);
1056 wl_list_remove(&cursor->tool_button.link); 1049 wl_list_remove(&cursor->tool_button.link);
@@ -1085,19 +1078,24 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
1085 wl_list_init(&cursor->image_surface_destroy.link); 1078 wl_list_init(&cursor->image_surface_destroy.link);
1086 cursor->image_surface_destroy.notify = handle_image_surface_destroy; 1079 cursor->image_surface_destroy.notify = handle_image_surface_destroy;
1087 1080
1088 cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); 1081 wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin);
1089 cursor->pinch_begin.notify = handle_pointer_pinch_begin; 1082 cursor->hold_begin.notify = handle_pointer_hold_begin;
1083 wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end);
1084 cursor->hold_end.notify = handle_pointer_hold_end;
1085
1090 wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); 1086 wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin);
1091 cursor->pinch_update.notify = handle_pointer_pinch_update; 1087 cursor->pinch_begin.notify = handle_pointer_pinch_begin;
1092 wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); 1088 wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update);
1093 cursor->pinch_end.notify = handle_pointer_pinch_end; 1089 cursor->pinch_update.notify = handle_pointer_pinch_update;
1094 wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); 1090 wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end);
1095 cursor->swipe_begin.notify = handle_pointer_swipe_begin; 1091 cursor->pinch_end.notify = handle_pointer_pinch_end;
1092
1096 wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); 1093 wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin);
1097 cursor->swipe_update.notify = handle_pointer_swipe_update; 1094 cursor->swipe_begin.notify = handle_pointer_swipe_begin;
1098 wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); 1095 wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update);
1099 cursor->swipe_end.notify = handle_pointer_swipe_end; 1096 cursor->swipe_update.notify = handle_pointer_swipe_update;
1100 wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end); 1097 wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end);
1098 cursor->swipe_end.notify = handle_pointer_swipe_end;
1101 1099
1102 // input events 1100 // input events
1103 wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); 1101 wl_signal_add(&wlr_cursor->events.motion, &cursor->motion);
@@ -1122,10 +1120,16 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
1122 wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); 1120 wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up);
1123 cursor->touch_up.notify = handle_touch_up; 1121 cursor->touch_up.notify = handle_touch_up;
1124 1122
1123 wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel);
1124 cursor->touch_cancel.notify = handle_touch_cancel;
1125
1125 wl_signal_add(&wlr_cursor->events.touch_motion, 1126 wl_signal_add(&wlr_cursor->events.touch_motion,
1126 &cursor->touch_motion); 1127 &cursor->touch_motion);
1127 cursor->touch_motion.notify = handle_touch_motion; 1128 cursor->touch_motion.notify = handle_touch_motion;
1128 1129
1130 wl_signal_add(&wlr_cursor->events.touch_frame, &cursor->touch_frame);
1131 cursor->touch_frame.notify = handle_touch_frame;
1132
1129 wl_signal_add(&wlr_cursor->events.tablet_tool_axis, 1133 wl_signal_add(&wlr_cursor->events.tablet_tool_axis,
1130 &cursor->tool_axis); 1134 &cursor->tool_axis);
1131 cursor->tool_axis.notify = handle_tool_axis; 1135 cursor->tool_axis.notify = handle_tool_axis;
@@ -1170,8 +1174,8 @@ void cursor_warp_to_container(struct sway_cursor *cursor,
1170 return; 1174 return;
1171 } 1175 }
1172 1176
1173 double x = container->x + container->width / 2.0; 1177 double x = container->pending.x + container->pending.width / 2.0;
1174 double y = container->y + container->height / 2.0; 1178 double y = container->pending.y + container->pending.height / 2.0;
1175 1179
1176 wlr_cursor_warp(cursor->cursor, NULL, x, y); 1180 wlr_cursor_warp(cursor->cursor, NULL, x, y);
1177 cursor_unhide(cursor); 1181 cursor_unhide(cursor);
@@ -1211,11 +1215,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) {
1211 // Get event code from name 1215 // Get event code from name
1212 int code = libevdev_event_code_from_name(EV_KEY, name); 1216 int code = libevdev_event_code_from_name(EV_KEY, name);
1213 if (code == -1) { 1217 if (code == -1) {
1214 size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; 1218 *error = format_str("Unknown event %s", name);
1215 *error = malloc(len);
1216 if (*error) {
1217 snprintf(*error, len, "Unknown event %s", name);
1218 }
1219 return 0; 1219 return 0;
1220 } 1220 }
1221 return code; 1221 return code;
@@ -1237,13 +1237,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) {
1237 } 1237 }
1238 const char *event = libevdev_event_code_get_name(EV_KEY, code); 1238 const char *event = libevdev_event_code_get_name(EV_KEY, code);
1239 if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { 1239 if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
1240 size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button", 1240 *error = format_str("Event code %d (%s) is not a button",
1241 code, event ? event : "(null)") + 1; 1241 code, event ? event : "(null)");
1242 *error = malloc(len);
1243 if (*error) {
1244 snprintf(*error, len, "Event code %d (%s) is not a button",
1245 code, event ? event : "(null)");
1246 }
1247 return 0; 1242 return 0;
1248 } 1243 }
1249 return code; 1244 return code;
@@ -1276,16 +1271,19 @@ const char *get_mouse_button_name(uint32_t button) {
1276static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { 1271static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) {
1277 struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; 1272 struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint;
1278 1273
1279 if (constraint->current.committed & 1274 if (constraint->current.cursor_hint.enabled) {
1280 WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
1281 double sx = constraint->current.cursor_hint.x; 1275 double sx = constraint->current.cursor_hint.x;
1282 double sy = constraint->current.cursor_hint.y; 1276 double sy = constraint->current.cursor_hint.y;
1283 1277
1284 struct sway_view *view = view_from_wlr_surface(constraint->surface); 1278 struct sway_view *view = view_from_wlr_surface(constraint->surface);
1279 if (!view) {
1280 return;
1281 }
1282
1285 struct sway_container *con = view->container; 1283 struct sway_container *con = view->container;
1286 1284
1287 double lx = sx + con->content_x - view->geometry.x; 1285 double lx = sx + con->pending.content_x - view->geometry.x;
1288 double ly = sy + con->content_y - view->geometry.y; 1286 double ly = sy + con->pending.content_y - view->geometry.y;
1289 1287
1290 wlr_cursor_warp(cursor->cursor, NULL, lx, ly); 1288 wlr_cursor_warp(cursor->cursor, NULL, lx, ly);
1291 1289
@@ -1332,12 +1330,9 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data) {
1332 sway_constraint->destroy.notify = handle_constraint_destroy; 1330 sway_constraint->destroy.notify = handle_constraint_destroy;
1333 wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); 1331 wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy);
1334 1332
1335 struct sway_node *focus = seat_get_focus(seat); 1333 struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface;
1336 if (focus && focus->type == N_CONTAINER && focus->sway_container->view) { 1334 if (surface && surface == constraint->surface) {
1337 struct wlr_surface *surface = focus->sway_container->view->surface; 1335 sway_cursor_constrain(seat->cursor, constraint);
1338 if (surface == constraint->surface) {
1339 sway_cursor_constrain(seat->cursor, constraint);
1340 }
1341 } 1336 }
1342} 1337}
1343 1338
@@ -1395,3 +1390,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor,
1395 wl_signal_add(&constraint->surface->events.commit, 1390 wl_signal_add(&constraint->surface->events.commit,
1396 &cursor->constraint_commit); 1391 &cursor->constraint_commit);
1397} 1392}
1393
1394void handle_request_set_cursor_shape(struct wl_listener *listener, void *data) {
1395 const struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
1396 struct sway_seat *seat = event->seat_client->seat->data;
1397
1398 if (!seatop_allows_set_cursor(seat)) {
1399 return;
1400 }
1401
1402 struct wl_client *focused_client = NULL;
1403 struct wlr_surface *focused_surface = seat->wlr_seat->pointer_state.focused_surface;
1404 if (focused_surface != NULL) {
1405 focused_client = wl_resource_get_client(focused_surface->resource);
1406 }
1407
1408 // TODO: check cursor mode
1409 if (focused_client == NULL || event->seat_client->client != focused_client) {
1410 sway_log(SWAY_DEBUG, "denying request to set cursor from unfocused client");
1411 return;
1412 }
1413
1414 cursor_set_image(seat->cursor, wlr_cursor_shape_v1_name(event->shape), focused_client);
1415}