diff options
author | Tudor Brindus <me@tbrindus.ca> | 2020-05-04 17:34:28 -0400 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2020-05-25 10:01:00 +0200 |
commit | 5d13f647f9384e59012c0f829651911564bb5365 (patch) | |
tree | b768fac3dac8328d1efc7c9b4e96aa461ab7c9a5 | |
parent | common/log: use bright black rather than black for SWAY_DEBUG (diff) | |
download | sway-5d13f647f9384e59012c0f829651911564bb5365.tar.gz sway-5d13f647f9384e59012c0f829651911564bb5365.tar.zst sway-5d13f647f9384e59012c0f829651911564bb5365.zip |
input/tablet: add seatop_down entry for tablet input
Currently, when tablet input exits a window during an implicit grab, it
passes focus to another window.
For instance, this is problematic when trying to drag a scrollbar, and
exiting the window — the scrollbar motion stops. Additionally,
without `focus_follows_mouse no`, the tablet passes focus to whatever
surface it goes over regardless of if there is an active implicit.
If the tablet is over a surface that does not bind tablet handlers, sway
will fall back to pointer emulation, and all of this works fine. It
probably should have consistent behavior between emulated and
not-emulated input, though.
This commit adds a condition for entering seatop_down when a tablet's
tool tip goes down, and exiting when it goes up. Since events won't be
routed through seatop_default, this prevents windows losing focus during
implicit grabs.
Closes #5302.
-rw-r--r-- | include/sway/input/seat.h | 6 | ||||
-rw-r--r-- | sway/input/cursor.c | 16 | ||||
-rw-r--r-- | sway/input/seat.c | 8 | ||||
-rw-r--r-- | sway/input/seatop_default.c | 20 | ||||
-rw-r--r-- | sway/input/seatop_down.c | 24 |
5 files changed, 73 insertions, 1 deletions
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 66f8f7e4..e313a206 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -23,6 +23,8 @@ struct sway_seatop_impl { | |||
23 | void (*rebase)(struct sway_seat *seat, uint32_t time_msec); | 23 | void (*rebase)(struct sway_seat *seat, uint32_t time_msec); |
24 | void (*tablet_tool_motion)(struct sway_seat *seat, | 24 | void (*tablet_tool_motion)(struct sway_seat *seat, |
25 | struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); | 25 | struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); |
26 | void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool, | ||
27 | uint32_t time_msec, enum wlr_tablet_tool_tip_state state); | ||
26 | void (*end)(struct sway_seat *seat); | 28 | void (*end)(struct sway_seat *seat); |
27 | void (*unref)(struct sway_seat *seat, struct sway_container *con); | 29 | void (*unref)(struct sway_seat *seat, struct sway_container *con); |
28 | void (*render)(struct sway_seat *seat, struct sway_output *output, | 30 | void (*render)(struct sway_seat *seat, struct sway_output *output, |
@@ -269,6 +271,10 @@ void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec, | |||
269 | void seatop_pointer_axis(struct sway_seat *seat, | 271 | void seatop_pointer_axis(struct sway_seat *seat, |
270 | struct wlr_event_pointer_axis *event); | 272 | struct wlr_event_pointer_axis *event); |
271 | 273 | ||
274 | void seatop_tablet_tool_tip(struct sway_seat *seat, | ||
275 | struct sway_tablet_tool *tool, uint32_t time_msec, | ||
276 | enum wlr_tablet_tool_tip_state state); | ||
277 | |||
272 | void seatop_tablet_tool_motion(struct sway_seat *seat, | 278 | void seatop_tablet_tool_motion(struct sway_seat *seat, |
273 | struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); | 279 | struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); |
274 | 280 | ||
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 8121cc84..8de7d950 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -572,7 +572,19 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, | |||
572 | struct sway_seat *seat = cursor->seat; | 572 | struct sway_seat *seat = cursor->seat; |
573 | node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | 573 | node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); |
574 | 574 | ||
575 | if (surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) { | 575 | // The logic for whether we should send a tablet event or an emulated pointer |
576 | // event is tricky. It comes down to: | ||
577 | // * If we began a drag on a non-tablet surface (simulated_tool_tip_down), | ||
578 | // then we should continue sending emulated pointer events regardless of | ||
579 | // whether the surface currently under us accepts tablet or not. | ||
580 | // * Otherwise, if we are over a surface that accepts tablet, then we should | ||
581 | // send tablet events. | ||
582 | // * If we began a drag over a tablet surface, we should continue sending | ||
583 | // tablet events until the drag is released, even if we are now over a | ||
584 | // non-tablet surface. | ||
585 | if (!cursor->simulated_tool_tip_down && | ||
586 | ((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) || | ||
587 | wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) { | ||
576 | seatop_tablet_tool_motion(seat, tool, time_msec, dx, dy); | 588 | seatop_tablet_tool_motion(seat, tool, time_msec, dx, dy); |
577 | } else { | 589 | } else { |
578 | wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); | 590 | wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); |
@@ -680,6 +692,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
680 | 692 | ||
681 | wlr_tablet_v2_tablet_tool_notify_up(sway_tool->tablet_v2_tool); | 693 | wlr_tablet_v2_tablet_tool_notify_up(sway_tool->tablet_v2_tool); |
682 | } | 694 | } |
695 | |||
696 | seatop_tablet_tool_tip(seat, sway_tool, event->time_msec, event->state); | ||
683 | } | 697 | } |
684 | 698 | ||
685 | static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor, | 699 | static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor, |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 233267e0..e5f15613 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1471,6 +1471,14 @@ void seatop_pointer_axis(struct sway_seat *seat, | |||
1471 | } | 1471 | } |
1472 | } | 1472 | } |
1473 | 1473 | ||
1474 | void seatop_tablet_tool_tip(struct sway_seat *seat, | ||
1475 | struct sway_tablet_tool *tool, uint32_t time_msec, | ||
1476 | enum wlr_tablet_tool_tip_state state) { | ||
1477 | if (seat->seatop_impl->tablet_tool_tip) { | ||
1478 | seat->seatop_impl->tablet_tool_tip(seat, tool, time_msec, state); | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1474 | void seatop_tablet_tool_motion(struct sway_seat *seat, | 1482 | void seatop_tablet_tool_motion(struct sway_seat *seat, |
1475 | struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { | 1483 | struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { |
1476 | if (seat->seatop_impl->tablet_tool_motion) { | 1484 | if (seat->seatop_impl->tablet_tool_motion) { |
diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 64a17157..32c7318b 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c | |||
@@ -198,6 +198,25 @@ static void state_add_button(struct seatop_default_event *e, uint32_t button) { | |||
198 | * Functions used by handle_button / | 198 | * Functions used by handle_button / |
199 | *--------------------------------*/ | 199 | *--------------------------------*/ |
200 | 200 | ||
201 | static void handle_tablet_tool_tip(struct sway_seat *seat, | ||
202 | struct sway_tablet_tool *tool, uint32_t time_msec, | ||
203 | enum wlr_tablet_tool_tip_state state) { | ||
204 | if (state != WLR_TABLET_TOOL_TIP_DOWN) { | ||
205 | return; | ||
206 | } | ||
207 | |||
208 | struct sway_cursor *cursor = seat->cursor; | ||
209 | |||
210 | struct wlr_surface *surface = NULL; | ||
211 | double sx, sy; | ||
212 | struct sway_node *node = node_at_coords(seat, | ||
213 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | ||
214 | |||
215 | if (surface && node && node->type == N_CONTAINER) { | ||
216 | seatop_begin_down(seat, node->sway_container, time_msec, sx, sy); | ||
217 | } | ||
218 | } | ||
219 | |||
201 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 220 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
202 | struct wlr_input_device *device, uint32_t button, | 221 | struct wlr_input_device *device, uint32_t button, |
203 | enum wlr_button_state state) { | 222 | enum wlr_button_state state) { |
@@ -649,6 +668,7 @@ static const struct sway_seatop_impl seatop_impl = { | |||
649 | .button = handle_button, | 668 | .button = handle_button, |
650 | .pointer_motion = handle_pointer_motion, | 669 | .pointer_motion = handle_pointer_motion, |
651 | .pointer_axis = handle_pointer_axis, | 670 | .pointer_axis = handle_pointer_axis, |
671 | .tablet_tool_tip = handle_tablet_tool_tip, | ||
652 | .tablet_tool_motion = handle_tablet_tool_motion, | 672 | .tablet_tool_motion = handle_tablet_tool_motion, |
653 | .rebase = handle_rebase, | 673 | .rebase = handle_rebase, |
654 | .allow_set_cursor = true, | 674 | .allow_set_cursor = true, |
diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 358d5c59..dd8be6bf 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <float.h> | 2 | #include <float.h> |
3 | #include <wlr/types/wlr_cursor.h> | 3 | #include <wlr/types/wlr_cursor.h> |
4 | #include <wlr/types/wlr_tablet_v2.h> | ||
4 | #include "sway/input/cursor.h" | 5 | #include "sway/input/cursor.h" |
5 | #include "sway/input/seat.h" | 6 | #include "sway/input/seat.h" |
6 | #include "sway/tree/view.h" | 7 | #include "sway/tree/view.h" |
@@ -49,6 +50,27 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, | |||
49 | } | 50 | } |
50 | } | 51 | } |
51 | 52 | ||
53 | static void handle_tablet_tool_tip(struct sway_seat *seat, | ||
54 | struct sway_tablet_tool *tool, uint32_t time_msec, | ||
55 | enum wlr_tablet_tool_tip_state state) { | ||
56 | if (state == WLR_TABLET_TOOL_TIP_UP) { | ||
57 | seatop_begin_default(seat); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static void handle_tablet_tool_motion(struct sway_seat *seat, | ||
62 | struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { | ||
63 | struct seatop_down_event *e = seat->seatop_data; | ||
64 | struct sway_container *con = e->con; | ||
65 | if (seat_is_input_allowed(seat, con->view->surface)) { | ||
66 | double moved_x = seat->cursor->cursor->x - e->ref_lx; | ||
67 | double moved_y = seat->cursor->cursor->y - e->ref_ly; | ||
68 | double sx = e->ref_con_lx + moved_x; | ||
69 | double sy = e->ref_con_ly + moved_y; | ||
70 | wlr_tablet_v2_tablet_tool_notify_motion(tool->tablet_v2_tool, sx, sy); | ||
71 | } | ||
72 | } | ||
73 | |||
52 | static void handle_unref(struct sway_seat *seat, struct sway_container *con) { | 74 | static void handle_unref(struct sway_seat *seat, struct sway_container *con) { |
53 | struct seatop_down_event *e = seat->seatop_data; | 75 | struct seatop_down_event *e = seat->seatop_data; |
54 | if (e->con == con) { | 76 | if (e->con == con) { |
@@ -60,6 +82,8 @@ static const struct sway_seatop_impl seatop_impl = { | |||
60 | .button = handle_button, | 82 | .button = handle_button, |
61 | .pointer_motion = handle_pointer_motion, | 83 | .pointer_motion = handle_pointer_motion, |
62 | .pointer_axis = handle_pointer_axis, | 84 | .pointer_axis = handle_pointer_axis, |
85 | .tablet_tool_tip = handle_tablet_tool_tip, | ||
86 | .tablet_tool_motion = handle_tablet_tool_motion, | ||
63 | .unref = handle_unref, | 87 | .unref = handle_unref, |
64 | .allow_set_cursor = true, | 88 | .allow_set_cursor = true, |
65 | }; | 89 | }; |