diff options
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r-- | sway/input/cursor.c | 632 |
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 | ||
35 | static struct wlr_surface *layer_surface_at(struct sway_output *output, | 34 | static 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 | |||
50 | static 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 | |||
59 | static 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, | |||
78 | struct sway_node *node_at_coords( | 44 | struct 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 = ¤t->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 | ||
231 | static void cursor_hide(struct sway_cursor *cursor) { | 182 | static 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 | ||
344 | static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | 295 | void 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, | |||
378 | static void handle_pointer_motion_relative( | 329 | static 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 | ||
389 | static void handle_pointer_motion_absolute( | 339 | static 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 | ||
407 | void dispatch_cursor_button(struct sway_cursor *cursor, | 357 | void dispatch_cursor_button(struct sway_cursor *cursor, |
@@ -416,7 +366,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
416 | 366 | ||
417 | static void handle_pointer_button(struct wl_listener *listener, void *data) { | 367 | static 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 | ||
437 | void dispatch_cursor_axis(struct sway_cursor *cursor, | 386 | void 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 | ||
442 | static void handle_pointer_axis(struct wl_listener *listener, void *data) { | 391 | static 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 | ||
450 | static void handle_pointer_frame(struct wl_listener *listener, void *data) { | 398 | static 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 | ||
455 | static void handle_touch_down(struct wl_listener *listener, void *data) { | 403 | static 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) { | 422 | static 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 | ||
502 | static void handle_touch_up(struct wl_listener *listener, void *data) { | 440 | static 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 | ||
522 | static void handle_touch_motion(struct wl_listener *listener, void *data) { | 458 | static 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 | |||
490 | static 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 | ||
646 | static void handle_tool_axis(struct wl_listener *listener, void *data) { | 589 | static 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 | ||
702 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | 645 | static 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, | |||
754 | static void handle_tool_proximity(struct wl_listener *listener, void *data) { | 695 | static 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 | ||
785 | static void handle_tool_button(struct wl_listener *listener, void *data) { | 727 | static 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 | ||
831 | static void check_constraint_region(struct sway_cursor *cursor) { | 812 | static 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 | ||
895 | static 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 | |||
903 | static 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 | |||
914 | static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { | 911 | static 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 | ||
923 | static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { | 919 | static 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 | ||
933 | static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { | 927 | static 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 | ||
942 | static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { | 935 | static 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 | ||
951 | static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { | 943 | static 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 | ||
960 | static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { | 951 | static 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 | ||
969 | static void handle_image_surface_destroy(struct wl_listener *listener, | 959 | static 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) { | |||
1276 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { | 1271 | static 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 | |||
1394 | void 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 | } | ||