xwayland: Implement the wl_touch interface
A DeviceIntPtr with touch valuators is also created in order to deliver the translated touch events. The lifetime of xwl_touch structs is tied to the wayland ones, finishing in either wl_touch.up() or wl_touch.cancel() Signed-off-by: Carlos Garnacho <carlosg@gnome.org> Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
This commit is contained in:
parent
d96eccc057
commit
b7cd48f71d
|
@ -148,6 +148,61 @@ xwl_keyboard_proc(DeviceIntPtr device, int what)
|
|||
return BadMatch;
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_touch_proc(DeviceIntPtr device, int what)
|
||||
{
|
||||
#define NTOUCHPOINTS 20
|
||||
#define NBUTTONS 1
|
||||
#define NAXES 2
|
||||
struct xwl_seat *xwl_seat = device->public.devicePrivate;
|
||||
Atom btn_labels[NBUTTONS] = { 0 };
|
||||
Atom axes_labels[NAXES] = { 0 };
|
||||
BYTE map[NBUTTONS + 1] = { 0 };
|
||||
|
||||
switch (what) {
|
||||
case DEVICE_INIT:
|
||||
device->public.on = FALSE;
|
||||
|
||||
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X);
|
||||
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y);
|
||||
|
||||
if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels,
|
||||
GetMotionHistorySize(), Absolute))
|
||||
return BadValue;
|
||||
|
||||
if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map))
|
||||
return BadValue;
|
||||
|
||||
if (!InitTouchClassDeviceStruct(device, NTOUCHPOINTS,
|
||||
XIDirectTouch, NAXES))
|
||||
return BadValue;
|
||||
|
||||
/* Valuators */
|
||||
/* FIXME: devices might be mapped to a single wl_output */
|
||||
InitValuatorAxisStruct(device, 0, axes_labels[0],
|
||||
0, xwl_seat->xwl_screen->width,
|
||||
10000, 0, 10000, Absolute);
|
||||
InitValuatorAxisStruct(device, 1, axes_labels[1],
|
||||
0, xwl_seat->xwl_screen->height,
|
||||
10000, 0, 10000, Absolute);
|
||||
return Success;
|
||||
|
||||
case DEVICE_ON:
|
||||
device->public.on = TRUE;
|
||||
return Success;
|
||||
|
||||
case DEVICE_OFF:
|
||||
case DEVICE_CLOSE:
|
||||
device->public.on = FALSE;
|
||||
return Success;
|
||||
}
|
||||
|
||||
return BadMatch;
|
||||
#undef NAXES
|
||||
#undef NBUTTONS
|
||||
#undef NTOUCHPOINTS
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_enter(void *data, struct wl_pointer *pointer,
|
||||
uint32_t serial, struct wl_surface *surface,
|
||||
|
@ -480,6 +535,129 @@ static const struct wl_keyboard_listener keyboard_listener = {
|
|||
keyboard_handle_repeat_info,
|
||||
};
|
||||
|
||||
static struct xwl_touch *
|
||||
xwl_seat_lookup_touch(struct xwl_seat *xwl_seat, int32_t id)
|
||||
{
|
||||
struct xwl_touch *xwl_touch, *next_xwl_touch;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
|
||||
&xwl_seat->touches, link_touch) {
|
||||
if (xwl_touch->id == id)
|
||||
return xwl_touch;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_touch_send_event(struct xwl_touch *xwl_touch,
|
||||
struct xwl_seat *xwl_seat, int type)
|
||||
{
|
||||
int32_t dx, dy;
|
||||
ValuatorMask mask;
|
||||
|
||||
dx = xwl_touch->window->window->drawable.x;
|
||||
dy = xwl_touch->window->window->drawable.y;
|
||||
|
||||
valuator_mask_zero(&mask);
|
||||
valuator_mask_set(&mask, 0, dx + xwl_touch->x);
|
||||
valuator_mask_set(&mask, 1, dy + xwl_touch->y);
|
||||
QueueTouchEvents(xwl_seat->touch, type, xwl_touch->id, 0, &mask);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_down(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t serial, uint32_t time,
|
||||
struct wl_surface *surface,
|
||||
int32_t id, wl_fixed_t sx_w, wl_fixed_t sy_w)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
struct xwl_touch *xwl_touch;
|
||||
|
||||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
xwl_touch = calloc(sizeof *xwl_touch, 1);
|
||||
if (xwl_touch == NULL) {
|
||||
ErrorF("touch_handle_down ENOMEM");
|
||||
return;
|
||||
}
|
||||
|
||||
xwl_touch->window = wl_surface_get_user_data(surface);
|
||||
xwl_touch->id = id;
|
||||
xwl_touch->x = wl_fixed_to_int(sx_w);
|
||||
xwl_touch->y = wl_fixed_to_int(sy_w);
|
||||
xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches);
|
||||
|
||||
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_up(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t serial, uint32_t time, int32_t id)
|
||||
{
|
||||
struct xwl_touch *xwl_touch;
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
|
||||
xwl_touch = xwl_seat_lookup_touch(xwl_seat, id);
|
||||
|
||||
if (!xwl_touch)
|
||||
return;
|
||||
|
||||
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchEnd);
|
||||
xorg_list_del(&xwl_touch->link_touch);
|
||||
free(xwl_touch);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_motion(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t time, int32_t id,
|
||||
wl_fixed_t sx_w, wl_fixed_t sy_w)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
struct xwl_touch *xwl_touch;
|
||||
|
||||
xwl_touch = xwl_seat_lookup_touch(xwl_seat, id);
|
||||
|
||||
if (!xwl_touch)
|
||||
return;
|
||||
|
||||
xwl_touch->x = wl_fixed_to_int(sx_w);
|
||||
xwl_touch->y = wl_fixed_to_int(sy_w);
|
||||
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_frame(void *data, struct wl_touch *wl_touch)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_cancel(void *data, struct wl_touch *wl_touch)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
struct xwl_touch *xwl_touch, *next_xwl_touch;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
|
||||
&xwl_seat->touches, link_touch) {
|
||||
/* We can't properly notify of cancellation to the X client
|
||||
* once it thinks it has the ownership, send at least a
|
||||
* TouchEnd event.
|
||||
*/
|
||||
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchEnd);
|
||||
xorg_list_del(&xwl_touch->link_touch);
|
||||
free(xwl_touch);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_touch_listener touch_listener = {
|
||||
touch_handle_down,
|
||||
touch_handle_up,
|
||||
touch_handle_motion,
|
||||
touch_handle_frame,
|
||||
touch_handle_cancel
|
||||
};
|
||||
|
||||
static DeviceIntPtr
|
||||
add_device(struct xwl_seat *xwl_seat,
|
||||
const char *driver, DeviceProc device_proc)
|
||||
|
@ -548,8 +726,26 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
|
|||
DisableDevice(xwl_seat->keyboard, TRUE);
|
||||
}
|
||||
|
||||
if (caps & WL_SEAT_CAPABILITY_TOUCH && xwl_seat->wl_touch == NULL) {
|
||||
xwl_seat->wl_touch = wl_seat_get_touch(seat);
|
||||
wl_touch_add_listener(xwl_seat->wl_touch,
|
||||
&touch_listener, xwl_seat);
|
||||
|
||||
if (xwl_seat->touch)
|
||||
EnableDevice(xwl_seat->touch, TRUE);
|
||||
else {
|
||||
xwl_seat->touch =
|
||||
add_device(xwl_seat, "xwayland-touch", xwl_touch_proc);
|
||||
}
|
||||
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && xwl_seat->wl_touch) {
|
||||
wl_touch_release(xwl_seat->wl_touch);
|
||||
xwl_seat->wl_touch = NULL;
|
||||
|
||||
if (xwl_seat->touch)
|
||||
DisableDevice(xwl_seat->touch, TRUE);
|
||||
}
|
||||
|
||||
xwl_seat->xwl_screen->expecting_event--;
|
||||
/* FIXME: Touch ... */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -116,10 +116,12 @@ struct xwl_touch {
|
|||
struct xwl_seat {
|
||||
DeviceIntPtr pointer;
|
||||
DeviceIntPtr keyboard;
|
||||
DeviceIntPtr touch;
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct wl_seat *seat;
|
||||
struct wl_pointer *wl_pointer;
|
||||
struct wl_keyboard *wl_keyboard;
|
||||
struct wl_touch *wl_touch;
|
||||
struct wl_array keys;
|
||||
struct xwl_window *focus_window;
|
||||
uint32_t id;
|
||||
|
|
Loading…
Reference in New Issue
Block a user