diff options
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r-- | sway/input/cursor.c | 587 |
1 files changed, 296 insertions, 291 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 2fe5b202..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,101 @@ 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 | // check for unmanaged views first | 47 | struct wlr_scene_node *scene_node = NULL; |
87 | #if HAVE_XWAYLAND | 48 | |
88 | struct wl_list *unmanaged = &root->xwayland_unmanaged; | 49 | struct wlr_scene_node *node; |
89 | struct sway_xwayland_unmanaged *unmanaged_surface; | 50 | wl_list_for_each_reverse(node, &root->layer_tree->children, link) { |
90 | wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { | 51 | struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node); |
91 | struct wlr_xwayland_surface *xsurface = | 52 | |
92 | unmanaged_surface->wlr_xwayland_surface; | 53 | bool non_interactive = scene_descriptor_try_get(&layer->node, |
93 | 54 | SWAY_SCENE_DESC_NON_INTERACTIVE); | |
94 | double _sx = lx - unmanaged_surface->lx; | 55 | if (non_interactive) { |
95 | double _sy = ly - unmanaged_surface->ly; | 56 | continue; |
96 | if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { | 57 | } |
97 | *surface = xsurface->surface; | 58 | |
98 | *sx = _sx; | 59 | scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy); |
99 | *sy = _sy; | 60 | if (scene_node) { |
100 | return NULL; | 61 | break; |
101 | } | 62 | } |
102 | } | 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_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 | } | ||
103 | #endif | 114 | #endif |
104 | // 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 | ||
105 | struct wlr_output *wlr_output = wlr_output_layout_output_at( | 125 | struct wlr_output *wlr_output = wlr_output_layout_output_at( |
106 | root->output_layout, lx, ly); | 126 | root->output_layout, lx, ly); |
107 | if (wlr_output == NULL) { | 127 | if (wlr_output == NULL) { |
108 | return NULL; | 128 | return NULL; |
109 | } | 129 | } |
130 | |||
110 | struct sway_output *output = wlr_output->data; | 131 | struct sway_output *output = wlr_output->data; |
111 | if (!output || !output->enabled) { | 132 | if (!output || !output->enabled) { |
112 | // output is being destroyed or is being enabled | 133 | // output is being destroyed or is being enabled |
113 | return NULL; | 134 | return NULL; |
114 | } | 135 | } |
115 | double ox = lx, oy = ly; | ||
116 | wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); | ||
117 | |||
118 | if (root->fullscreen_global) { | ||
119 | // Try fullscreen container | ||
120 | struct sway_container *con = tiling_container_at( | ||
121 | &root->fullscreen_global->node, lx, ly, surface, sx, sy); | ||
122 | if (con) { | ||
123 | return &con->node; | ||
124 | } | ||
125 | return NULL; | ||
126 | } | ||
127 | 136 | ||
128 | // find the focused workspace on the output for this seat | ||
129 | struct sway_workspace *ws = output_get_active_workspace(output); | 137 | struct sway_workspace *ws = output_get_active_workspace(output); |
130 | if (!ws) { | 138 | if (!ws) { |
131 | return NULL; | 139 | return NULL; |
132 | } | 140 | } |
133 | 141 | ||
134 | if ((*surface = layer_surface_at(output, | ||
135 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | ||
136 | ox, oy, sx, sy))) { | ||
137 | return NULL; | ||
138 | } | ||
139 | if (ws->fullscreen) { | ||
140 | // Try transient containers | ||
141 | for (int i = 0; i < ws->floating->length; ++i) { | ||
142 | struct sway_container *floater = ws->floating->items[i]; | ||
143 | if (container_is_transient_for(floater, ws->fullscreen)) { | ||
144 | struct sway_container *con = tiling_container_at( | ||
145 | &floater->node, lx, ly, surface, sx, sy); | ||
146 | if (con) { | ||
147 | return &con->node; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | // Try fullscreen container | ||
152 | struct sway_container *con = | ||
153 | tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy); | ||
154 | if (con) { | ||
155 | return &con->node; | ||
156 | } | ||
157 | return NULL; | ||
158 | } | ||
159 | if ((*surface = layer_surface_popup_at(output, | ||
160 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
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_BOTTOM], | ||
166 | ox, oy, sx, sy))) { | ||
167 | return NULL; | ||
168 | } | ||
169 | if ((*surface = layer_surface_popup_at(output, | ||
170 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | ||
171 | ox, oy, sx, sy))) { | ||
172 | return NULL; | ||
173 | } | ||
174 | if ((*surface = layer_surface_at(output, | ||
175 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
176 | ox, oy, sx, sy))) { | ||
177 | return NULL; | ||
178 | } | ||
179 | |||
180 | struct sway_container *c; | ||
181 | if ((c = container_at(ws, lx, ly, surface, sx, sy))) { | ||
182 | return &c->node; | ||
183 | } | ||
184 | |||
185 | if ((*surface = layer_surface_at(output, | ||
186 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | ||
187 | ox, oy, sx, sy))) { | ||
188 | return NULL; | ||
189 | } | ||
190 | if ((*surface = layer_surface_at(output, | ||
191 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | ||
192 | ox, oy, sx, sy))) { | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | return &ws->node; | 142 | return &ws->node; |
197 | } | 143 | } |
198 | 144 | ||
@@ -218,7 +164,7 @@ void cursor_update_image(struct sway_cursor *cursor, | |||
218 | // Try a node's resize edge | 164 | // Try a node's resize edge |
219 | 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); |
220 | if (edge == WLR_EDGE_NONE) { | 166 | if (edge == WLR_EDGE_NONE) { |
221 | cursor_set_image(cursor, "left_ptr", NULL); | 167 | cursor_set_image(cursor, "default", NULL); |
222 | } else if (container_is_floating(node->sway_container)) { | 168 | } else if (container_is_floating(node->sway_container)) { |
223 | cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); | 169 | cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); |
224 | } else { | 170 | } else { |
@@ -229,12 +175,12 @@ void cursor_update_image(struct sway_cursor *cursor, | |||
229 | } | 175 | } |
230 | } | 176 | } |
231 | } else { | 177 | } else { |
232 | cursor_set_image(cursor, "left_ptr", NULL); | 178 | cursor_set_image(cursor, "default", NULL); |
233 | } | 179 | } |
234 | } | 180 | } |
235 | 181 | ||
236 | static void cursor_hide(struct sway_cursor *cursor) { | 182 | static void cursor_hide(struct sway_cursor *cursor) { |
237 | wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); | 183 | wlr_cursor_unset_image(cursor->cursor); |
238 | cursor->hidden = true; | 184 | cursor->hidden = true; |
239 | wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); | 185 | wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); |
240 | } | 186 | } |
@@ -297,7 +243,7 @@ static enum sway_input_idle_source idle_source_from_device( | |||
297 | return IDLE_SOURCE_POINTER; | 243 | return IDLE_SOURCE_POINTER; |
298 | case WLR_INPUT_DEVICE_TOUCH: | 244 | case WLR_INPUT_DEVICE_TOUCH: |
299 | return IDLE_SOURCE_TOUCH; | 245 | return IDLE_SOURCE_TOUCH; |
300 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 246 | case WLR_INPUT_DEVICE_TABLET: |
301 | return IDLE_SOURCE_TABLET_TOOL; | 247 | return IDLE_SOURCE_TABLET_TOOL; |
302 | case WLR_INPUT_DEVICE_TABLET_PAD: | 248 | case WLR_INPUT_DEVICE_TABLET_PAD: |
303 | return IDLE_SOURCE_TABLET_PAD; | 249 | return IDLE_SOURCE_TABLET_PAD; |
@@ -346,7 +292,7 @@ void cursor_unhide(struct sway_cursor *cursor) { | |||
346 | 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)); |
347 | } | 293 | } |
348 | 294 | ||
349 | static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | 295 | void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, |
350 | struct wlr_input_device *device, double dx, double dy, | 296 | struct wlr_input_device *device, double dx, double dy, |
351 | double dx_unaccel, double dy_unaccel) { | 297 | double dx_unaccel, double dy_unaccel) { |
352 | wlr_relative_pointer_manager_v1_send_relative_motion( | 298 | wlr_relative_pointer_manager_v1_send_relative_motion( |
@@ -383,33 +329,34 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
383 | static void handle_pointer_motion_relative( | 329 | static void handle_pointer_motion_relative( |
384 | struct wl_listener *listener, void *data) { | 330 | struct wl_listener *listener, void *data) { |
385 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); | 331 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); |
386 | struct wlr_event_pointer_motion *e = data; | 332 | struct wlr_pointer_motion_event *e = data; |
387 | cursor_handle_activity_from_device(cursor, e->device); | 333 | cursor_handle_activity_from_device(cursor, &e->pointer->base); |
388 | 334 | ||
389 | 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, |
390 | e->unaccel_dx, e->unaccel_dy); | 336 | e->delta_y, e->unaccel_dx, e->unaccel_dy); |
391 | } | 337 | } |
392 | 338 | ||
393 | static void handle_pointer_motion_absolute( | 339 | static void handle_pointer_motion_absolute( |
394 | struct wl_listener *listener, void *data) { | 340 | struct wl_listener *listener, void *data) { |
395 | struct sway_cursor *cursor = | 341 | struct sway_cursor *cursor = |
396 | wl_container_of(listener, cursor, motion_absolute); | 342 | wl_container_of(listener, cursor, motion_absolute); |
397 | struct wlr_event_pointer_motion_absolute *event = data; | 343 | struct wlr_pointer_motion_absolute_event *event = data; |
398 | cursor_handle_activity_from_device(cursor, event->device); | 344 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
399 | 345 | ||
400 | double lx, ly; | 346 | double lx, ly; |
401 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, | 347 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->pointer->base, |
402 | event->x, event->y, &lx, &ly); | 348 | event->x, event->y, &lx, &ly); |
403 | 349 | ||
404 | double dx = lx - cursor->cursor->x; | 350 | double dx = lx - cursor->cursor->x; |
405 | double dy = ly - cursor->cursor->y; | 351 | double dy = ly - cursor->cursor->y; |
406 | 352 | ||
407 | pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); | 353 | pointer_motion(cursor, event->time_msec, &event->pointer->base, dx, dy, |
354 | dx, dy); | ||
408 | } | 355 | } |
409 | 356 | ||
410 | void dispatch_cursor_button(struct sway_cursor *cursor, | 357 | void dispatch_cursor_button(struct sway_cursor *cursor, |
411 | 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, |
412 | enum wlr_button_state state) { | 359 | enum wl_pointer_button_state state) { |
413 | if (time_msec == 0) { | 360 | if (time_msec == 0) { |
414 | time_msec = get_current_time_msec(); | 361 | time_msec = get_current_time_msec(); |
415 | } | 362 | } |
@@ -419,9 +366,9 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
419 | 366 | ||
420 | static void handle_pointer_button(struct wl_listener *listener, void *data) { | 367 | static void handle_pointer_button(struct wl_listener *listener, void *data) { |
421 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); | 368 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); |
422 | struct wlr_event_pointer_button *event = data; | 369 | struct wlr_pointer_button_event *event = data; |
423 | 370 | ||
424 | if (event->state == WLR_BUTTON_PRESSED) { | 371 | if (event->state == WL_POINTER_BUTTON_STATE_PRESSED) { |
425 | cursor->pressed_button_count++; | 372 | cursor->pressed_button_count++; |
426 | } else { | 373 | } else { |
427 | if (cursor->pressed_button_count > 0) { | 374 | if (cursor->pressed_button_count > 0) { |
@@ -431,20 +378,20 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) { | |||
431 | } | 378 | } |
432 | } | 379 | } |
433 | 380 | ||
434 | cursor_handle_activity_from_device(cursor, event->device); | 381 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
435 | dispatch_cursor_button(cursor, event->device, | 382 | dispatch_cursor_button(cursor, &event->pointer->base, |
436 | event->time_msec, event->button, event->state); | 383 | event->time_msec, event->button, event->state); |
437 | } | 384 | } |
438 | 385 | ||
439 | void dispatch_cursor_axis(struct sway_cursor *cursor, | 386 | void dispatch_cursor_axis(struct sway_cursor *cursor, |
440 | struct wlr_event_pointer_axis *event) { | 387 | struct wlr_pointer_axis_event *event) { |
441 | seatop_pointer_axis(cursor->seat, event); | 388 | seatop_pointer_axis(cursor->seat, event); |
442 | } | 389 | } |
443 | 390 | ||
444 | static void handle_pointer_axis(struct wl_listener *listener, void *data) { | 391 | static void handle_pointer_axis(struct wl_listener *listener, void *data) { |
445 | struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); | 392 | struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); |
446 | struct wlr_event_pointer_axis *event = data; | 393 | struct wlr_pointer_axis_event *event = data; |
447 | cursor_handle_activity_from_device(cursor, event->device); | 394 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
448 | dispatch_cursor_axis(cursor, event); | 395 | dispatch_cursor_axis(cursor, event); |
449 | } | 396 | } |
450 | 397 | ||
@@ -455,93 +402,76 @@ static void handle_pointer_frame(struct wl_listener *listener, void *data) { | |||
455 | 402 | ||
456 | static void handle_touch_down(struct wl_listener *listener, void *data) { | 403 | static void handle_touch_down(struct wl_listener *listener, void *data) { |
457 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); | 404 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); |
458 | struct wlr_event_touch_down *event = data; | 405 | struct wlr_touch_down_event *event = data; |
459 | cursor_handle_activity_from_device(cursor, event->device); | 406 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
460 | cursor_hide(cursor); | 407 | cursor_hide(cursor); |
461 | 408 | ||
462 | struct sway_seat *seat = cursor->seat; | 409 | struct sway_seat *seat = cursor->seat; |
463 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
464 | struct wlr_surface *surface = NULL; | ||
465 | 410 | ||
466 | double lx, ly; | 411 | double lx, ly; |
467 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, | 412 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, |
468 | event->x, event->y, &lx, &ly); | 413 | event->x, event->y, &lx, &ly); |
469 | double sx, sy; | ||
470 | struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy); | ||
471 | 414 | ||
472 | seat->touch_id = event->touch_id; | 415 | seat->touch_id = event->touch_id; |
473 | seat->touch_x = lx; | 416 | seat->touch_x = lx; |
474 | seat->touch_y = ly; | 417 | seat->touch_y = ly; |
475 | 418 | ||
476 | if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { | 419 | seatop_touch_down(seat, event, lx, ly); |
477 | if (seat_is_input_allowed(seat, surface)) { | 420 | } |
478 | wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec, | 421 | |
479 | event->touch_id, sx, sy); | 422 | static void handle_touch_up(struct wl_listener *listener, void *data) { |
423 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); | ||
424 | struct wlr_touch_up_event *event = data; | ||
425 | cursor_handle_activity_from_device(cursor, &event->touch->base); | ||
480 | 426 | ||
481 | if (focused_node) { | 427 | struct sway_seat *seat = cursor->seat; |
482 | seat_set_focus(seat, focused_node); | 428 | |
483 | } | 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, WL_POINTER_BUTTON_STATE_RELEASED); | ||
484 | } | 434 | } |
485 | } else if (!cursor->simulating_pointer_from_touch && | 435 | } else { |
486 | (!surface || seat_is_input_allowed(seat, surface))) { | 436 | seatop_touch_up(seat, event); |
487 | // Fallback to cursor simulation. | ||
488 | // The pointer_touch_id state is needed, so drags are not aborted when over | ||
489 | // a surface supporting touch and multi touch events don't interfere. | ||
490 | cursor->simulating_pointer_from_touch = true; | ||
491 | cursor->pointer_touch_id = seat->touch_id; | ||
492 | double dx, dy; | ||
493 | dx = lx - cursor->cursor->x; | ||
494 | dy = ly - cursor->cursor->y; | ||
495 | pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); | ||
496 | dispatch_cursor_button(cursor, event->device, event->time_msec, | ||
497 | BTN_LEFT, WLR_BUTTON_PRESSED); | ||
498 | } | 437 | } |
499 | } | 438 | } |
500 | 439 | ||
501 | static void handle_touch_up(struct wl_listener *listener, void *data) { | 440 | static void handle_touch_cancel(struct wl_listener *listener, void *data) { |
502 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); | 441 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel); |
503 | struct wlr_event_touch_up *event = data; | 442 | struct wlr_touch_cancel_event *event = data; |
504 | cursor_handle_activity_from_device(cursor, event->device); | 443 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
505 | 444 | ||
506 | struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; | 445 | struct sway_seat *seat = cursor->seat; |
507 | 446 | ||
508 | if (cursor->simulating_pointer_from_touch) { | 447 | if (cursor->simulating_pointer_from_touch) { |
509 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { | 448 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { |
510 | cursor->pointer_touch_up = true; | 449 | cursor->pointer_touch_up = true; |
511 | dispatch_cursor_button(cursor, event->device, event->time_msec, | 450 | dispatch_cursor_button(cursor, &event->touch->base, |
512 | BTN_LEFT, WLR_BUTTON_RELEASED); | 451 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); |
513 | } | 452 | } |
514 | } else { | 453 | } else { |
515 | wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); | 454 | seatop_touch_cancel(seat, event); |
516 | } | 455 | } |
517 | } | 456 | } |
518 | 457 | ||
519 | static void handle_touch_motion(struct wl_listener *listener, void *data) { | 458 | static void handle_touch_motion(struct wl_listener *listener, void *data) { |
520 | struct sway_cursor *cursor = | 459 | struct sway_cursor *cursor = |
521 | wl_container_of(listener, cursor, touch_motion); | 460 | wl_container_of(listener, cursor, touch_motion); |
522 | struct wlr_event_touch_motion *event = data; | 461 | struct wlr_touch_motion_event *event = data; |
523 | cursor_handle_activity_from_device(cursor, event->device); | 462 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
524 | 463 | ||
525 | struct sway_seat *seat = cursor->seat; | 464 | struct sway_seat *seat = cursor->seat; |
526 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
527 | struct wlr_surface *surface = NULL; | ||
528 | 465 | ||
529 | double lx, ly; | 466 | double lx, ly; |
530 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, | 467 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, |
531 | event->x, event->y, &lx, &ly); | 468 | event->x, event->y, &lx, &ly); |
532 | double sx, sy; | ||
533 | node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy); | ||
534 | 469 | ||
535 | if (seat->touch_id == event->touch_id) { | 470 | if (seat->touch_id == event->touch_id) { |
536 | seat->touch_x = lx; | 471 | seat->touch_x = lx; |
537 | seat->touch_y = ly; | 472 | seat->touch_y = ly; |
538 | 473 | ||
539 | struct sway_drag_icon *drag_icon; | 474 | drag_icons_update_position(seat); |
540 | wl_list_for_each(drag_icon, &root->drag_icons, link) { | ||
541 | if (drag_icon->seat == seat) { | ||
542 | drag_icon_update_position(drag_icon); | ||
543 | } | ||
544 | } | ||
545 | } | 475 | } |
546 | 476 | ||
547 | if (cursor->simulating_pointer_from_touch) { | 477 | if (cursor->simulating_pointer_from_touch) { |
@@ -549,11 +479,11 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { | |||
549 | double dx, dy; | 479 | double dx, dy; |
550 | dx = lx - cursor->cursor->x; | 480 | dx = lx - cursor->cursor->x; |
551 | dy = ly - cursor->cursor->y; | 481 | dy = ly - cursor->cursor->y; |
552 | pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); | 482 | pointer_motion(cursor, event->time_msec, &event->touch->base, |
483 | dx, dy, dx, dy); | ||
553 | } | 484 | } |
554 | } else if (surface) { | 485 | } else { |
555 | wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, | 486 | seatop_touch_motion(seat, event, lx, ly); |
556 | event->touch_id, sx, sy); | ||
557 | } | 487 | } |
558 | } | 488 | } |
559 | 489 | ||
@@ -588,14 +518,15 @@ static void apply_mapping_from_region(struct wlr_input_device *device, | |||
588 | double x1 = region->x1, x2 = region->x2; | 518 | double x1 = region->x1, x2 = region->x2; |
589 | double y1 = region->y1, y2 = region->y2; | 519 | double y1 = region->y1, y2 = region->y2; |
590 | 520 | ||
591 | if (region->mm) { | 521 | if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET) { |
592 | 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) { | ||
593 | return; | 524 | return; |
594 | } | 525 | } |
595 | x1 /= device->width_mm; | 526 | x1 /= tablet->width_mm; |
596 | x2 /= device->width_mm; | 527 | x2 /= tablet->width_mm; |
597 | y1 /= device->height_mm; | 528 | y1 /= tablet->height_mm; |
598 | y2 /= device->height_mm; | 529 | y2 /= tablet->height_mm; |
599 | } | 530 | } |
600 | 531 | ||
601 | *x = apply_mapping_from_coord(x1, x2, *x); | 532 | *x = apply_mapping_from_coord(x1, x2, *x); |
@@ -657,8 +588,8 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, | |||
657 | 588 | ||
658 | static void handle_tool_axis(struct wl_listener *listener, void *data) { | 589 | static void handle_tool_axis(struct wl_listener *listener, void *data) { |
659 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); | 590 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); |
660 | struct wlr_event_tablet_tool_axis *event = data; | 591 | struct wlr_tablet_tool_axis_event *event = data; |
661 | cursor_handle_activity_from_device(cursor, event->device); | 592 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
662 | 593 | ||
663 | struct sway_tablet_tool *sway_tool = event->tool->data; | 594 | struct sway_tablet_tool *sway_tool = event->tool->data; |
664 | if (!sway_tool) { | 595 | if (!sway_tool) { |
@@ -713,8 +644,8 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { | |||
713 | 644 | ||
714 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | 645 | static void handle_tool_tip(struct wl_listener *listener, void *data) { |
715 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); | 646 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); |
716 | struct wlr_event_tablet_tool_tip *event = data; | 647 | struct wlr_tablet_tool_tip_event *event = data; |
717 | cursor_handle_activity_from_device(cursor, event->device); | 648 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
718 | 649 | ||
719 | struct sway_tablet_tool *sway_tool = event->tool->data; | 650 | struct sway_tablet_tool *sway_tool = event->tool->data; |
720 | 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; |
@@ -729,8 +660,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
729 | if (cursor->simulating_pointer_from_tool_tip && | 660 | if (cursor->simulating_pointer_from_tool_tip && |
730 | event->state == WLR_TABLET_TOOL_TIP_UP) { | 661 | event->state == WLR_TABLET_TOOL_TIP_UP) { |
731 | cursor->simulating_pointer_from_tool_tip = false; | 662 | cursor->simulating_pointer_from_tool_tip = false; |
732 | dispatch_cursor_button(cursor, event->device, event->time_msec, | 663 | dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec, |
733 | BTN_LEFT, WLR_BUTTON_RELEASED); | 664 | BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); |
734 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 665 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
735 | } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { | 666 | } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { |
736 | // 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 |
@@ -741,8 +672,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
741 | WLR_TABLET_TOOL_TIP_UP); | 672 | WLR_TABLET_TOOL_TIP_UP); |
742 | } else { | 673 | } else { |
743 | cursor->simulating_pointer_from_tool_tip = true; | 674 | cursor->simulating_pointer_from_tool_tip = true; |
744 | dispatch_cursor_button(cursor, event->device, event->time_msec, | 675 | dispatch_cursor_button(cursor, &event->tablet->base, |
745 | BTN_LEFT, WLR_BUTTON_PRESSED); | 676 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); |
746 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 677 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
747 | } | 678 | } |
748 | } else { | 679 | } else { |
@@ -764,12 +695,13 @@ static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor, | |||
764 | static void handle_tool_proximity(struct wl_listener *listener, void *data) { | 695 | static void handle_tool_proximity(struct wl_listener *listener, void *data) { |
765 | struct sway_cursor *cursor = | 696 | struct sway_cursor *cursor = |
766 | wl_container_of(listener, cursor, tool_proximity); | 697 | wl_container_of(listener, cursor, tool_proximity); |
767 | struct wlr_event_tablet_tool_proximity *event = data; | 698 | struct wlr_tablet_tool_proximity_event *event = data; |
768 | cursor_handle_activity_from_device(cursor, event->device); | 699 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
769 | 700 | ||
770 | struct wlr_tablet_tool *tool = event->tool; | 701 | struct wlr_tablet_tool *tool = event->tool; |
771 | if (!tool->data) { | 702 | if (!tool->data) { |
772 | 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); | ||
773 | if (!tablet) { | 705 | if (!tablet) { |
774 | sway_log(SWAY_ERROR, "no tablet for tablet tool"); | 706 | sway_log(SWAY_ERROR, "no tablet for tablet tool"); |
775 | return; | 707 | return; |
@@ -794,8 +726,8 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) { | |||
794 | 726 | ||
795 | static void handle_tool_button(struct wl_listener *listener, void *data) { | 727 | static void handle_tool_button(struct wl_listener *listener, void *data) { |
796 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); | 728 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); |
797 | struct wlr_event_tablet_tool_button *event = data; | 729 | struct wlr_tablet_tool_button_event *event = data; |
798 | cursor_handle_activity_from_device(cursor, event->device); | 730 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
799 | 731 | ||
800 | struct sway_tablet_tool *sway_tool = event->tool->data; | 732 | struct sway_tablet_tool *sway_tool = event->tool->data; |
801 | if (!sway_tool) { | 733 | if (!sway_tool) { |
@@ -810,31 +742,71 @@ static void handle_tool_button(struct wl_listener *listener, void *data) { | |||
810 | node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, | 742 | node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, |
811 | &surface, &sx, &sy); | 743 | &surface, &sx, &sy); |
812 | 744 | ||
813 | 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 | |||
814 | // 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 |
815 | // which simulated pointer buttons | 774 | // which simulated pointer buttons |
816 | switch (event->state) { | 775 | switch (event->state) { |
817 | case WLR_BUTTON_PRESSED: | 776 | case WLR_BUTTON_PRESSED: |
818 | if (cursor->tool_buttons == 0) { | 777 | if (cursor->tool_buttons == 0) { |
819 | dispatch_cursor_button(cursor, event->device, | 778 | dispatch_cursor_button(cursor, &event->tablet->base, |
820 | event->time_msec, BTN_RIGHT, event->state); | 779 | event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_PRESSED); |
821 | } | 780 | } |
822 | cursor->tool_buttons++; | ||
823 | break; | 781 | break; |
824 | case WLR_BUTTON_RELEASED: | 782 | case WLR_BUTTON_RELEASED: |
825 | if (cursor->tool_buttons == 1) { | 783 | if (cursor->tool_buttons <= 1) { |
826 | dispatch_cursor_button(cursor, event->device, | 784 | dispatch_cursor_button(cursor, &event->tablet->base, |
827 | event->time_msec, BTN_RIGHT, event->state); | 785 | event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_RELEASED); |
828 | } | 786 | } |
829 | cursor->tool_buttons--; | ||
830 | break; | 787 | break; |
831 | } | 788 | } |
832 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 789 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
833 | 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); | ||
834 | } | 795 | } |
835 | 796 | ||
836 | wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, | 797 | // Update tool button count. |
837 | 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 | } | ||
838 | } | 810 | } |
839 | 811 | ||
840 | static void check_constraint_region(struct sway_cursor *cursor) { | 812 | static void check_constraint_region(struct sway_cursor *cursor) { |
@@ -920,59 +892,68 @@ static void handle_request_pointer_set_cursor(struct wl_listener *listener, | |||
920 | event->hotspot_y, focused_client); | 892 | event->hotspot_y, focused_client); |
921 | } | 893 | } |
922 | 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 | |||
923 | 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) { |
924 | struct sway_cursor *cursor = wl_container_of( | 912 | struct sway_cursor *cursor = wl_container_of( |
925 | listener, cursor, pinch_begin); | 913 | listener, cursor, pinch_begin); |
926 | struct wlr_event_pointer_pinch_begin *event = data; | 914 | struct wlr_pointer_pinch_begin_event *event = data; |
927 | wlr_pointer_gestures_v1_send_pinch_begin( | 915 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
928 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 916 | seatop_pinch_begin(cursor->seat, event); |
929 | event->time_msec, event->fingers); | ||
930 | } | 917 | } |
931 | 918 | ||
932 | 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) { |
933 | struct sway_cursor *cursor = wl_container_of( | 920 | struct sway_cursor *cursor = wl_container_of( |
934 | listener, cursor, pinch_update); | 921 | listener, cursor, pinch_update); |
935 | struct wlr_event_pointer_pinch_update *event = data; | 922 | struct wlr_pointer_pinch_update_event *event = data; |
936 | wlr_pointer_gestures_v1_send_pinch_update( | 923 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
937 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 924 | seatop_pinch_update(cursor->seat, event); |
938 | event->time_msec, event->dx, event->dy, | ||
939 | event->scale, event->rotation); | ||
940 | } | 925 | } |
941 | 926 | ||
942 | 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) { |
943 | struct sway_cursor *cursor = wl_container_of( | 928 | struct sway_cursor *cursor = wl_container_of( |
944 | listener, cursor, pinch_end); | 929 | listener, cursor, pinch_end); |
945 | struct wlr_event_pointer_pinch_end *event = data; | 930 | struct wlr_pointer_pinch_end_event *event = data; |
946 | wlr_pointer_gestures_v1_send_pinch_end( | 931 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
947 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 932 | seatop_pinch_end(cursor->seat, event); |
948 | event->time_msec, event->cancelled); | ||
949 | } | 933 | } |
950 | 934 | ||
951 | 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) { |
952 | struct sway_cursor *cursor = wl_container_of( | 936 | struct sway_cursor *cursor = wl_container_of( |
953 | listener, cursor, swipe_begin); | 937 | listener, cursor, swipe_begin); |
954 | struct wlr_event_pointer_swipe_begin *event = data; | 938 | struct wlr_pointer_swipe_begin_event *event = data; |
955 | wlr_pointer_gestures_v1_send_swipe_begin( | 939 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
956 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 940 | seatop_swipe_begin(cursor->seat, event); |
957 | event->time_msec, event->fingers); | ||
958 | } | 941 | } |
959 | 942 | ||
960 | 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) { |
961 | struct sway_cursor *cursor = wl_container_of( | 944 | struct sway_cursor *cursor = wl_container_of( |
962 | listener, cursor, swipe_update); | 945 | listener, cursor, swipe_update); |
963 | struct wlr_event_pointer_swipe_update *event = data; | 946 | struct wlr_pointer_swipe_update_event *event = data; |
964 | wlr_pointer_gestures_v1_send_swipe_update( | 947 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
965 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 948 | seatop_swipe_update(cursor->seat, event); |
966 | event->time_msec, event->dx, event->dy); | ||
967 | } | 949 | } |
968 | 950 | ||
969 | 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) { |
970 | struct sway_cursor *cursor = wl_container_of( | 952 | struct sway_cursor *cursor = wl_container_of( |
971 | listener, cursor, swipe_end); | 953 | listener, cursor, swipe_end); |
972 | struct wlr_event_pointer_swipe_end *event = data; | 954 | struct wlr_pointer_swipe_end_event *event = data; |
973 | wlr_pointer_gestures_v1_send_swipe_end( | 955 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
974 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 956 | seatop_swipe_end(cursor->seat, event); |
975 | event->time_msec, event->cancelled); | ||
976 | } | 957 | } |
977 | 958 | ||
978 | static void handle_image_surface_destroy(struct wl_listener *listener, | 959 | static void handle_image_surface_destroy(struct wl_listener *listener, |
@@ -1011,10 +992,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image, | |||
1011 | } | 992 | } |
1012 | 993 | ||
1013 | if (!image) { | 994 | if (!image) { |
1014 | wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); | 995 | wlr_cursor_unset_image(cursor->cursor); |
1015 | } else if (!current_image || strcmp(current_image, image) != 0) { | 996 | } else if (!current_image || strcmp(current_image, image) != 0) { |
1016 | wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, | 997 | wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image); |
1017 | cursor->cursor); | ||
1018 | } | 998 | } |
1019 | } | 999 | } |
1020 | 1000 | ||
@@ -1046,6 +1026,8 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { | |||
1046 | wl_event_source_remove(cursor->hide_source); | 1026 | wl_event_source_remove(cursor->hide_source); |
1047 | 1027 | ||
1048 | 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); | ||
1049 | wl_list_remove(&cursor->pinch_begin.link); | 1031 | wl_list_remove(&cursor->pinch_begin.link); |
1050 | wl_list_remove(&cursor->pinch_update.link); | 1032 | wl_list_remove(&cursor->pinch_update.link); |
1051 | wl_list_remove(&cursor->pinch_end.link); | 1033 | wl_list_remove(&cursor->pinch_end.link); |
@@ -1059,6 +1041,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { | |||
1059 | wl_list_remove(&cursor->frame.link); | 1041 | wl_list_remove(&cursor->frame.link); |
1060 | wl_list_remove(&cursor->touch_down.link); | 1042 | wl_list_remove(&cursor->touch_down.link); |
1061 | wl_list_remove(&cursor->touch_up.link); | 1043 | wl_list_remove(&cursor->touch_up.link); |
1044 | wl_list_remove(&cursor->touch_cancel.link); | ||
1062 | wl_list_remove(&cursor->touch_motion.link); | 1045 | wl_list_remove(&cursor->touch_motion.link); |
1063 | wl_list_remove(&cursor->touch_frame.link); | 1046 | wl_list_remove(&cursor->touch_frame.link); |
1064 | wl_list_remove(&cursor->tool_axis.link); | 1047 | wl_list_remove(&cursor->tool_axis.link); |
@@ -1095,19 +1078,24 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
1095 | wl_list_init(&cursor->image_surface_destroy.link); | 1078 | wl_list_init(&cursor->image_surface_destroy.link); |
1096 | cursor->image_surface_destroy.notify = handle_image_surface_destroy; | 1079 | cursor->image_surface_destroy.notify = handle_image_surface_destroy; |
1097 | 1080 | ||
1098 | cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); | 1081 | wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin); |
1099 | 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 | |||
1100 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); | 1086 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); |
1101 | cursor->pinch_update.notify = handle_pointer_pinch_update; | 1087 | cursor->pinch_begin.notify = handle_pointer_pinch_begin; |
1102 | wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); | 1088 | wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); |
1103 | cursor->pinch_end.notify = handle_pointer_pinch_end; | 1089 | cursor->pinch_update.notify = handle_pointer_pinch_update; |
1104 | wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); | 1090 | wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); |
1105 | cursor->swipe_begin.notify = handle_pointer_swipe_begin; | 1091 | cursor->pinch_end.notify = handle_pointer_pinch_end; |
1092 | |||
1106 | wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); | 1093 | wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); |
1107 | cursor->swipe_update.notify = handle_pointer_swipe_update; | 1094 | cursor->swipe_begin.notify = handle_pointer_swipe_begin; |
1108 | wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); | 1095 | wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); |
1109 | cursor->swipe_end.notify = handle_pointer_swipe_end; | 1096 | cursor->swipe_update.notify = handle_pointer_swipe_update; |
1110 | 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; | ||
1111 | 1099 | ||
1112 | // input events | 1100 | // input events |
1113 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); | 1101 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); |
@@ -1132,6 +1120,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
1132 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); | 1120 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); |
1133 | cursor->touch_up.notify = handle_touch_up; | 1121 | cursor->touch_up.notify = handle_touch_up; |
1134 | 1122 | ||
1123 | wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel); | ||
1124 | cursor->touch_cancel.notify = handle_touch_cancel; | ||
1125 | |||
1135 | wl_signal_add(&wlr_cursor->events.touch_motion, | 1126 | wl_signal_add(&wlr_cursor->events.touch_motion, |
1136 | &cursor->touch_motion); | 1127 | &cursor->touch_motion); |
1137 | cursor->touch_motion.notify = handle_touch_motion; | 1128 | cursor->touch_motion.notify = handle_touch_motion; |
@@ -1224,11 +1215,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) { | |||
1224 | // Get event code from name | 1215 | // Get event code from name |
1225 | int code = libevdev_event_code_from_name(EV_KEY, name); | 1216 | int code = libevdev_event_code_from_name(EV_KEY, name); |
1226 | if (code == -1) { | 1217 | if (code == -1) { |
1227 | size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; | 1218 | *error = format_str("Unknown event %s", name); |
1228 | *error = malloc(len); | ||
1229 | if (*error) { | ||
1230 | snprintf(*error, len, "Unknown event %s", name); | ||
1231 | } | ||
1232 | return 0; | 1219 | return 0; |
1233 | } | 1220 | } |
1234 | return code; | 1221 | return code; |
@@ -1250,13 +1237,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) { | |||
1250 | } | 1237 | } |
1251 | const char *event = libevdev_event_code_get_name(EV_KEY, code); | 1238 | const char *event = libevdev_event_code_get_name(EV_KEY, code); |
1252 | if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { | 1239 | if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { |
1253 | 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", |
1254 | code, event ? event : "(null)") + 1; | 1241 | code, event ? event : "(null)"); |
1255 | *error = malloc(len); | ||
1256 | if (*error) { | ||
1257 | snprintf(*error, len, "Event code %d (%s) is not a button", | ||
1258 | code, event ? event : "(null)"); | ||
1259 | } | ||
1260 | return 0; | 1242 | return 0; |
1261 | } | 1243 | } |
1262 | return code; | 1244 | return code; |
@@ -1289,12 +1271,15 @@ const char *get_mouse_button_name(uint32_t button) { | |||
1289 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { | 1271 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { |
1290 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; | 1272 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; |
1291 | 1273 | ||
1292 | if (constraint->current.committed & | 1274 | if (constraint->current.cursor_hint.enabled) { |
1293 | WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { | ||
1294 | double sx = constraint->current.cursor_hint.x; | 1275 | double sx = constraint->current.cursor_hint.x; |
1295 | double sy = constraint->current.cursor_hint.y; | 1276 | double sy = constraint->current.cursor_hint.y; |
1296 | 1277 | ||
1297 | 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 | |||
1298 | struct sway_container *con = view->container; | 1283 | struct sway_container *con = view->container; |
1299 | 1284 | ||
1300 | double lx = sx + con->pending.content_x - view->geometry.x; | 1285 | double lx = sx + con->pending.content_x - view->geometry.x; |
@@ -1345,12 +1330,9 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data) { | |||
1345 | sway_constraint->destroy.notify = handle_constraint_destroy; | 1330 | sway_constraint->destroy.notify = handle_constraint_destroy; |
1346 | wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); | 1331 | wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); |
1347 | 1332 | ||
1348 | struct sway_node *focus = seat_get_focus(seat); | 1333 | struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface; |
1349 | if (focus && focus->type == N_CONTAINER && focus->sway_container->view) { | 1334 | if (surface && surface == constraint->surface) { |
1350 | struct wlr_surface *surface = focus->sway_container->view->surface; | 1335 | sway_cursor_constrain(seat->cursor, constraint); |
1351 | if (surface == constraint->surface) { | ||
1352 | sway_cursor_constrain(seat->cursor, constraint); | ||
1353 | } | ||
1354 | } | 1336 | } |
1355 | } | 1337 | } |
1356 | 1338 | ||
@@ -1408,3 +1390,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor, | |||
1408 | wl_signal_add(&constraint->surface->events.commit, | 1390 | wl_signal_add(&constraint->surface->events.commit, |
1409 | &cursor->constraint_commit); | 1391 | &cursor->constraint_commit); |
1410 | } | 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 | } | ||