Implement seatop_touch

Atm we got issue with the touch position sent to the clients. While
holding contact, leaving the initial container will continue to send
motion event to the client but with the new local position from the new
container.

This seatop goal is to send the position of the touch event, relatively
to the initial container layout position.
This commit is contained in:
Stacy Harper 2021-08-21 16:04:08 +02:00 committed by Simon Zeni
parent 7d2e4a5106
commit 4666d1785b
6 changed files with 187 additions and 48 deletions

View file

@ -108,6 +108,10 @@ void cursor_unhide(struct sway_cursor *cursor);
int cursor_get_timeout(struct sway_cursor *cursor);
void cursor_notify_key_press(struct sway_cursor *cursor);
void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
struct wlr_input_device *device, double dx, double dy,
double dx_unaccel, double dy_unaccel);
void dispatch_cursor_button(struct sway_cursor *cursor,
struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
enum wlr_button_state state);

View file

@ -4,6 +4,7 @@
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_touch.h>
#include <wlr/util/edges.h>
#include "sway/config.h"
#include "sway/input/input-manager.h"
@ -36,6 +37,12 @@ struct sway_seatop_impl {
void (*swipe_end)(struct sway_seat *seat,
struct wlr_pointer_swipe_end_event *event);
void (*rebase)(struct sway_seat *seat, uint32_t time_msec);
void (*touch_motion)(struct sway_seat *seat,
struct wlr_touch_motion_event *event, double lx, double ly);
void (*touch_up)(struct sway_seat *seat,
struct wlr_touch_up_event *event);
void (*touch_down)(struct sway_seat *seat,
struct wlr_touch_down_event *event, double lx, double ly);
void (*tablet_tool_motion)(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec);
void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool,
@ -256,10 +263,13 @@ enum wlr_edges find_resize_edge(struct sway_container *cont,
void seatop_begin_default(struct sway_seat *seat);
void seatop_begin_down(struct sway_seat *seat, struct sway_container *con,
uint32_t time_msec, double sx, double sy);
double sx, double sy);
void seatop_begin_down_on_surface(struct sway_seat *seat,
struct wlr_surface *surface, uint32_t time_msec, double sx, double sy);
struct wlr_surface *surface, double sx, double sy);
void seatop_begin_touch_down(struct sway_seat *seat, struct wlr_surface *surface,
struct wlr_touch_down_event *event, double sx, double sy, double lx, double ly);
void seatop_begin_move_floating(struct sway_seat *seat,
struct sway_container *con);
@ -319,6 +329,15 @@ void seatop_swipe_update(struct sway_seat *seat,
void seatop_swipe_end(struct sway_seat *seat,
struct wlr_pointer_swipe_end_event *event);
void seatop_touch_motion(struct sway_seat *seat,
struct wlr_touch_motion_event *event, double lx, double ly);
void seatop_touch_up(struct sway_seat *seat,
struct wlr_touch_up_event *event);
void seatop_touch_down(struct sway_seat *seat,
struct wlr_touch_down_event *event, double lx, double ly);
void seatop_rebase(struct sway_seat *seat, uint32_t time_msec);
/**

View file

@ -364,7 +364,7 @@ void cursor_unhide(struct sway_cursor *cursor) {
wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor));
}
static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
struct wlr_input_device *device, double dx, double dy,
double dx_unaccel, double dy_unaccel) {
wlr_relative_pointer_manager_v1_send_relative_motion(
@ -479,43 +479,16 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {
cursor_hide(cursor);
struct sway_seat *seat = cursor->seat;
struct wlr_seat *wlr_seat = seat->wlr_seat;
struct wlr_surface *surface = NULL;
double lx, ly;
wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
event->x, event->y, &lx, &ly);
double sx, sy;
struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy);
seat->touch_id = event->touch_id;
seat->touch_x = lx;
seat->touch_y = ly;
if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) {
if (seat_is_input_allowed(seat, surface)) {
wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec,
event->touch_id, sx, sy);
if (focused_node) {
seat_set_focus(seat, focused_node);
}
}
} else if (!cursor->simulating_pointer_from_touch &&
(!surface || seat_is_input_allowed(seat, surface))) {
// Fallback to cursor simulation.
// The pointer_touch_id state is needed, so drags are not aborted when over
// a surface supporting touch and multi touch events don't interfere.
cursor->simulating_pointer_from_touch = true;
cursor->pointer_touch_id = seat->touch_id;
double dx, dy;
dx = lx - cursor->cursor->x;
dy = ly - cursor->cursor->y;
pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy,
dx, dy);
dispatch_cursor_button(cursor, &event->touch->base, event->time_msec,
BTN_LEFT, WLR_BUTTON_PRESSED);
}
seatop_touch_down(seat, event, lx, ly);
}
static void handle_touch_up(struct wl_listener *listener, void *data) {
@ -523,7 +496,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
struct wlr_touch_up_event *event = data;
cursor_handle_activity_from_device(cursor, &event->touch->base);
struct wlr_seat *wlr_seat = cursor->seat->wlr_seat;
struct sway_seat *seat = cursor->seat;
if (cursor->simulating_pointer_from_touch) {
if (cursor->pointer_touch_id == cursor->seat->touch_id) {
@ -532,7 +505,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED);
}
} else {
wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id);
seatop_touch_up(seat, event);
}
}
@ -543,19 +516,14 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
cursor_handle_activity_from_device(cursor, &event->touch->base);
struct sway_seat *seat = cursor->seat;
struct wlr_seat *wlr_seat = seat->wlr_seat;
struct wlr_surface *surface = NULL;
double lx, ly;
wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
event->x, event->y, &lx, &ly);
double sx, sy;
node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy);
if (seat->touch_id == event->touch_id) {
seat->touch_x = lx;
seat->touch_y = ly;
struct sway_drag_icon *drag_icon;
wl_list_for_each(drag_icon, &root->drag_icons, link) {
if (drag_icon->seat == seat) {
@ -572,9 +540,8 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
pointer_motion(cursor, event->time_msec, &event->touch->base,
dx, dy, dx, dy);
}
} else if (surface) {
wlr_seat_touch_notify_motion(wlr_seat, event->time_msec,
event->touch_id, sx, sy);
} else {
seatop_touch_motion(seat, event, lx, ly);
}
}

View file

@ -1618,6 +1618,26 @@ void seatop_pointer_axis(struct sway_seat *seat,
}
}
void seatop_touch_motion(struct sway_seat *seat, struct wlr_touch_motion_event *event,
double lx, double ly) {
if (seat->seatop_impl->touch_motion) {
seat->seatop_impl->touch_motion(seat, event, lx, ly);
}
}
void seatop_touch_up(struct sway_seat *seat, struct wlr_touch_up_event *event) {
if (seat->seatop_impl->touch_up) {
seat->seatop_impl->touch_up(seat, event);
}
}
void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *event,
double lx, double ly) {
if (seat->seatop_impl->touch_down) {
seat->seatop_impl->touch_down(seat, event, lx, ly);
}
}
void seatop_tablet_tool_tip(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec,
enum wlr_tablet_tool_tip_state state) {

View file

@ -261,7 +261,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
// Handle tapping on a container surface
seat_set_focus_container(seat, cont);
seatop_begin_down(seat, node->sway_container, time_msec, sx, sy);
seatop_begin_down(seat, node->sway_container, sx, sy);
}
#if HAVE_XWAYLAND
// Handle tapping on an xwayland unmanaged view
@ -374,7 +374,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
transaction_commit_dirty();
}
if (state == WLR_BUTTON_PRESSED) {
seatop_begin_down_on_surface(seat, surface, time_msec, sx, sy);
seatop_begin_down_on_surface(seat, surface, sx, sy);
}
seat_pointer_notify_button(seat, time_msec, button, state);
return;
@ -499,7 +499,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
// Handle mousedown on a container surface
if (surface && cont && state == WLR_BUTTON_PRESSED) {
seatop_begin_down(seat, cont, time_msec, sx, sy);
seatop_begin_down(seat, cont, sx, sy);
seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED);
return;
}
@ -649,6 +649,36 @@ static void handle_tablet_tool_motion(struct sway_seat *seat,
e->previous_node = node;
}
static void handle_touch_down(struct sway_seat *seat,
struct wlr_touch_down_event *event, double lx, double ly) {
struct wlr_surface *surface = NULL;
struct wlr_seat *wlr_seat = seat->wlr_seat;
struct sway_cursor *cursor = seat->cursor;
double sx, sy;
node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy);
if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) {
if (seat_is_input_allowed(seat, surface)) {
cursor->simulating_pointer_from_touch = false;
seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly);
}
} else if (!cursor->simulating_pointer_from_touch &&
(!surface || seat_is_input_allowed(seat, surface))) {
// Fallback to cursor simulation.
// The pointer_touch_id state is needed, so drags are not aborted when over
// a surface supporting touch and multi touch events don't interfere.
cursor->simulating_pointer_from_touch = true;
cursor->pointer_touch_id = seat->touch_id;
double dx, dy;
dx = seat->touch_x - cursor->cursor->x;
dy = seat->touch_y - cursor->cursor->y;
pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy,
dx, dy);
dispatch_cursor_button(cursor, &event->touch->base, event->time_msec,
BTN_LEFT, WLR_BUTTON_PRESSED);
}
}
/*----------------------------------------\
* Functions used by handle_pointer_axis /
*--------------------------------------*/
@ -1096,6 +1126,7 @@ static const struct sway_seatop_impl seatop_impl = {
.swipe_begin = handle_swipe_begin,
.swipe_update = handle_swipe_update,
.swipe_end = handle_swipe_end,
.touch_down = handle_touch_down,
.rebase = handle_rebase,
.allow_set_cursor = true,
};

View file

@ -2,12 +2,20 @@
#include <float.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_tablet_v2.h>
#include <wlr/types/wlr_touch.h>
#include "sway/input/cursor.h"
#include "sway/input/seat.h"
#include "sway/tree/view.h"
#include "sway/desktop/transaction.h"
#include "log.h"
struct seatop_touch_point_event {
double ref_lx, ref_ly; // touch's x/y at start of op
double ref_con_lx, ref_con_ly; // container's x/y at start of op
int32_t touch_id;
struct wl_list link;
};
struct seatop_down_event {
struct sway_container *con;
struct sway_seat *seat;
@ -15,8 +23,87 @@ struct seatop_down_event {
struct wlr_surface *surface;
double ref_lx, ref_ly; // cursor's x/y at start of op
double ref_con_lx, ref_con_ly; // container's x/y at start of op
struct wl_list point_events; // seatop_touch_point_event::link
};
static void handle_touch_motion(struct sway_seat *seat,
struct wlr_touch_motion_event *event, double lx, double ly) {
struct seatop_down_event *e = seat->seatop_data;
struct seatop_touch_point_event *point_event;
bool found = false;
wl_list_for_each(point_event, &e->point_events, link) {
if (point_event->touch_id == event->touch_id) {
found = true;
break;
}
}
if (!found) {
return; // Probably not a point_event from this seatop_down
}
double moved_x = lx - point_event->ref_lx;
double moved_y = ly - point_event->ref_ly;
double sx = point_event->ref_con_lx + moved_x;
double sy = point_event->ref_con_ly + moved_y;
wlr_seat_touch_notify_motion(seat->wlr_seat, event->time_msec,
event->touch_id, sx, sy);
}
static void handle_touch_up(struct sway_seat *seat,
struct wlr_touch_up_event *event) {
struct seatop_down_event *e = seat->seatop_data;
struct seatop_touch_point_event *point_event, *tmp;
wl_list_for_each_safe(point_event, tmp, &e->point_events, link) {
if (point_event->touch_id == event->touch_id) {
wl_list_remove(&point_event->link);
free(point_event);
break;
}
}
if (wl_list_empty(&e->point_events)) {
seatop_begin_default(seat);
}
wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id);
}
static void handle_touch_down(struct sway_seat *seat,
struct wlr_touch_down_event *event, double lx, double ly) {
struct seatop_down_event *e = seat->seatop_data;
double sx, sy;
struct wlr_surface *surface = NULL;
struct sway_node *focused_node = node_at_coords(seat, seat->touch_x,
seat->touch_y, &surface, &sx, &sy);
if (!surface || surface != e->surface) { // Must start from the initial surface
return;
}
struct seatop_touch_point_event *point_event =
calloc(1, sizeof(struct seatop_touch_point_event));
if (!sway_assert(point_event, "Unable to allocate point_event")) {
return;
}
point_event->touch_id = event->touch_id;
point_event->ref_lx = lx;
point_event->ref_ly = ly;
point_event->ref_con_lx = sx;
point_event->ref_con_ly = sy;
wl_list_insert(&e->point_events, &point_event->link);
wlr_seat_touch_notify_down(seat->wlr_seat, surface, event->time_msec,
event->touch_id, sx, sy);
if (focused_node) {
seat_set_focus(seat, focused_node);
}
}
static void handle_pointer_axis(struct sway_seat *seat,
struct wlr_pointer_axis_event *event) {
struct sway_input_device *input_device =
@ -99,14 +186,17 @@ static const struct sway_seatop_impl seatop_impl = {
.pointer_axis = handle_pointer_axis,
.tablet_tool_tip = handle_tablet_tool_tip,
.tablet_tool_motion = handle_tablet_tool_motion,
.touch_motion = handle_touch_motion,
.touch_up = handle_touch_up,
.touch_down = handle_touch_down,
.unref = handle_unref,
.end = handle_end,
.allow_set_cursor = true,
};
void seatop_begin_down(struct sway_seat *seat, struct sway_container *con,
uint32_t time_msec, double sx, double sy) {
seatop_begin_down_on_surface(seat, con->view->surface, time_msec, sx, sy);
double sx, double sy) {
seatop_begin_down_on_surface(seat, con->view->surface, sx, sy);
struct seatop_down_event *e = seat->seatop_data;
e->con = con;
@ -114,13 +204,20 @@ void seatop_begin_down(struct sway_seat *seat, struct sway_container *con,
transaction_commit_dirty();
}
void seatop_begin_touch_down(struct sway_seat *seat,
struct wlr_surface *surface, struct wlr_touch_down_event *event,
double sx, double sy, double lx, double ly) {
seatop_begin_down_on_surface(seat, surface, sx, sy);
handle_touch_down(seat, event, lx, ly);
}
void seatop_begin_down_on_surface(struct sway_seat *seat,
struct wlr_surface *surface, uint32_t time_msec, double sx, double sy) {
struct wlr_surface *surface, double sx, double sy) {
seatop_end(seat);
struct seatop_down_event *e =
calloc(1, sizeof(struct seatop_down_event));
if (!e) {
if (!sway_assert(e, "Unable to allocate e")) {
return;
}
e->con = NULL;
@ -132,6 +229,7 @@ void seatop_begin_down_on_surface(struct sway_seat *seat,
e->ref_ly = seat->cursor->cursor->y;
e->ref_con_lx = sx;
e->ref_con_ly = sy;
wl_list_init(&e->point_events);
seat->seatop_impl = &seatop_impl;
seat->seatop_data = e;