diff options
-rw-r--r-- | include/sway/input/cursor.h | 13 | ||||
-rw-r--r-- | include/sway/input/seat.h | 6 | ||||
-rw-r--r-- | include/sway/server.h | 4 | ||||
-rw-r--r-- | protocols/meson.build | 1 | ||||
-rw-r--r-- | sway/input/cursor.c | 235 | ||||
-rw-r--r-- | sway/input/seat.c | 6 | ||||
-rw-r--r-- | sway/input/seatop_down.c | 11 | ||||
-rw-r--r-- | sway/server.c | 9 |
8 files changed, 261 insertions, 24 deletions
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index c87d8332..072a56ca 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _SWAY_INPUT_CURSOR_H | 2 | #define _SWAY_INPUT_CURSOR_H |
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <stdint.h> | 4 | #include <stdint.h> |
5 | #include <wlr/types/wlr_pointer_constraints_v1.h> | ||
5 | #include <wlr/types/wlr_surface.h> | 6 | #include <wlr/types/wlr_surface.h> |
6 | #include "sway/input/seat.h" | 7 | #include "sway/input/seat.h" |
7 | 8 | ||
@@ -26,6 +27,9 @@ struct sway_cursor { | |||
26 | struct wlr_surface *image_surface; | 27 | struct wlr_surface *image_surface; |
27 | int hotspot_x, hotspot_y; | 28 | int hotspot_x, hotspot_y; |
28 | 29 | ||
30 | struct wlr_pointer_constraint_v1 *active_constraint; | ||
31 | pixman_region32_t confine; // invalid if active_constraint == NULL | ||
32 | |||
29 | struct wl_listener motion; | 33 | struct wl_listener motion; |
30 | struct wl_listener motion_absolute; | 34 | struct wl_listener motion_absolute; |
31 | struct wl_listener button; | 35 | struct wl_listener button; |
@@ -43,6 +47,8 @@ struct sway_cursor { | |||
43 | 47 | ||
44 | struct wl_listener request_set_cursor; | 48 | struct wl_listener request_set_cursor; |
45 | 49 | ||
50 | struct wl_listener constraint_commit; | ||
51 | |||
46 | struct wl_event_source *hide_source; | 52 | struct wl_event_source *hide_source; |
47 | bool hidden; | 53 | bool hidden; |
48 | 54 | ||
@@ -75,7 +81,8 @@ int cursor_get_timeout(struct sway_cursor *cursor); | |||
75 | * Like cursor_rebase, but also allows focus to change when the cursor enters a | 81 | * Like cursor_rebase, but also allows focus to change when the cursor enters a |
76 | * new container. | 82 | * new container. |
77 | */ | 83 | */ |
78 | void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec); | 84 | void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, |
85 | struct sway_node *node, struct wlr_surface *surface, double sx, double sy); | ||
79 | 86 | ||
80 | void dispatch_cursor_button(struct sway_cursor *cursor, | 87 | void dispatch_cursor_button(struct sway_cursor *cursor, |
81 | struct wlr_input_device *device, uint32_t time_msec, uint32_t button, | 88 | struct wlr_input_device *device, uint32_t time_msec, uint32_t button, |
@@ -97,6 +104,10 @@ void cursor_warp_to_container(struct sway_cursor *cursor, | |||
97 | void cursor_warp_to_workspace(struct sway_cursor *cursor, | 104 | void cursor_warp_to_workspace(struct sway_cursor *cursor, |
98 | struct sway_workspace *workspace); | 105 | struct sway_workspace *workspace); |
99 | 106 | ||
107 | |||
108 | void sway_cursor_constrain(struct sway_cursor *cursor, | ||
109 | struct wlr_pointer_constraint_v1 *constraint); | ||
110 | |||
100 | uint32_t get_mouse_bindsym(const char *name, char **error); | 111 | uint32_t get_mouse_bindsym(const char *name, char **error); |
101 | 112 | ||
102 | uint32_t get_mouse_bindcode(const char *name, char **error); | 113 | uint32_t get_mouse_bindcode(const char *name, char **error); |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index ef85b67f..1c9354df 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -84,6 +84,12 @@ struct sway_seat { | |||
84 | struct wl_list link; // input_manager::seats | 84 | struct wl_list link; // input_manager::seats |
85 | }; | 85 | }; |
86 | 86 | ||
87 | struct sway_pointer_constraint { | ||
88 | struct wlr_pointer_constraint_v1 *constraint; | ||
89 | |||
90 | struct wl_listener destroy; | ||
91 | }; | ||
92 | |||
87 | struct sway_seat *seat_create(const char *seat_name); | 93 | struct sway_seat *seat_create(const char *seat_name); |
88 | 94 | ||
89 | void seat_destroy(struct sway_seat *seat); | 95 | void seat_destroy(struct sway_seat *seat); |
diff --git a/include/sway/server.h b/include/sway/server.h index 9242ceb7..fa2c6557 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -61,6 +61,9 @@ struct sway_server { | |||
61 | 61 | ||
62 | struct wlr_presentation *presentation; | 62 | struct wlr_presentation *presentation; |
63 | 63 | ||
64 | struct wlr_pointer_constraints_v1 *pointer_constraints; | ||
65 | struct wl_listener pointer_constraint; | ||
66 | |||
64 | size_t txn_timeout_ms; | 67 | size_t txn_timeout_ms; |
65 | list_t *transactions; | 68 | list_t *transactions; |
66 | list_t *dirty_nodes; | 69 | list_t *dirty_nodes; |
@@ -86,5 +89,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data); | |||
86 | #endif | 89 | #endif |
87 | void handle_server_decoration(struct wl_listener *listener, void *data); | 90 | void handle_server_decoration(struct wl_listener *listener, void *data); |
88 | void handle_xdg_decoration(struct wl_listener *listener, void *data); | 91 | void handle_xdg_decoration(struct wl_listener *listener, void *data); |
92 | void handle_pointer_constraint(struct wl_listener *listener, void *data); | ||
89 | 93 | ||
90 | #endif | 94 | #endif |
diff --git a/protocols/meson.build b/protocols/meson.build index a031245c..c438b078 100644 --- a/protocols/meson.build +++ b/protocols/meson.build | |||
@@ -39,6 +39,7 @@ server_protocols = [ | |||
39 | [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], | 39 | [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], |
40 | [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], | 40 | [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], |
41 | [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], | 41 | [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], |
42 | [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'], | ||
42 | ['wlr-layer-shell-unstable-v1.xml'], | 43 | ['wlr-layer-shell-unstable-v1.xml'], |
43 | ['wlr-input-inhibitor-unstable-v1.xml'], | 44 | ['wlr-input-inhibitor-unstable-v1.xml'], |
44 | ] | 45 | ] |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c84d6c40..c87efc2b 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <assert.h> | ||
2 | #include <math.h> | 3 | #include <math.h> |
3 | #include <libevdev/libevdev.h> | 4 | #include <libevdev/libevdev.h> |
4 | #include <linux/input-event-codes.h> | 5 | #include <linux/input-event-codes.h> |
@@ -6,10 +7,11 @@ | |||
6 | #include <float.h> | 7 | #include <float.h> |
7 | #include <limits.h> | 8 | #include <limits.h> |
8 | #include <strings.h> | 9 | #include <strings.h> |
10 | #include <wlr/types/wlr_box.h> | ||
9 | #include <wlr/types/wlr_cursor.h> | 11 | #include <wlr/types/wlr_cursor.h> |
10 | #include <wlr/types/wlr_xcursor_manager.h> | ||
11 | #include <wlr/types/wlr_idle.h> | 12 | #include <wlr/types/wlr_idle.h> |
12 | #include <wlr/types/wlr_box.h> | 13 | #include <wlr/types/wlr_xcursor_manager.h> |
14 | #include <wlr/util/region.h> | ||
13 | #include "list.h" | 15 | #include "list.h" |
14 | #include "log.h" | 16 | #include "log.h" |
15 | #include "config.h" | 17 | #include "config.h" |
@@ -327,8 +329,9 @@ void cursor_unhide(struct sway_cursor *cursor) { | |||
327 | cursor_rebase(cursor); | 329 | cursor_rebase(cursor); |
328 | } | 330 | } |
329 | 331 | ||
330 | void cursor_send_pointer_motion(struct sway_cursor *cursor, | 332 | void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, |
331 | uint32_t time_msec) { | 333 | struct sway_node *node, struct wlr_surface *surface, |
334 | double sx, double sy) { | ||
332 | if (time_msec == 0) { | 335 | if (time_msec == 0) { |
333 | time_msec = get_current_time_msec(); | 336 | time_msec = get_current_time_msec(); |
334 | } | 337 | } |
@@ -343,12 +346,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
343 | return; | 346 | return; |
344 | } | 347 | } |
345 | 348 | ||
346 | struct wlr_surface *surface = NULL; | ||
347 | double sx, sy; | ||
348 | |||
349 | struct sway_node *prev_node = cursor->previous.node; | 349 | struct sway_node *prev_node = cursor->previous.node; |
350 | struct sway_node *node = node_at_coords(seat, | ||
351 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | ||
352 | 350 | ||
353 | // Update the stored previous position | 351 | // Update the stored previous position |
354 | cursor->previous.x = cursor->cursor->x; | 352 | cursor->previous.x = cursor->cursor->x; |
@@ -401,9 +399,62 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { | |||
401 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); | 399 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); |
402 | struct wlr_event_pointer_motion *event = data; | 400 | struct wlr_event_pointer_motion *event = data; |
403 | cursor_handle_activity(cursor); | 401 | cursor_handle_activity(cursor); |
404 | wlr_cursor_move(cursor->cursor, event->device, | 402 | |
405 | event->delta_x, event->delta_y); | 403 | double dx = event->delta_x; |
406 | cursor_send_pointer_motion(cursor, event->time_msec); | 404 | double dy = event->delta_y; |
405 | |||
406 | struct wlr_surface *surface = NULL; | ||
407 | double sx, sy; | ||
408 | struct sway_node *node = node_at_coords(cursor->seat, | ||
409 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | ||
410 | |||
411 | if (cursor->active_constraint) { | ||
412 | if (cursor->active_constraint->surface != surface) { | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | double sx_confined, sy_confined; | ||
417 | if (!wlr_region_confine(&cursor->confine, sx, sy, sx + dx, sy + dy, | ||
418 | &sx_confined, &sy_confined)) { | ||
419 | return; | ||
420 | } | ||
421 | |||
422 | dx = sx_confined - sx; | ||
423 | dy = sy_confined - sy; | ||
424 | } | ||
425 | |||
426 | wlr_cursor_move(cursor->cursor, event->device, dx, dy); | ||
427 | cursor_send_pointer_motion(cursor, event->time_msec, node, surface, | ||
428 | sx + dx, sy + dy); | ||
429 | transaction_commit_dirty(); | ||
430 | } | ||
431 | |||
432 | static void cursor_motion_absolute(struct sway_cursor *cursor, | ||
433 | uint32_t time_msec, struct wlr_input_device *dev, | ||
434 | double x, double y) { | ||
435 | cursor_handle_activity(cursor); | ||
436 | |||
437 | double lx, ly; | ||
438 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, dev, | ||
439 | x, y, &lx, &ly); | ||
440 | |||
441 | struct wlr_surface *surface = NULL; | ||
442 | double sx, sy; | ||
443 | struct sway_node *node = node_at_coords(cursor->seat, | ||
444 | lx, ly, &surface, &sx, &sy); | ||
445 | |||
446 | if (cursor->active_constraint) { | ||
447 | if (cursor->active_constraint->surface != surface) { | ||
448 | return; | ||
449 | } | ||
450 | if (!pixman_region32_contains_point(&cursor->confine, | ||
451 | floor(sx), floor(sy), NULL)) { | ||
452 | return; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | wlr_cursor_warp_closest(cursor->cursor, dev, lx, ly); | ||
457 | cursor_send_pointer_motion(cursor, time_msec, node, surface, sx, sy); | ||
407 | transaction_commit_dirty(); | 458 | transaction_commit_dirty(); |
408 | } | 459 | } |
409 | 460 | ||
@@ -412,10 +463,9 @@ static void handle_cursor_motion_absolute( | |||
412 | struct sway_cursor *cursor = | 463 | struct sway_cursor *cursor = |
413 | wl_container_of(listener, cursor, motion_absolute); | 464 | wl_container_of(listener, cursor, motion_absolute); |
414 | struct wlr_event_pointer_motion_absolute *event = data; | 465 | struct wlr_event_pointer_motion_absolute *event = data; |
415 | cursor_handle_activity(cursor); | 466 | |
416 | wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); | 467 | cursor_motion_absolute(cursor, event->time_msec, event->device, |
417 | cursor_send_pointer_motion(cursor, event->time_msec); | 468 | event->x, event->y); |
418 | transaction_commit_dirty(); | ||
419 | } | 469 | } |
420 | 470 | ||
421 | /** | 471 | /** |
@@ -961,9 +1011,7 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { | |||
961 | apply_mapping_from_region(event->device, ic->mapped_from_region, &x, &y); | 1011 | apply_mapping_from_region(event->device, ic->mapped_from_region, &x, &y); |
962 | } | 1012 | } |
963 | 1013 | ||
964 | wlr_cursor_warp_absolute(cursor->cursor, event->device, x, y); | 1014 | cursor_motion_absolute(cursor, event->time_msec, event->device, x, y); |
965 | cursor_send_pointer_motion(cursor, event->time_msec); | ||
966 | transaction_commit_dirty(); | ||
967 | } | 1015 | } |
968 | 1016 | ||
969 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | 1017 | static void handle_tool_tip(struct wl_listener *listener, void *data) { |
@@ -1001,6 +1049,49 @@ static void handle_tool_button(struct wl_listener *listener, void *data) { | |||
1001 | transaction_commit_dirty(); | 1049 | transaction_commit_dirty(); |
1002 | } | 1050 | } |
1003 | 1051 | ||
1052 | static void check_constraint_region(struct sway_cursor *cursor) { | ||
1053 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; | ||
1054 | pixman_region32_t *region = &constraint->region; | ||
1055 | struct sway_view *view = view_from_wlr_surface(constraint->surface); | ||
1056 | if (view) { | ||
1057 | struct sway_container *con = view->container; | ||
1058 | |||
1059 | double sx = cursor->cursor->x - con->content_x + view->geometry.x; | ||
1060 | double sy = cursor->cursor->y - con->content_y + view->geometry.y; | ||
1061 | |||
1062 | if (!pixman_region32_contains_point(region, | ||
1063 | floor(sx), floor(sy), NULL)) { | ||
1064 | int nboxes; | ||
1065 | pixman_box32_t *boxes = pixman_region32_rectangles(region, &nboxes); | ||
1066 | if (nboxes > 0) { | ||
1067 | double sx = (boxes[0].x1 + boxes[0].x2) / 2.; | ||
1068 | double sy = (boxes[0].y1 + boxes[0].y2) / 2.; | ||
1069 | |||
1070 | wlr_cursor_warp_closest(cursor->cursor, NULL, | ||
1071 | sx + con->content_x - view->geometry.x, | ||
1072 | sy + con->content_y - view->geometry.y); | ||
1073 | } | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | // A locked pointer will result in an empty region, thus disallowing all movement | ||
1078 | if (constraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED) { | ||
1079 | pixman_region32_copy(&cursor->confine, region); | ||
1080 | } else { | ||
1081 | pixman_region32_clear(&cursor->confine); | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | static void handle_constraint_commit(struct wl_listener *listener, | ||
1086 | void *data) { | ||
1087 | struct sway_cursor *cursor = | ||
1088 | wl_container_of(listener, cursor, constraint_commit); | ||
1089 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; | ||
1090 | assert(constraint->surface == data); | ||
1091 | |||
1092 | check_constraint_region(cursor); | ||
1093 | } | ||
1094 | |||
1004 | static void handle_request_set_cursor(struct wl_listener *listener, | 1095 | static void handle_request_set_cursor(struct wl_listener *listener, |
1005 | void *data) { | 1096 | void *data) { |
1006 | struct sway_cursor *cursor = | 1097 | struct sway_cursor *cursor = |
@@ -1162,6 +1253,8 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
1162 | &cursor->request_set_cursor); | 1253 | &cursor->request_set_cursor); |
1163 | cursor->request_set_cursor.notify = handle_request_set_cursor; | 1254 | cursor->request_set_cursor.notify = handle_request_set_cursor; |
1164 | 1255 | ||
1256 | wl_list_init(&cursor->constraint_commit.link); | ||
1257 | |||
1165 | cursor->cursor = wlr_cursor; | 1258 | cursor->cursor = wlr_cursor; |
1166 | 1259 | ||
1167 | return cursor; | 1260 | return cursor; |
@@ -1284,3 +1377,107 @@ const char *get_mouse_button_name(uint32_t button) { | |||
1284 | } | 1377 | } |
1285 | return name; | 1378 | return name; |
1286 | } | 1379 | } |
1380 | |||
1381 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { | ||
1382 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; | ||
1383 | |||
1384 | if (constraint->current.committed & | ||
1385 | WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { | ||
1386 | double sx = constraint->current.cursor_hint.x; | ||
1387 | double sy = constraint->current.cursor_hint.y; | ||
1388 | |||
1389 | struct sway_view *view = view_from_wlr_surface(constraint->surface); | ||
1390 | struct sway_container *con = view->container; | ||
1391 | |||
1392 | double lx = sx + con->content_x - view->geometry.x; | ||
1393 | double ly = sy + con->content_y - view->geometry.y; | ||
1394 | |||
1395 | wlr_cursor_warp(cursor->cursor, NULL, lx, ly); | ||
1396 | } | ||
1397 | } | ||
1398 | |||
1399 | void handle_constraint_destroy(struct wl_listener *listener, void *data) { | ||
1400 | struct sway_pointer_constraint *sway_constraint = | ||
1401 | wl_container_of(listener, sway_constraint, destroy); | ||
1402 | struct wlr_pointer_constraint_v1 *constraint = data; | ||
1403 | struct sway_seat *seat = constraint->seat->data; | ||
1404 | struct sway_cursor *cursor = seat->cursor; | ||
1405 | |||
1406 | wl_list_remove(&sway_constraint->destroy.link); | ||
1407 | |||
1408 | if (cursor->active_constraint == constraint) { | ||
1409 | warp_to_constraint_cursor_hint(cursor); | ||
1410 | |||
1411 | if (cursor->constraint_commit.link.next != NULL) { | ||
1412 | wl_list_remove(&cursor->constraint_commit.link); | ||
1413 | } | ||
1414 | wl_list_init(&cursor->constraint_commit.link); | ||
1415 | cursor->active_constraint = NULL; | ||
1416 | } | ||
1417 | |||
1418 | free(sway_constraint); | ||
1419 | } | ||
1420 | |||
1421 | void handle_pointer_constraint(struct wl_listener *listener, void *data) { | ||
1422 | struct wlr_pointer_constraint_v1 *constraint = data; | ||
1423 | struct sway_seat *seat = constraint->seat->data; | ||
1424 | |||
1425 | struct sway_pointer_constraint *sway_constraint = | ||
1426 | calloc(1, sizeof(struct sway_pointer_constraint)); | ||
1427 | sway_constraint->constraint = constraint; | ||
1428 | |||
1429 | sway_constraint->destroy.notify = handle_constraint_destroy; | ||
1430 | wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); | ||
1431 | |||
1432 | struct sway_node *focus = seat_get_focus(seat); | ||
1433 | if (focus && focus->type == N_CONTAINER && focus->sway_container->view) { | ||
1434 | struct wlr_surface *surface = focus->sway_container->view->surface; | ||
1435 | if (surface == constraint->surface) { | ||
1436 | sway_cursor_constrain(seat->cursor, constraint); | ||
1437 | } | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | void sway_cursor_constrain(struct sway_cursor *cursor, | ||
1442 | struct wlr_pointer_constraint_v1 *constraint) { | ||
1443 | if (cursor->active_constraint == constraint) { | ||
1444 | return; | ||
1445 | } | ||
1446 | |||
1447 | wl_list_remove(&cursor->constraint_commit.link); | ||
1448 | if (cursor->active_constraint) { | ||
1449 | if (constraint == NULL) { | ||
1450 | warp_to_constraint_cursor_hint(cursor); | ||
1451 | } | ||
1452 | wlr_pointer_constraint_v1_send_deactivated( | ||
1453 | cursor->active_constraint); | ||
1454 | } | ||
1455 | |||
1456 | cursor->active_constraint = constraint; | ||
1457 | |||
1458 | if (constraint == NULL) { | ||
1459 | wl_list_init(&cursor->constraint_commit.link); | ||
1460 | return; | ||
1461 | } | ||
1462 | |||
1463 | // FIXME: Big hack, stolen from wlr_pointer_constraints_v1.c:121. | ||
1464 | // This is necessary because the focus may be set before the surface | ||
1465 | // has finished committing, which means that warping won't work properly, | ||
1466 | // since this code will be run *after* the focus has been set. | ||
1467 | // That is why we duplicate the code here. | ||
1468 | if (pixman_region32_not_empty(&constraint->current.region)) { | ||
1469 | pixman_region32_intersect(&constraint->region, | ||
1470 | &constraint->surface->input_region, &constraint->current.region); | ||
1471 | } else { | ||
1472 | pixman_region32_copy(&constraint->region, | ||
1473 | &constraint->surface->input_region); | ||
1474 | } | ||
1475 | |||
1476 | check_constraint_region(cursor); | ||
1477 | |||
1478 | wlr_pointer_constraint_v1_send_activated(constraint); | ||
1479 | |||
1480 | cursor->constraint_commit.notify = handle_constraint_commit; | ||
1481 | wl_signal_add(&constraint->surface->events.commit, | ||
1482 | &cursor->constraint_commit); | ||
1483 | } | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index 8cb1d8e9..d159da22 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -105,6 +105,11 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { | |||
105 | wlr_seat_keyboard_notify_enter( | 105 | wlr_seat_keyboard_notify_enter( |
106 | seat->wlr_seat, view->surface, NULL, 0, NULL); | 106 | seat->wlr_seat, view->surface, NULL, 0, NULL); |
107 | } | 107 | } |
108 | |||
109 | struct wlr_pointer_constraint_v1 *constraint = | ||
110 | wlr_pointer_constraints_v1_constraint_for_surface( | ||
111 | server.pointer_constraints, view->surface, seat->wlr_seat); | ||
112 | sway_cursor_constrain(seat->cursor, constraint); | ||
108 | } | 113 | } |
109 | } | 114 | } |
110 | 115 | ||
@@ -684,6 +689,7 @@ static void send_unfocus(struct sway_container *con, void *data) { | |||
684 | 689 | ||
685 | // Unfocus the container and any children (eg. when leaving `focus parent`) | 690 | // Unfocus the container and any children (eg. when leaving `focus parent`) |
686 | static void seat_send_unfocus(struct sway_node *node, struct sway_seat *seat) { | 691 | static void seat_send_unfocus(struct sway_node *node, struct sway_seat *seat) { |
692 | sway_cursor_constrain(seat->cursor, NULL); | ||
687 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); | 693 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); |
688 | if (node->type == N_WORKSPACE) { | 694 | if (node->type == N_WORKSPACE) { |
689 | workspace_for_each_container(node->sway_workspace, send_unfocus, seat); | 695 | workspace_for_each_container(node->sway_workspace, send_unfocus, seat); |
diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index c491e9c2..c2256c9a 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c | |||
@@ -26,14 +26,19 @@ static void handle_motion(struct sway_seat *seat, uint32_t time_msec) { | |||
26 | 26 | ||
27 | static void handle_finish(struct sway_seat *seat) { | 27 | static void handle_finish(struct sway_seat *seat) { |
28 | struct seatop_down_event *e = seat->seatop_data; | 28 | struct seatop_down_event *e = seat->seatop_data; |
29 | struct sway_cursor *cursor = seat->cursor; | ||
29 | // Set the cursor's previous coords to the x/y at the start of the | 30 | // Set the cursor's previous coords to the x/y at the start of the |
30 | // operation, so the container change will be detected if using | 31 | // operation, so the container change will be detected if using |
31 | // focus_follows_mouse and the cursor moved off the original container | 32 | // focus_follows_mouse and the cursor moved off the original container |
32 | // during the operation. | 33 | // during the operation. |
33 | seat->cursor->previous.x = e->ref_lx; | 34 | cursor->previous.x = e->ref_lx; |
34 | seat->cursor->previous.y = e->ref_ly; | 35 | cursor->previous.y = e->ref_ly; |
35 | if (e->moved) { | 36 | if (e->moved) { |
36 | cursor_send_pointer_motion(seat->cursor, 0); | 37 | struct wlr_surface *surface = NULL; |
38 | double sx, sy; | ||
39 | struct sway_node *node = node_at_coords(seat, | ||
40 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | ||
41 | cursor_send_pointer_motion(cursor, 0, node, surface, sx, sy); | ||
37 | } | 42 | } |
38 | } | 43 | } |
39 | 44 | ||
diff --git a/sway/server.c b/sway/server.c index 43dc3900..82262585 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -10,11 +10,12 @@ | |||
10 | #include <wlr/types/wlr_compositor.h> | 10 | #include <wlr/types/wlr_compositor.h> |
11 | #include <wlr/types/wlr_data_control_v1.h> | 11 | #include <wlr/types/wlr_data_control_v1.h> |
12 | #include <wlr/types/wlr_export_dmabuf_v1.h> | 12 | #include <wlr/types/wlr_export_dmabuf_v1.h> |
13 | #include <wlr/types/wlr_gamma_control_v1.h> | ||
14 | #include <wlr/types/wlr_gamma_control.h> | 13 | #include <wlr/types/wlr_gamma_control.h> |
14 | #include <wlr/types/wlr_gamma_control_v1.h> | ||
15 | #include <wlr/types/wlr_gtk_primary_selection.h> | 15 | #include <wlr/types/wlr_gtk_primary_selection.h> |
16 | #include <wlr/types/wlr_idle.h> | 16 | #include <wlr/types/wlr_idle.h> |
17 | #include <wlr/types/wlr_layer_shell_v1.h> | 17 | #include <wlr/types/wlr_layer_shell_v1.h> |
18 | #include <wlr/types/wlr_pointer_constraints_v1.h> | ||
18 | #include <wlr/types/wlr_screencopy_v1.h> | 19 | #include <wlr/types/wlr_screencopy_v1.h> |
19 | #include <wlr/types/wlr_server_decoration.h> | 20 | #include <wlr/types/wlr_server_decoration.h> |
20 | #include <wlr/types/wlr_xcursor_manager.h> | 21 | #include <wlr/types/wlr_xcursor_manager.h> |
@@ -105,6 +106,12 @@ bool server_init(struct sway_server *server) { | |||
105 | server->xdg_decoration.notify = handle_xdg_decoration; | 106 | server->xdg_decoration.notify = handle_xdg_decoration; |
106 | wl_list_init(&server->xdg_decorations); | 107 | wl_list_init(&server->xdg_decorations); |
107 | 108 | ||
109 | server->pointer_constraints = | ||
110 | wlr_pointer_constraints_v1_create(server->wl_display); | ||
111 | server->pointer_constraint.notify = handle_pointer_constraint; | ||
112 | wl_signal_add(&server->pointer_constraints->events.new_constraint, | ||
113 | &server->pointer_constraint); | ||
114 | |||
108 | server->presentation = | 115 | server->presentation = |
109 | wlr_presentation_create(server->wl_display, server->backend); | 116 | wlr_presentation_create(server->wl_display, server->backend); |
110 | 117 | ||