Xi: hook up pointer emulation for emulating touches
Includes a hack for implicit grab activation, because integrating this requires a larger rewrite and I'm not sleeping enough as it is. Right now, we deliver the event and check before/after if there is an implicit grab on. If one activated, then store the event in the grab and switch the listener type to a grab listener. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Chase Douglas <chase.douglas@canonical.com> Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
This commit is contained in:
parent
753c4dca1e
commit
1894468c2b
177
Xi/exevents.c
177
Xi/exevents.c
|
@ -1203,6 +1203,153 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
|
||||||
|
TouchListener *listener, ClientPtr client,
|
||||||
|
WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
|
||||||
|
{
|
||||||
|
InternalEvent motion, button;
|
||||||
|
InternalEvent *ptrev = &motion;
|
||||||
|
int nevents;
|
||||||
|
DeviceIntPtr kbd;
|
||||||
|
|
||||||
|
/* We don't deliver pointer events to non-owners */
|
||||||
|
if (!TouchResourceIsOwner(ti, listener->listener))
|
||||||
|
return Success;
|
||||||
|
|
||||||
|
nevents = TouchConvertToPointerEvent(ev, &motion, &button);
|
||||||
|
BUG_WARN(nevents == 0);
|
||||||
|
if (nevents == 0)
|
||||||
|
return BadValue;
|
||||||
|
|
||||||
|
if (nevents > 1)
|
||||||
|
ptrev = &button;
|
||||||
|
|
||||||
|
kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
|
||||||
|
event_set_state(dev, kbd, &ptrev->device_event);
|
||||||
|
ptrev->device_event.corestate = event_get_corestate(dev, kbd);
|
||||||
|
|
||||||
|
if (grab)
|
||||||
|
{
|
||||||
|
/* this side-steps the usual activation mechansims, but... */
|
||||||
|
if (ev->any.type == ET_TouchBegin)
|
||||||
|
ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
|
||||||
|
else {
|
||||||
|
int deliveries = 0;
|
||||||
|
/* 'grab' is the passive grab, but if the grab isn't active,
|
||||||
|
* don't deliver */
|
||||||
|
if (!dev->deviceGrab.grab)
|
||||||
|
return Success;
|
||||||
|
|
||||||
|
if (grab->ownerEvents)
|
||||||
|
{
|
||||||
|
WindowPtr focus = NullWindow;
|
||||||
|
WindowPtr win = dev->spriteInfo->sprite->win;
|
||||||
|
deliveries = DeliverDeviceEvents(win, ptrev, grab, focus, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deliveries)
|
||||||
|
DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
|
||||||
|
|
||||||
|
if (ev->any.type == ET_TouchEnd &&
|
||||||
|
!dev->button->buttonsDown &&
|
||||||
|
dev->deviceGrab.fromPassiveGrab &&
|
||||||
|
GrabIsPointerGrab(grab))
|
||||||
|
(*dev->deviceGrab.DeactivateGrab)(dev);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
GrabPtr devgrab = dev->deviceGrab.grab;
|
||||||
|
|
||||||
|
DeliverDeviceEvents(win, ptrev, grab, win, dev);
|
||||||
|
/* FIXME: bad hack
|
||||||
|
* Implicit passive grab activated in response to this event. Store
|
||||||
|
* the event.
|
||||||
|
*/
|
||||||
|
if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab)
|
||||||
|
{
|
||||||
|
TouchListener *listener;
|
||||||
|
|
||||||
|
devgrab = dev->deviceGrab.grab;
|
||||||
|
|
||||||
|
*dev->deviceGrab.sync.event = ev->device_event;
|
||||||
|
|
||||||
|
/* The listener array has a sequence of grabs and then one event
|
||||||
|
* selection. Implicit grab activation occurs through delivering an
|
||||||
|
* event selection. Thus, we update the last listener in the array.
|
||||||
|
*/
|
||||||
|
listener = &ti->listeners[ti->num_listeners - 1];
|
||||||
|
listener->listener = devgrab->resource;
|
||||||
|
|
||||||
|
if (devgrab->grabtype != XI2 ||
|
||||||
|
devgrab->type != XI_TouchBegin)
|
||||||
|
listener->type = LISTENER_POINTER_GRAB;
|
||||||
|
else
|
||||||
|
listener->type = LISTENER_GRAB;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (ev->any.type == ET_TouchBegin)
|
||||||
|
listener->state = LISTENER_IS_OWNER;
|
||||||
|
else if (ev->any.type == ET_TouchEnd)
|
||||||
|
listener->state = LISTENER_HAS_END;
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
||||||
|
InternalEvent *ev)
|
||||||
|
{
|
||||||
|
InternalEvent motion;
|
||||||
|
|
||||||
|
if (ti->num_listeners)
|
||||||
|
{
|
||||||
|
ClientPtr client;
|
||||||
|
WindowPtr win;
|
||||||
|
GrabPtr grab;
|
||||||
|
XI2Mask *mask;
|
||||||
|
|
||||||
|
if (ti->listeners[0].type != LISTENER_POINTER_REGULAR ||
|
||||||
|
ti->listeners[0].type != LISTENER_POINTER_GRAB)
|
||||||
|
return;
|
||||||
|
|
||||||
|
motion = *ev;
|
||||||
|
motion.any.type = ET_TouchUpdate;
|
||||||
|
motion.device_event.detail.button = 0;
|
||||||
|
|
||||||
|
if (!RetrieveTouchDeliveryData(dev, ti, &motion,
|
||||||
|
&ti->listeners[0], &client, &win, &grab,
|
||||||
|
&mask))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* There may be a pointer grab on the device */
|
||||||
|
if (!grab)
|
||||||
|
{
|
||||||
|
grab = dev->deviceGrab.grab;
|
||||||
|
if (grab)
|
||||||
|
{
|
||||||
|
win = grab->window;
|
||||||
|
mask = grab->xi2mask;
|
||||||
|
client = rClient(grab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeliverTouchEmulatedEvent(dev, ti, &motion, &ti->listeners[0], client, win, grab, mask);
|
||||||
|
} else {
|
||||||
|
InternalEvent button;
|
||||||
|
int converted;
|
||||||
|
converted = TouchConvertToPointerEvent(ev, &motion, &button);
|
||||||
|
|
||||||
|
BUG_WARN(converted == 0);
|
||||||
|
if (converted)
|
||||||
|
ProcessOtherEvent(&motion, dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes and delivers a TouchBegin, TouchUpdate, or a
|
* Processes and delivers a TouchBegin, TouchUpdate, or a
|
||||||
* TouchEnd event.
|
* TouchEnd event.
|
||||||
|
@ -1241,6 +1388,12 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* if emulate_pointer is set, emulate the motion event right
|
||||||
|
* here, so we can ignore it for button event emulation. TouchUpdate
|
||||||
|
* events which _only_ emulate motion just work normally */
|
||||||
|
if (emulate_pointer && ev->any.type != ET_TouchUpdate)
|
||||||
|
DeliverEmulatedMotionEvent(dev, ti, ev);
|
||||||
if (emulate_pointer && IsMaster(dev))
|
if (emulate_pointer && IsMaster(dev))
|
||||||
CheckMotion(&ev->device_event, dev);
|
CheckMotion(&ev->device_event, dev);
|
||||||
|
|
||||||
|
@ -1436,6 +1589,15 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev
|
||||||
int rc = Success;
|
int rc = Success;
|
||||||
Bool has_ownershipmask;
|
Bool has_ownershipmask;
|
||||||
|
|
||||||
|
if (listener->type == LISTENER_POINTER_REGULAR ||
|
||||||
|
listener->type == LISTENER_POINTER_GRAB)
|
||||||
|
{
|
||||||
|
rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
|
||||||
|
grab, xi2mask);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
|
has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
|
||||||
|
|
||||||
if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
|
if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
|
||||||
|
@ -1454,6 +1616,7 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev
|
||||||
}
|
}
|
||||||
listener->state = state;
|
listener->state = state;
|
||||||
|
|
||||||
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,6 +1627,14 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
|
||||||
{
|
{
|
||||||
int rc = Success;
|
int rc = Success;
|
||||||
|
|
||||||
|
if (listener->type == LISTENER_POINTER_REGULAR ||
|
||||||
|
listener->type == LISTENER_POINTER_GRAB)
|
||||||
|
{
|
||||||
|
rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
|
||||||
|
grab, xi2mask);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Event in response to reject */
|
/* Event in response to reject */
|
||||||
if (ev->device_event.flags & TOUCH_REJECT)
|
if (ev->device_event.flags & TOUCH_REJECT)
|
||||||
{
|
{
|
||||||
|
@ -1488,6 +1659,7 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1517,7 +1689,10 @@ DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
|
||||||
rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
|
rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
|
||||||
} else if (ev->any.type == ET_TouchUpdate)
|
} else if (ev->any.type == ET_TouchUpdate)
|
||||||
{
|
{
|
||||||
if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
|
if (listener->type == LISTENER_POINTER_REGULAR ||
|
||||||
|
listener->type == LISTENER_POINTER_GRAB)
|
||||||
|
DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
|
||||||
|
else if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
|
||||||
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
|
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
|
||||||
} else if (ev->any.type == ET_TouchEnd)
|
} else if (ev->any.type == ET_TouchEnd)
|
||||||
rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
|
rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
|
||||||
|
|
Loading…
Reference in New Issue