diff options
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r-- | sway/input/cursor.c | 513 |
1 files changed, 239 insertions, 274 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 0b2f03a2..3d04826c 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <assert.h> | 1 | #include <assert.h> |
3 | #include <math.h> | 2 | #include <math.h> |
4 | #include <libevdev/libevdev.h> | 3 | #include <libevdev/libevdev.h> |
@@ -7,8 +6,9 @@ | |||
7 | #include <time.h> | 6 | #include <time.h> |
8 | #include <strings.h> | 7 | #include <strings.h> |
9 | #include <wlr/types/wlr_cursor.h> | 8 | #include <wlr/types/wlr_cursor.h> |
10 | #include <wlr/types/wlr_idle.h> | 9 | #include <wlr/types/wlr_cursor_shape_v1.h> |
11 | #include <wlr/types/wlr_pointer.h> | 10 | #include <wlr/types/wlr_pointer.h> |
11 | #include <wlr/types/wlr_relative_pointer_v1.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> |
14 | #include <wlr/types/wlr_tablet_pad.h> | 14 | #include <wlr/types/wlr_tablet_pad.h> |
@@ -19,12 +19,12 @@ | |||
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/input/cursor.h" | 22 | #include "sway/input/cursor.h" |
24 | #include "sway/input/keyboard.h" | 23 | #include "sway/input/keyboard.h" |
25 | #include "sway/input/tablet.h" | 24 | #include "sway/input/tablet.h" |
26 | #include "sway/layers.h" | 25 | #include "sway/layers.h" |
27 | #include "sway/output.h" | 26 | #include "sway/output.h" |
27 | #include "sway/scene_descriptor.h" | ||
28 | #include "sway/tree/container.h" | 28 | #include "sway/tree/container.h" |
29 | #include "sway/tree/root.h" | 29 | #include "sway/tree/root.h" |
30 | #include "sway/tree/view.h" | 30 | #include "sway/tree/view.h" |
@@ -37,45 +37,6 @@ static uint32_t get_current_time_msec(void) { | |||
37 | return now.tv_sec * 1000 + now.tv_nsec / 1000000; | 37 | return now.tv_sec * 1000 + now.tv_nsec / 1000000; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct wlr_surface *layer_surface_at(struct sway_output *output, | ||
41 | struct wl_list *layer, double ox, double oy, double *sx, double *sy) { | ||
42 | struct sway_layer_surface *sway_layer; | ||
43 | wl_list_for_each_reverse(sway_layer, layer, link) { | ||
44 | double _sx = ox - sway_layer->geo.x; | ||
45 | double _sy = oy - sway_layer->geo.y; | ||
46 | struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( | ||
47 | sway_layer->layer_surface, _sx, _sy, sx, sy); | ||
48 | if (sub) { | ||
49 | return sub; | ||
50 | } | ||
51 | } | ||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | static bool surface_is_xdg_popup(struct wlr_surface *surface) { | ||
56 | if (wlr_surface_is_xdg_surface(surface)) { | ||
57 | struct wlr_xdg_surface *xdg_surface = | ||
58 | wlr_xdg_surface_from_wlr_surface(surface); | ||
59 | return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP; | ||
60 | } | ||
61 | return false; | ||
62 | } | ||
63 | |||
64 | static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, | ||
65 | struct wl_list *layer, double ox, double oy, double *sx, double *sy) { | ||
66 | struct sway_layer_surface *sway_layer; | ||
67 | wl_list_for_each_reverse(sway_layer, layer, link) { | ||
68 | double _sx = ox - sway_layer->geo.x; | ||
69 | double _sy = oy - sway_layer->geo.y; | ||
70 | struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( | ||
71 | sway_layer->layer_surface, _sx, _sy, sx, sy); | ||
72 | if (sub && surface_is_xdg_popup(sub)) { | ||
73 | return sub; | ||
74 | } | ||
75 | } | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | /** | 40 | /** |
80 | * Returns the node at the cursor's position. If there is a surface at that | 41 | * Returns the node at the cursor's position. If there is a surface at that |
81 | * location, it is stored in **surface (it may not be a view). | 42 | * location, it is stored in **surface (it may not be a view). |
@@ -83,116 +44,98 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, | |||
83 | struct sway_node *node_at_coords( | 44 | struct sway_node *node_at_coords( |
84 | struct sway_seat *seat, double lx, double ly, | 45 | struct sway_seat *seat, double lx, double ly, |
85 | struct wlr_surface **surface, double *sx, double *sy) { | 46 | struct wlr_surface **surface, double *sx, double *sy) { |
86 | // find the output the cursor is on | 47 | struct wlr_scene_node *scene_node = NULL; |
87 | struct wlr_output *wlr_output = wlr_output_layout_output_at( | ||
88 | root->output_layout, lx, ly); | ||
89 | if (wlr_output == NULL) { | ||
90 | return NULL; | ||
91 | } | ||
92 | struct sway_output *output = wlr_output->data; | ||
93 | if (!output || !output->enabled) { | ||
94 | // output is being destroyed or is being enabled | ||
95 | return NULL; | ||
96 | } | ||
97 | double ox = lx, oy = ly; | ||
98 | wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); | ||
99 | 48 | ||
100 | // layer surfaces on the overlay layer are rendered on top | 49 | struct wlr_scene_node *node; |
101 | if ((*surface = layer_surface_at(output, | 50 | wl_list_for_each_reverse(node, &root->layer_tree->children, link) { |
102 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | 51 | struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node); |
103 | ox, oy, sx, sy))) { | ||
104 | return NULL; | ||
105 | } | ||
106 | 52 | ||
107 | // check for unmanaged views | 53 | bool non_interactive = scene_descriptor_try_get(&layer->node, |
108 | #if HAVE_XWAYLAND | 54 | SWAY_SCENE_DESC_NON_INTERACTIVE); |
109 | struct wl_list *unmanaged = &root->xwayland_unmanaged; | 55 | if (non_interactive) { |
110 | struct sway_xwayland_unmanaged *unmanaged_surface; | 56 | continue; |
111 | wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { | ||
112 | struct wlr_xwayland_surface *xsurface = | ||
113 | unmanaged_surface->wlr_xwayland_surface; | ||
114 | |||
115 | double _sx = lx - unmanaged_surface->lx; | ||
116 | double _sy = ly - unmanaged_surface->ly; | ||
117 | if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { | ||
118 | *surface = xsurface->surface; | ||
119 | *sx = _sx; | ||
120 | *sy = _sy; | ||
121 | return NULL; | ||
122 | } | 57 | } |
123 | } | ||
124 | #endif | ||
125 | 58 | ||
126 | if (root->fullscreen_global) { | 59 | scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy); |
127 | // Try fullscreen container | 60 | if (scene_node) { |
128 | struct sway_container *con = tiling_container_at( | 61 | break; |
129 | &root->fullscreen_global->node, lx, ly, surface, sx, sy); | ||
130 | if (con) { | ||
131 | return &con->node; | ||
132 | } | 62 | } |
133 | return NULL; | ||
134 | } | 63 | } |
135 | 64 | ||
136 | // find the focused workspace on the output for this seat | 65 | if (scene_node) { |
137 | struct sway_workspace *ws = output_get_active_workspace(output); | 66 | // determine what wlr_surface we clicked on |
138 | if (!ws) { | 67 | if (scene_node->type == WLR_SCENE_NODE_BUFFER) { |
139 | return NULL; | 68 | struct wlr_scene_buffer *scene_buffer = |
140 | } | 69 | wlr_scene_buffer_from_node(scene_node); |
70 | struct wlr_scene_surface *scene_surface = | ||
71 | wlr_scene_surface_try_from_buffer(scene_buffer); | ||
141 | 72 | ||
142 | if (ws->fullscreen) { | 73 | if (scene_surface) { |
143 | // Try transient containers | 74 | *surface = scene_surface->surface; |
144 | for (int i = 0; i < ws->floating->length; ++i) { | ||
145 | struct sway_container *floater = ws->floating->items[i]; | ||
146 | if (container_is_transient_for(floater, ws->fullscreen)) { | ||
147 | struct sway_container *con = tiling_container_at( | ||
148 | &floater->node, lx, ly, surface, sx, sy); | ||
149 | if (con) { | ||
150 | return &con->node; | ||
151 | } | ||
152 | } | 75 | } |
153 | } | 76 | } |
154 | // Try fullscreen container | 77 | |
155 | struct sway_container *con = | 78 | // determine what container we clicked on |
156 | tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy); | 79 | struct wlr_scene_node *current = scene_node; |
157 | if (con) { | 80 | while (true) { |
158 | return &con->node; | 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_popup_desc *popup = | ||
94 | scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP); | ||
95 | if (popup && popup->view) { | ||
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 | } | ||
114 | #endif | ||
115 | |||
116 | if (!current->parent) { | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | current = ¤t->parent->node; | ||
159 | } | 121 | } |
160 | return NULL; | ||
161 | } | ||
162 | if ((*surface = layer_surface_popup_at(output, | ||
163 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
164 | ox, oy, sx, sy))) { | ||
165 | return NULL; | ||
166 | } | ||
167 | if ((*surface = layer_surface_popup_at(output, | ||
168 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | ||
169 | ox, oy, sx, sy))) { | ||
170 | return NULL; | ||
171 | } | ||
172 | if ((*surface = layer_surface_popup_at(output, | ||
173 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | ||
174 | ox, oy, sx, sy))) { | ||
175 | return NULL; | ||
176 | } | ||
177 | if ((*surface = layer_surface_at(output, | ||
178 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
179 | ox, oy, sx, sy))) { | ||
180 | return NULL; | ||
181 | } | 122 | } |
182 | 123 | ||
183 | struct sway_container *c; | 124 | // if we aren't on a container, determine what workspace we are on |
184 | if ((c = container_at(ws, lx, ly, surface, sx, sy))) { | 125 | struct wlr_output *wlr_output = wlr_output_layout_output_at( |
185 | return &c->node; | 126 | root->output_layout, lx, ly); |
127 | if (wlr_output == NULL) { | ||
128 | return NULL; | ||
186 | } | 129 | } |
187 | 130 | ||
188 | if ((*surface = layer_surface_at(output, | 131 | struct sway_output *output = wlr_output->data; |
189 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | 132 | if (!output || !output->enabled) { |
190 | ox, oy, sx, sy))) { | 133 | // output is being destroyed or is being enabled |
191 | return NULL; | 134 | return NULL; |
192 | } | 135 | } |
193 | if ((*surface = layer_surface_at(output, | 136 | |
194 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | 137 | struct sway_workspace *ws = output_get_active_workspace(output); |
195 | ox, oy, sx, sy))) { | 138 | if (!ws) { |
196 | return NULL; | 139 | return NULL; |
197 | } | 140 | } |
198 | 141 | ||
@@ -221,7 +164,7 @@ void cursor_update_image(struct sway_cursor *cursor, | |||
221 | // Try a node's resize edge | 164 | // Try a node's resize edge |
222 | 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); |
223 | if (edge == WLR_EDGE_NONE) { | 166 | if (edge == WLR_EDGE_NONE) { |
224 | cursor_set_image(cursor, "left_ptr", NULL); | 167 | cursor_set_image(cursor, "default", NULL); |
225 | } else if (container_is_floating(node->sway_container)) { | 168 | } else if (container_is_floating(node->sway_container)) { |
226 | cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); | 169 | cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); |
227 | } else { | 170 | } else { |
@@ -232,12 +175,12 @@ void cursor_update_image(struct sway_cursor *cursor, | |||
232 | } | 175 | } |
233 | } | 176 | } |
234 | } else { | 177 | } else { |
235 | cursor_set_image(cursor, "left_ptr", NULL); | 178 | cursor_set_image(cursor, "default", NULL); |
236 | } | 179 | } |
237 | } | 180 | } |
238 | 181 | ||
239 | static void cursor_hide(struct sway_cursor *cursor) { | 182 | static void cursor_hide(struct sway_cursor *cursor) { |
240 | wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); | 183 | wlr_cursor_unset_image(cursor->cursor); |
241 | cursor->hidden = true; | 184 | cursor->hidden = true; |
242 | wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); | 185 | wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); |
243 | } | 186 | } |
@@ -300,7 +243,7 @@ static enum sway_input_idle_source idle_source_from_device( | |||
300 | return IDLE_SOURCE_POINTER; | 243 | return IDLE_SOURCE_POINTER; |
301 | case WLR_INPUT_DEVICE_TOUCH: | 244 | case WLR_INPUT_DEVICE_TOUCH: |
302 | return IDLE_SOURCE_TOUCH; | 245 | return IDLE_SOURCE_TOUCH; |
303 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 246 | case WLR_INPUT_DEVICE_TABLET: |
304 | return IDLE_SOURCE_TABLET_TOOL; | 247 | return IDLE_SOURCE_TABLET_TOOL; |
305 | case WLR_INPUT_DEVICE_TABLET_PAD: | 248 | case WLR_INPUT_DEVICE_TABLET_PAD: |
306 | return IDLE_SOURCE_TABLET_PAD; | 249 | return IDLE_SOURCE_TABLET_PAD; |
@@ -349,7 +292,7 @@ void cursor_unhide(struct sway_cursor *cursor) { | |||
349 | 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)); |
350 | } | 293 | } |
351 | 294 | ||
352 | static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | 295 | void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, |
353 | struct wlr_input_device *device, double dx, double dy, | 296 | struct wlr_input_device *device, double dx, double dy, |
354 | double dx_unaccel, double dy_unaccel) { | 297 | double dx_unaccel, double dy_unaccel) { |
355 | wlr_relative_pointer_manager_v1_send_relative_motion( | 298 | wlr_relative_pointer_manager_v1_send_relative_motion( |
@@ -413,7 +356,7 @@ static void handle_pointer_motion_absolute( | |||
413 | 356 | ||
414 | void dispatch_cursor_button(struct sway_cursor *cursor, | 357 | void dispatch_cursor_button(struct sway_cursor *cursor, |
415 | struct wlr_input_device *device, uint32_t time_msec, uint32_t button, | 358 | struct wlr_input_device *device, uint32_t time_msec, uint32_t button, |
416 | enum wlr_button_state state) { | 359 | enum wl_pointer_button_state state) { |
417 | if (time_msec == 0) { | 360 | if (time_msec == 0) { |
418 | time_msec = get_current_time_msec(); | 361 | time_msec = get_current_time_msec(); |
419 | } | 362 | } |
@@ -425,7 +368,7 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) { | |||
425 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); | 368 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); |
426 | struct wlr_pointer_button_event *event = data; | 369 | struct wlr_pointer_button_event *event = data; |
427 | 370 | ||
428 | if (event->state == WLR_BUTTON_PRESSED) { | 371 | if (event->state == WL_POINTER_BUTTON_STATE_PRESSED) { |
429 | cursor->pressed_button_count++; | 372 | cursor->pressed_button_count++; |
430 | } else { | 373 | } else { |
431 | if (cursor->pressed_button_count > 0) { | 374 | if (cursor->pressed_button_count > 0) { |
@@ -464,43 +407,16 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { | |||
464 | cursor_hide(cursor); | 407 | cursor_hide(cursor); |
465 | 408 | ||
466 | struct sway_seat *seat = cursor->seat; | 409 | struct sway_seat *seat = cursor->seat; |
467 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
468 | struct wlr_surface *surface = NULL; | ||
469 | 410 | ||
470 | double lx, ly; | 411 | double lx, ly; |
471 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, | 412 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, |
472 | event->x, event->y, &lx, &ly); | 413 | event->x, event->y, &lx, &ly); |
473 | double sx, sy; | ||
474 | struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy); | ||
475 | 414 | ||
476 | seat->touch_id = event->touch_id; | 415 | seat->touch_id = event->touch_id; |
477 | seat->touch_x = lx; | 416 | seat->touch_x = lx; |
478 | seat->touch_y = ly; | 417 | seat->touch_y = ly; |
479 | 418 | ||
480 | if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { | 419 | seatop_touch_down(seat, event, lx, ly); |
481 | if (seat_is_input_allowed(seat, surface)) { | ||
482 | wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec, | ||
483 | event->touch_id, sx, sy); | ||
484 | |||
485 | if (focused_node) { | ||
486 | seat_set_focus(seat, focused_node); | ||
487 | } | ||
488 | } | ||
489 | } else if (!cursor->simulating_pointer_from_touch && | ||
490 | (!surface || seat_is_input_allowed(seat, surface))) { | ||
491 | // Fallback to cursor simulation. | ||
492 | // The pointer_touch_id state is needed, so drags are not aborted when over | ||
493 | // a surface supporting touch and multi touch events don't interfere. | ||
494 | cursor->simulating_pointer_from_touch = true; | ||
495 | cursor->pointer_touch_id = seat->touch_id; | ||
496 | double dx, dy; | ||
497 | dx = lx - cursor->cursor->x; | ||
498 | dy = ly - cursor->cursor->y; | ||
499 | pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, | ||
500 | dx, dy); | ||
501 | dispatch_cursor_button(cursor, &event->touch->base, event->time_msec, | ||
502 | BTN_LEFT, WLR_BUTTON_PRESSED); | ||
503 | } | ||
504 | } | 420 | } |
505 | 421 | ||
506 | static void handle_touch_up(struct wl_listener *listener, void *data) { | 422 | static void handle_touch_up(struct wl_listener *listener, void *data) { |
@@ -508,16 +424,34 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { | |||
508 | struct wlr_touch_up_event *event = data; | 424 | struct wlr_touch_up_event *event = data; |
509 | cursor_handle_activity_from_device(cursor, &event->touch->base); | 425 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
510 | 426 | ||
511 | struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; | 427 | struct sway_seat *seat = cursor->seat; |
512 | 428 | ||
513 | if (cursor->simulating_pointer_from_touch) { | 429 | if (cursor->simulating_pointer_from_touch) { |
514 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { | 430 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { |
515 | cursor->pointer_touch_up = true; | 431 | cursor->pointer_touch_up = true; |
516 | dispatch_cursor_button(cursor, &event->touch->base, | 432 | dispatch_cursor_button(cursor, &event->touch->base, |
517 | event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); | 433 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); |
518 | } | 434 | } |
519 | } else { | 435 | } else { |
520 | wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); | 436 | seatop_touch_up(seat, event); |
437 | } | ||
438 | } | ||
439 | |||
440 | static void handle_touch_cancel(struct wl_listener *listener, void *data) { | ||
441 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel); | ||
442 | struct wlr_touch_cancel_event *event = data; | ||
443 | cursor_handle_activity_from_device(cursor, &event->touch->base); | ||
444 | |||
445 | struct sway_seat *seat = cursor->seat; | ||
446 | |||
447 | if (cursor->simulating_pointer_from_touch) { | ||
448 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { | ||
449 | cursor->pointer_touch_up = true; | ||
450 | dispatch_cursor_button(cursor, &event->touch->base, | ||
451 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); | ||
452 | } | ||
453 | } else { | ||
454 | seatop_touch_cancel(seat, event); | ||
521 | } | 455 | } |
522 | } | 456 | } |
523 | 457 | ||
@@ -528,25 +462,16 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { | |||
528 | cursor_handle_activity_from_device(cursor, &event->touch->base); | 462 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
529 | 463 | ||
530 | struct sway_seat *seat = cursor->seat; | 464 | struct sway_seat *seat = cursor->seat; |
531 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
532 | struct wlr_surface *surface = NULL; | ||
533 | 465 | ||
534 | double lx, ly; | 466 | double lx, ly; |
535 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, | 467 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, |
536 | event->x, event->y, &lx, &ly); | 468 | event->x, event->y, &lx, &ly); |
537 | double sx, sy; | ||
538 | node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy); | ||
539 | 469 | ||
540 | if (seat->touch_id == event->touch_id) { | 470 | if (seat->touch_id == event->touch_id) { |
541 | seat->touch_x = lx; | 471 | seat->touch_x = lx; |
542 | seat->touch_y = ly; | 472 | seat->touch_y = ly; |
543 | 473 | ||
544 | struct sway_drag_icon *drag_icon; | 474 | drag_icons_update_position(seat); |
545 | wl_list_for_each(drag_icon, &root->drag_icons, link) { | ||
546 | if (drag_icon->seat == seat) { | ||
547 | drag_icon_update_position(drag_icon); | ||
548 | } | ||
549 | } | ||
550 | } | 475 | } |
551 | 476 | ||
552 | if (cursor->simulating_pointer_from_touch) { | 477 | if (cursor->simulating_pointer_from_touch) { |
@@ -557,9 +482,8 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { | |||
557 | pointer_motion(cursor, event->time_msec, &event->touch->base, | 482 | pointer_motion(cursor, event->time_msec, &event->touch->base, |
558 | dx, dy, dx, dy); | 483 | dx, dy, dx, dy); |
559 | } | 484 | } |
560 | } else if (surface) { | 485 | } else { |
561 | wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, | 486 | seatop_touch_motion(seat, event, lx, ly); |
562 | event->touch_id, sx, sy); | ||
563 | } | 487 | } |
564 | } | 488 | } |
565 | 489 | ||
@@ -594,8 +518,8 @@ static void apply_mapping_from_region(struct wlr_input_device *device, | |||
594 | double x1 = region->x1, x2 = region->x2; | 518 | double x1 = region->x1, x2 = region->x2; |
595 | double y1 = region->y1, y2 = region->y2; | 519 | double y1 = region->y1, y2 = region->y2; |
596 | 520 | ||
597 | if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { | 521 | if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET) { |
598 | struct wlr_tablet *tablet = device->tablet; | 522 | struct wlr_tablet *tablet = wlr_tablet_from_input_device(device); |
599 | if (tablet->width_mm == 0 || tablet->height_mm == 0) { | 523 | if (tablet->width_mm == 0 || tablet->height_mm == 0) { |
600 | return; | 524 | return; |
601 | } | 525 | } |
@@ -737,7 +661,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
737 | event->state == WLR_TABLET_TOOL_TIP_UP) { | 661 | event->state == WLR_TABLET_TOOL_TIP_UP) { |
738 | cursor->simulating_pointer_from_tool_tip = false; | 662 | cursor->simulating_pointer_from_tool_tip = false; |
739 | dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec, | 663 | dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec, |
740 | BTN_LEFT, WLR_BUTTON_RELEASED); | 664 | BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); |
741 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 665 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
742 | } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { | 666 | } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { |
743 | // 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 |
@@ -749,7 +673,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
749 | } else { | 673 | } else { |
750 | cursor->simulating_pointer_from_tool_tip = true; | 674 | cursor->simulating_pointer_from_tool_tip = true; |
751 | dispatch_cursor_button(cursor, &event->tablet->base, | 675 | dispatch_cursor_button(cursor, &event->tablet->base, |
752 | event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED); | 676 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); |
753 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 677 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
754 | } | 678 | } |
755 | } else { | 679 | } else { |
@@ -818,31 +742,71 @@ static void handle_tool_button(struct wl_listener *listener, void *data) { | |||
818 | node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, | 742 | node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, |
819 | &surface, &sx, &sy); | 743 | &surface, &sx, &sy); |
820 | 744 | ||
821 | 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 | |||
822 | // 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 |
823 | // which simulated pointer buttons | 774 | // which simulated pointer buttons |
824 | switch (event->state) { | 775 | switch (event->state) { |
825 | case WLR_BUTTON_PRESSED: | 776 | case WLR_BUTTON_PRESSED: |
826 | if (cursor->tool_buttons == 0) { | 777 | if (cursor->tool_buttons == 0) { |
827 | dispatch_cursor_button(cursor, &event->tablet->base, | 778 | dispatch_cursor_button(cursor, &event->tablet->base, |
828 | event->time_msec, BTN_RIGHT, event->state); | 779 | event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_PRESSED); |
829 | } | 780 | } |
830 | cursor->tool_buttons++; | ||
831 | break; | 781 | break; |
832 | case WLR_BUTTON_RELEASED: | 782 | case WLR_BUTTON_RELEASED: |
833 | if (cursor->tool_buttons == 1) { | 783 | if (cursor->tool_buttons <= 1) { |
834 | dispatch_cursor_button(cursor, &event->tablet->base, | 784 | dispatch_cursor_button(cursor, &event->tablet->base, |
835 | event->time_msec, BTN_RIGHT, event->state); | 785 | event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_RELEASED); |
836 | } | 786 | } |
837 | cursor->tool_buttons--; | ||
838 | break; | 787 | break; |
839 | } | 788 | } |
840 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 789 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
841 | return; | 790 | } else { |
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); | ||
842 | } | 795 | } |
843 | 796 | ||
844 | wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, | 797 | // Update tool button count. |
845 | 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 | } | ||
846 | } | 810 | } |
847 | 811 | ||
848 | static void check_constraint_region(struct sway_cursor *cursor) { | 812 | static void check_constraint_region(struct sway_cursor *cursor) { |
@@ -928,14 +892,28 @@ static void handle_request_pointer_set_cursor(struct wl_listener *listener, | |||
928 | event->hotspot_y, focused_client); | 892 | event->hotspot_y, focused_client); |
929 | } | 893 | } |
930 | 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 | |||
931 | 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) { |
932 | struct sway_cursor *cursor = wl_container_of( | 912 | struct sway_cursor *cursor = wl_container_of( |
933 | listener, cursor, pinch_begin); | 913 | listener, cursor, pinch_begin); |
934 | struct wlr_pointer_pinch_begin_event *event = data; | 914 | struct wlr_pointer_pinch_begin_event *event = data; |
935 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | 915 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
936 | wlr_pointer_gestures_v1_send_pinch_begin( | 916 | seatop_pinch_begin(cursor->seat, event); |
937 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
938 | event->time_msec, event->fingers); | ||
939 | } | 917 | } |
940 | 918 | ||
941 | 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) { |
@@ -943,10 +921,7 @@ static void handle_pointer_pinch_update(struct wl_listener *listener, void *data | |||
943 | listener, cursor, pinch_update); | 921 | listener, cursor, pinch_update); |
944 | struct wlr_pointer_pinch_update_event *event = data; | 922 | struct wlr_pointer_pinch_update_event *event = data; |
945 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | 923 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
946 | wlr_pointer_gestures_v1_send_pinch_update( | 924 | seatop_pinch_update(cursor->seat, event); |
947 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
948 | event->time_msec, event->dx, event->dy, | ||
949 | event->scale, event->rotation); | ||
950 | } | 925 | } |
951 | 926 | ||
952 | 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) { |
@@ -954,9 +929,7 @@ static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { | |||
954 | listener, cursor, pinch_end); | 929 | listener, cursor, pinch_end); |
955 | struct wlr_pointer_pinch_end_event *event = data; | 930 | struct wlr_pointer_pinch_end_event *event = data; |
956 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | 931 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
957 | wlr_pointer_gestures_v1_send_pinch_end( | 932 | seatop_pinch_end(cursor->seat, event); |
958 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
959 | event->time_msec, event->cancelled); | ||
960 | } | 933 | } |
961 | 934 | ||
962 | 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) { |
@@ -964,9 +937,7 @@ static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) | |||
964 | listener, cursor, swipe_begin); | 937 | listener, cursor, swipe_begin); |
965 | struct wlr_pointer_swipe_begin_event *event = data; | 938 | struct wlr_pointer_swipe_begin_event *event = data; |
966 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | 939 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
967 | wlr_pointer_gestures_v1_send_swipe_begin( | 940 | seatop_swipe_begin(cursor->seat, event); |
968 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
969 | event->time_msec, event->fingers); | ||
970 | } | 941 | } |
971 | 942 | ||
972 | 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) { |
@@ -974,9 +945,7 @@ static void handle_pointer_swipe_update(struct wl_listener *listener, void *data | |||
974 | listener, cursor, swipe_update); | 945 | listener, cursor, swipe_update); |
975 | struct wlr_pointer_swipe_update_event *event = data; | 946 | struct wlr_pointer_swipe_update_event *event = data; |
976 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | 947 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
977 | wlr_pointer_gestures_v1_send_swipe_update( | 948 | seatop_swipe_update(cursor->seat, event); |
978 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
979 | event->time_msec, event->dx, event->dy); | ||
980 | } | 949 | } |
981 | 950 | ||
982 | 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) { |
@@ -984,29 +953,7 @@ static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { | |||
984 | listener, cursor, swipe_end); | 953 | listener, cursor, swipe_end); |
985 | struct wlr_pointer_swipe_end_event *event = data; | 954 | struct wlr_pointer_swipe_end_event *event = data; |
986 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | 955 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
987 | wlr_pointer_gestures_v1_send_swipe_end( | 956 | seatop_swipe_end(cursor->seat, event); |
988 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
989 | event->time_msec, event->cancelled); | ||
990 | } | ||
991 | |||
992 | static void handle_pointer_hold_begin(struct wl_listener *listener, void *data) { | ||
993 | struct sway_cursor *cursor = wl_container_of( | ||
994 | listener, cursor, hold_begin); | ||
995 | struct wlr_pointer_hold_begin_event *event = data; | ||
996 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | ||
997 | wlr_pointer_gestures_v1_send_hold_begin( | ||
998 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
999 | event->time_msec, event->fingers); | ||
1000 | } | ||
1001 | |||
1002 | static void handle_pointer_hold_end(struct wl_listener *listener, void *data) { | ||
1003 | struct sway_cursor *cursor = wl_container_of( | ||
1004 | listener, cursor, hold_end); | ||
1005 | struct wlr_pointer_hold_end_event *event = data; | ||
1006 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | ||
1007 | wlr_pointer_gestures_v1_send_hold_end( | ||
1008 | cursor->pointer_gestures, cursor->seat->wlr_seat, | ||
1009 | event->time_msec, event->cancelled); | ||
1010 | } | 957 | } |
1011 | 958 | ||
1012 | static void handle_image_surface_destroy(struct wl_listener *listener, | 959 | static void handle_image_surface_destroy(struct wl_listener *listener, |
@@ -1045,10 +992,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image, | |||
1045 | } | 992 | } |
1046 | 993 | ||
1047 | if (!image) { | 994 | if (!image) { |
1048 | wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); | 995 | wlr_cursor_unset_image(cursor->cursor); |
1049 | } else if (!current_image || strcmp(current_image, image) != 0) { | 996 | } else if (!current_image || strcmp(current_image, image) != 0) { |
1050 | wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, | 997 | wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image); |
1051 | cursor->cursor); | ||
1052 | } | 998 | } |
1053 | } | 999 | } |
1054 | 1000 | ||
@@ -1080,14 +1026,14 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { | |||
1080 | wl_event_source_remove(cursor->hide_source); | 1026 | wl_event_source_remove(cursor->hide_source); |
1081 | 1027 | ||
1082 | 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); | ||
1083 | wl_list_remove(&cursor->pinch_begin.link); | 1031 | wl_list_remove(&cursor->pinch_begin.link); |
1084 | wl_list_remove(&cursor->pinch_update.link); | 1032 | wl_list_remove(&cursor->pinch_update.link); |
1085 | wl_list_remove(&cursor->pinch_end.link); | 1033 | wl_list_remove(&cursor->pinch_end.link); |
1086 | wl_list_remove(&cursor->swipe_begin.link); | 1034 | wl_list_remove(&cursor->swipe_begin.link); |
1087 | wl_list_remove(&cursor->swipe_update.link); | 1035 | wl_list_remove(&cursor->swipe_update.link); |
1088 | wl_list_remove(&cursor->swipe_end.link); | 1036 | wl_list_remove(&cursor->swipe_end.link); |
1089 | wl_list_remove(&cursor->hold_begin.link); | ||
1090 | wl_list_remove(&cursor->hold_end.link); | ||
1091 | wl_list_remove(&cursor->motion.link); | 1037 | wl_list_remove(&cursor->motion.link); |
1092 | wl_list_remove(&cursor->motion_absolute.link); | 1038 | wl_list_remove(&cursor->motion_absolute.link); |
1093 | wl_list_remove(&cursor->button.link); | 1039 | wl_list_remove(&cursor->button.link); |
@@ -1095,6 +1041,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { | |||
1095 | wl_list_remove(&cursor->frame.link); | 1041 | wl_list_remove(&cursor->frame.link); |
1096 | wl_list_remove(&cursor->touch_down.link); | 1042 | wl_list_remove(&cursor->touch_down.link); |
1097 | wl_list_remove(&cursor->touch_up.link); | 1043 | wl_list_remove(&cursor->touch_up.link); |
1044 | wl_list_remove(&cursor->touch_cancel.link); | ||
1098 | wl_list_remove(&cursor->touch_motion.link); | 1045 | wl_list_remove(&cursor->touch_motion.link); |
1099 | wl_list_remove(&cursor->touch_frame.link); | 1046 | wl_list_remove(&cursor->touch_frame.link); |
1100 | wl_list_remove(&cursor->tool_axis.link); | 1047 | wl_list_remove(&cursor->tool_axis.link); |
@@ -1131,23 +1078,24 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
1131 | wl_list_init(&cursor->image_surface_destroy.link); | 1078 | wl_list_init(&cursor->image_surface_destroy.link); |
1132 | cursor->image_surface_destroy.notify = handle_image_surface_destroy; | 1079 | cursor->image_surface_destroy.notify = handle_image_surface_destroy; |
1133 | 1080 | ||
1134 | cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); | 1081 | wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin); |
1135 | 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 | |||
1136 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); | 1086 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); |
1137 | cursor->pinch_update.notify = handle_pointer_pinch_update; | 1087 | cursor->pinch_begin.notify = handle_pointer_pinch_begin; |
1138 | wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); | 1088 | wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); |
1139 | cursor->pinch_end.notify = handle_pointer_pinch_end; | 1089 | cursor->pinch_update.notify = handle_pointer_pinch_update; |
1140 | wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); | 1090 | wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); |
1141 | cursor->swipe_begin.notify = handle_pointer_swipe_begin; | 1091 | cursor->pinch_end.notify = handle_pointer_pinch_end; |
1092 | |||
1142 | wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); | 1093 | wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); |
1143 | cursor->swipe_update.notify = handle_pointer_swipe_update; | 1094 | cursor->swipe_begin.notify = handle_pointer_swipe_begin; |
1144 | wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); | 1095 | wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); |
1145 | cursor->swipe_end.notify = handle_pointer_swipe_end; | 1096 | cursor->swipe_update.notify = handle_pointer_swipe_update; |
1146 | wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end); | 1097 | wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end); |
1147 | cursor->hold_begin.notify = handle_pointer_hold_begin; | 1098 | cursor->swipe_end.notify = handle_pointer_swipe_end; |
1148 | wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin); | ||
1149 | cursor->hold_end.notify = handle_pointer_hold_end; | ||
1150 | wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end); | ||
1151 | 1099 | ||
1152 | // input events | 1100 | // input events |
1153 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); | 1101 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); |
@@ -1172,6 +1120,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
1172 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); | 1120 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); |
1173 | cursor->touch_up.notify = handle_touch_up; | 1121 | cursor->touch_up.notify = handle_touch_up; |
1174 | 1122 | ||
1123 | wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel); | ||
1124 | cursor->touch_cancel.notify = handle_touch_cancel; | ||
1125 | |||
1175 | wl_signal_add(&wlr_cursor->events.touch_motion, | 1126 | wl_signal_add(&wlr_cursor->events.touch_motion, |
1176 | &cursor->touch_motion); | 1127 | &cursor->touch_motion); |
1177 | cursor->touch_motion.notify = handle_touch_motion; | 1128 | cursor->touch_motion.notify = handle_touch_motion; |
@@ -1264,11 +1215,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) { | |||
1264 | // Get event code from name | 1215 | // Get event code from name |
1265 | int code = libevdev_event_code_from_name(EV_KEY, name); | 1216 | int code = libevdev_event_code_from_name(EV_KEY, name); |
1266 | if (code == -1) { | 1217 | if (code == -1) { |
1267 | size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; | 1218 | *error = format_str("Unknown event %s", name); |
1268 | *error = malloc(len); | ||
1269 | if (*error) { | ||
1270 | snprintf(*error, len, "Unknown event %s", name); | ||
1271 | } | ||
1272 | return 0; | 1219 | return 0; |
1273 | } | 1220 | } |
1274 | return code; | 1221 | return code; |
@@ -1290,13 +1237,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) { | |||
1290 | } | 1237 | } |
1291 | const char *event = libevdev_event_code_get_name(EV_KEY, code); | 1238 | const char *event = libevdev_event_code_get_name(EV_KEY, code); |
1292 | if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { | 1239 | if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { |
1293 | 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", |
1294 | code, event ? event : "(null)") + 1; | 1241 | code, event ? event : "(null)"); |
1295 | *error = malloc(len); | ||
1296 | if (*error) { | ||
1297 | snprintf(*error, len, "Event code %d (%s) is not a button", | ||
1298 | code, event ? event : "(null)"); | ||
1299 | } | ||
1300 | return 0; | 1242 | return 0; |
1301 | } | 1243 | } |
1302 | return code; | 1244 | return code; |
@@ -1329,12 +1271,15 @@ const char *get_mouse_button_name(uint32_t button) { | |||
1329 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { | 1271 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { |
1330 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; | 1272 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; |
1331 | 1273 | ||
1332 | if (constraint->current.committed & | 1274 | if (constraint->current.cursor_hint.enabled) { |
1333 | WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { | ||
1334 | double sx = constraint->current.cursor_hint.x; | 1275 | double sx = constraint->current.cursor_hint.x; |
1335 | double sy = constraint->current.cursor_hint.y; | 1276 | double sy = constraint->current.cursor_hint.y; |
1336 | 1277 | ||
1337 | 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 | |||
1338 | struct sway_container *con = view->container; | 1283 | struct sway_container *con = view->container; |
1339 | 1284 | ||
1340 | double lx = sx + con->pending.content_x - view->geometry.x; | 1285 | double lx = sx + con->pending.content_x - view->geometry.x; |
@@ -1385,12 +1330,9 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data) { | |||
1385 | sway_constraint->destroy.notify = handle_constraint_destroy; | 1330 | sway_constraint->destroy.notify = handle_constraint_destroy; |
1386 | wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); | 1331 | wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); |
1387 | 1332 | ||
1388 | struct sway_node *focus = seat_get_focus(seat); | 1333 | struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface; |
1389 | if (focus && node_is_view(focus)) { | 1334 | if (surface && surface == constraint->surface) { |
1390 | struct wlr_surface *surface = focus->sway_container->view->surface; | 1335 | sway_cursor_constrain(seat->cursor, constraint); |
1391 | if (surface == constraint->surface) { | ||
1392 | sway_cursor_constrain(seat->cursor, constraint); | ||
1393 | } | ||
1394 | } | 1336 | } |
1395 | } | 1337 | } |
1396 | 1338 | ||
@@ -1448,3 +1390,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor, | |||
1448 | wl_signal_add(&constraint->surface->events.commit, | 1390 | wl_signal_add(&constraint->surface->events.commit, |
1449 | &cursor->constraint_commit); | 1391 | &cursor->constraint_commit); |
1450 | } | 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 | } | ||