diff options
author | Las <las@protonmail.ch> | 2019-01-26 00:45:06 +0100 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2019-01-30 19:53:59 +0100 |
commit | cedde21c967ae5be0d1a9c7656ab8c6b3186ae42 (patch) | |
tree | 26c784ea3d6546d762a96b131a2cf23cee9a9c38 /sway | |
parent | criteria & scratchpad verify if show in another workspace (#3522) (diff) | |
download | sway-cedde21c967ae5be0d1a9c7656ab8c6b3186ae42.tar.gz sway-cedde21c967ae5be0d1a9c7656ab8c6b3186ae42.tar.zst sway-cedde21c967ae5be0d1a9c7656ab8c6b3186ae42.zip |
Implement pointer-constraints-unstable-v1
Diffstat (limited to 'sway')
-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 |
4 files changed, 238 insertions, 23 deletions
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 | ||