Process and deliver touch events
Does not include pointer emulation handling. Does include partial ownership handling but not the actual processing of ownership events. Note: this commit is a retroactive commit extracted from a series of ~50 commits and may thus appear a bit more complicated than what you'd write out from scratch. Pointer processing tree is roughly: - ProcessOtherEvents - ProcessTouchEvents - DeliverTouchEvents - DeliverTouchBeginEvent|DeliverTouchEndEvent|... - DeliverOneTouchEvent Also hooks up the event history playing to the right function now. Co-authored-by: Daniel Stone <daniel@fooishbar.org> Co-authored-by: Chase Douglas <chase.douglas@canonical.com> 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
634b0da9a8
commit
e389a19a73
401
Xi/exevents.c
401
Xi/exevents.c
|
@ -104,6 +104,7 @@ SOFTWARE.
|
||||||
#include "eventconvert.h"
|
#include "eventconvert.h"
|
||||||
#include "eventstr.h"
|
#include "eventstr.h"
|
||||||
#include "inpututils.h"
|
#include "inpututils.h"
|
||||||
|
#include "mi.h"
|
||||||
|
|
||||||
#include <X11/extensions/XKBproto.h>
|
#include <X11/extensions/XKBproto.h>
|
||||||
#include "xkbsrv.h"
|
#include "xkbsrv.h"
|
||||||
|
@ -1013,6 +1014,258 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
|
||||||
return DEFAULT;
|
return DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A client that does not have the TouchOwnership mask set may not receive a
|
||||||
|
* TouchBegin event if there is at least one grab active.
|
||||||
|
*
|
||||||
|
* @return TRUE if the client selected for ownership events on the given
|
||||||
|
* window for this device, FALSE otherwise
|
||||||
|
*/
|
||||||
|
static inline Bool
|
||||||
|
TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev, WindowPtr win)
|
||||||
|
{
|
||||||
|
InputClients *iclient;
|
||||||
|
|
||||||
|
nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next)
|
||||||
|
{
|
||||||
|
if (rClient(iclient) != client)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason, XID resource)
|
||||||
|
{
|
||||||
|
int nev, i;
|
||||||
|
InternalEvent *tel = InitEventList(GetMaximumEventsNum());
|
||||||
|
|
||||||
|
nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
|
||||||
|
for (i = 0; i < nev; i++)
|
||||||
|
mieqProcessDeviceEvent(dev, tel + i, NULL);
|
||||||
|
|
||||||
|
FreeEventList(tel, GetMaximumEventsNum());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to deliver a touch event to the given client.
|
||||||
|
*/
|
||||||
|
static Bool
|
||||||
|
DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
|
||||||
|
GrabPtr grab, WindowPtr win, InternalEvent *ev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
xEvent *xi2;
|
||||||
|
Mask filter;
|
||||||
|
Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
|
||||||
|
|
||||||
|
/* FIXME: owner event handling */
|
||||||
|
|
||||||
|
/* If the client does not have the ownership mask set and is not
|
||||||
|
* the current owner of the touch, only pretend we delivered */
|
||||||
|
if (!grab && ti->num_grabs != 0 &&
|
||||||
|
!TouchClientWantsOwnershipEvents(client, dev,win))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* If we fail here, we're going to leave a client hanging. */
|
||||||
|
err = EventToXI2(ev, &xi2);
|
||||||
|
if (err != Success)
|
||||||
|
FatalError("[Xi] %s: XI2 conversion failed in %s"
|
||||||
|
" (%d)\n", dev->name, __func__, err);
|
||||||
|
|
||||||
|
FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
|
||||||
|
filter = GetEventFilter(dev, xi2);
|
||||||
|
if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
|
||||||
|
return FALSE;
|
||||||
|
err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
|
||||||
|
free(xi2);
|
||||||
|
|
||||||
|
/* Returning the value from TryClientEvents isn't useful, since all our
|
||||||
|
* resource-gone cleanups will update the delivery list anyway. */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the event's valuator information into the touchpoint, we may need
|
||||||
|
* this for emulated TouchEnd events.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
|
||||||
|
if (BitIsOn(ev->valuators.mask, i))
|
||||||
|
valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a touch event and a potential listener, retrieve info needed for
|
||||||
|
* processing the event.
|
||||||
|
*
|
||||||
|
* @param dev The device generating the touch event.
|
||||||
|
* @param ti The touch point info record for the touch event.
|
||||||
|
* @param ev The touch event to process.
|
||||||
|
* @param listener The touch event listener that may receive the touch event.
|
||||||
|
* @param[out] client The client that should receive the touch event.
|
||||||
|
* @param[out] win The window to deliver the event on.
|
||||||
|
* @param[out] grab The grab to deliver the event through, if any.
|
||||||
|
* @param[out] mask The XI 2.x event mask of the grab or selection, if any.
|
||||||
|
* @return TRUE if an event should be delivered to the listener, FALSE
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
static Bool
|
||||||
|
RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
||||||
|
InternalEvent *ev, TouchListener *listener,
|
||||||
|
ClientPtr *client, WindowPtr *win, GrabPtr *grab,
|
||||||
|
XI2Mask **mask)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
InputClients *iclients = NULL;
|
||||||
|
|
||||||
|
if (listener->type == LISTENER_GRAB ||
|
||||||
|
listener->type == LISTENER_POINTER_GRAB)
|
||||||
|
{
|
||||||
|
rc = dixLookupResourceByType((pointer*)grab, listener->listener,
|
||||||
|
RT_PASSIVEGRAB,
|
||||||
|
serverClient, DixSendAccess);
|
||||||
|
if (rc != Success)
|
||||||
|
{
|
||||||
|
/* the grab doesn't exist but we have a grabbing listener - this
|
||||||
|
* is an implicit/active grab */
|
||||||
|
rc = dixLookupClient(client, listener->listener, serverClient, DixSendAccess);
|
||||||
|
if (rc != Success)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*grab = dev->deviceGrab.grab;
|
||||||
|
if (!*grab)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*client = rClient(*grab);
|
||||||
|
*win = (*grab)->window;
|
||||||
|
*mask = (*grab)->xi2mask;
|
||||||
|
} else {
|
||||||
|
if (listener->level == CORE)
|
||||||
|
rc = dixLookupWindow(win, listener->listener,
|
||||||
|
serverClient, DixSendAccess);
|
||||||
|
else
|
||||||
|
rc = dixLookupResourceByType((pointer*)win, listener->listener,
|
||||||
|
RT_INPUTCLIENT,
|
||||||
|
serverClient, DixSendAccess);
|
||||||
|
if (rc != Success)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
if (listener->level == XI2)
|
||||||
|
{
|
||||||
|
int evtype;
|
||||||
|
if (ti->emulate_pointer && listener->type == LISTENER_POINTER_REGULAR)
|
||||||
|
evtype = GetXI2Type(TouchGetPointerEventType(ev));
|
||||||
|
else
|
||||||
|
evtype = GetXI2Type(ev->any.type);
|
||||||
|
|
||||||
|
nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
|
||||||
|
if (xi2mask_isset(iclients->xi2mask, dev, evtype))
|
||||||
|
break;
|
||||||
|
BUG_WARN(!iclients);
|
||||||
|
if (!iclients)
|
||||||
|
return FALSE;
|
||||||
|
} else if (listener->level == XI)
|
||||||
|
{
|
||||||
|
int xi_type = GetXIType(TouchGetPointerEventType(ev));
|
||||||
|
Mask xi_filter = event_get_filter_from_type(dev, xi_type);
|
||||||
|
nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
|
||||||
|
if (iclients->mask[dev->id] & xi_filter)
|
||||||
|
break;
|
||||||
|
BUG_WARN(!iclients);
|
||||||
|
if (!iclients)
|
||||||
|
return FALSE;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
int coretype = GetCoreType(TouchGetPointerEventType(ev));
|
||||||
|
Mask core_filter = event_get_filter_from_type(dev, coretype);
|
||||||
|
|
||||||
|
/* all others */
|
||||||
|
nt_list_for_each_entry(iclients, (InputClients*)wOtherClients(*win), next)
|
||||||
|
if (iclients->mask[XIAllDevices] & core_filter)
|
||||||
|
break;
|
||||||
|
/* if owner selected, iclients is NULL */
|
||||||
|
}
|
||||||
|
|
||||||
|
*client = iclients ? rClient(iclients) : wClient(*win);
|
||||||
|
*mask = iclients ? iclients->xi2mask : NULL;
|
||||||
|
*grab = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes and delivers a TouchBegin, TouchUpdate, or a
|
||||||
|
* TouchEnd event.
|
||||||
|
*
|
||||||
|
* Due to having rather different delivery semantics (see the Xi 2.2 protocol
|
||||||
|
* spec for more information), this implements its own grab and event-selection
|
||||||
|
* delivery logic.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
|
||||||
|
{
|
||||||
|
TouchClassPtr t = dev->touch;
|
||||||
|
TouchPointInfoPtr ti;
|
||||||
|
uint32_t touchid;
|
||||||
|
int type = ev->any.type;
|
||||||
|
int emulate_pointer = !!(ev->device_event.flags & TOUCH_POINTER_EMULATED);
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ev->any.type == ET_TouchOwnership)
|
||||||
|
touchid = ev->touch_ownership_event.touchid;
|
||||||
|
else
|
||||||
|
touchid = ev->device_event.touchid;
|
||||||
|
|
||||||
|
if (type == ET_TouchBegin) {
|
||||||
|
ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
|
||||||
|
emulate_pointer);
|
||||||
|
} else
|
||||||
|
ti = TouchFindByClientID(dev, touchid);
|
||||||
|
|
||||||
|
if (!ti)
|
||||||
|
{
|
||||||
|
DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
|
||||||
|
dev->name, type, touchid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emulate_pointer && IsMaster(dev))
|
||||||
|
CheckMotion(&ev->device_event, dev);
|
||||||
|
|
||||||
|
/* Make sure we have a valid window trace for event delivery; must be
|
||||||
|
* called after event type mutation. */
|
||||||
|
/* FIXME: check this */
|
||||||
|
if (!TouchEnsureSprite(dev, ti, ev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* TouchOwnership events are handled separately from the rest, as they
|
||||||
|
* have more complex semantics. */
|
||||||
|
if (ev->any.type == ET_TouchOwnership)
|
||||||
|
/* FIXME: process me! */;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TouchCopyValuatorData(&ev->device_event, ti);
|
||||||
|
/* WARNING: the event type may change to TouchUpdate in
|
||||||
|
* DeliverTouchEvents if a TouchEnd was delivered to a grabbing
|
||||||
|
* owner */
|
||||||
|
DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0);
|
||||||
|
if (ev->any.type == ET_TouchEnd)
|
||||||
|
TouchEndTouch(dev, ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process DeviceEvents and DeviceChangedEvents.
|
* Process DeviceEvents and DeviceChangedEvents.
|
||||||
|
@ -1162,12 +1415,160 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
|
||||||
case ET_RawTouchEnd:
|
case ET_RawTouchEnd:
|
||||||
DeliverRawEvent(&ev->raw_event, device);
|
DeliverRawEvent(&ev->raw_event, device);
|
||||||
break;
|
break;
|
||||||
|
case ET_TouchBegin:
|
||||||
|
case ET_TouchUpdate:
|
||||||
|
case ET_TouchOwnership:
|
||||||
|
case ET_TouchEnd:
|
||||||
|
ProcessTouchEvent(ev, device);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ProcessDeviceEvent(ev, device);
|
ProcessDeviceEvent(ev, device);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
|
||||||
|
TouchListener *listener, ClientPtr client,
|
||||||
|
WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
|
||||||
|
{
|
||||||
|
enum TouchListenerState state;
|
||||||
|
int rc = Success;
|
||||||
|
Bool has_ownershipmask;
|
||||||
|
|
||||||
|
has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
|
||||||
|
|
||||||
|
if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
|
||||||
|
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
|
||||||
|
if (!TouchResourceIsOwner(ti, listener->listener))
|
||||||
|
{
|
||||||
|
if (has_ownershipmask)
|
||||||
|
state = LISTENER_AWAITING_OWNER;
|
||||||
|
else
|
||||||
|
state = LISTENER_AWAITING_BEGIN;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (has_ownershipmask)
|
||||||
|
TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
|
||||||
|
state = LISTENER_IS_OWNER;
|
||||||
|
}
|
||||||
|
listener->state = state;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
|
||||||
|
TouchListener *listener, ClientPtr client,
|
||||||
|
WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
|
||||||
|
{
|
||||||
|
int rc = Success;
|
||||||
|
|
||||||
|
/* Event in response to reject */
|
||||||
|
if (ev->device_event.flags & TOUCH_REJECT)
|
||||||
|
{
|
||||||
|
if (listener->state != LISTENER_HAS_END)
|
||||||
|
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
|
||||||
|
listener->state = LISTENER_HAS_END;
|
||||||
|
} else if (TouchResourceIsOwner(ti, listener->listener))
|
||||||
|
{
|
||||||
|
/* FIXME: what about early acceptance */
|
||||||
|
if (!(ev->device_event.flags & TOUCH_ACCEPT))
|
||||||
|
{
|
||||||
|
if (listener->state != LISTENER_HAS_END)
|
||||||
|
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
|
||||||
|
listener->state = LISTENER_HAS_END;
|
||||||
|
}
|
||||||
|
if (ti->num_listeners > 1 &&
|
||||||
|
(ev->device_event.flags & (TOUCH_ACCEPT|TOUCH_REJECT)) == 0)
|
||||||
|
{
|
||||||
|
ev->any.type = ET_TouchUpdate;
|
||||||
|
ev->device_event.flags |= TOUCH_PENDING_END;
|
||||||
|
ti->pending_finish = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
|
||||||
|
TouchListener *listener, ClientPtr client,
|
||||||
|
WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
|
||||||
|
{
|
||||||
|
Bool has_ownershipmask = FALSE;
|
||||||
|
int rc = Success;
|
||||||
|
|
||||||
|
if (xi2mask)
|
||||||
|
has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
|
||||||
|
|
||||||
|
if (ev->any.type == ET_TouchOwnership)
|
||||||
|
{
|
||||||
|
ev->touch_ownership_event.deviceid = dev->id;
|
||||||
|
if (!TouchResourceIsOwner(ti, listener->listener))
|
||||||
|
goto out;
|
||||||
|
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
|
||||||
|
listener->state = LISTENER_IS_OWNER;
|
||||||
|
} else
|
||||||
|
ev->device_event.deviceid = dev->id;
|
||||||
|
|
||||||
|
if (ev->any.type == ET_TouchBegin)
|
||||||
|
{
|
||||||
|
rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
|
||||||
|
} else if (ev->any.type == ET_TouchUpdate)
|
||||||
|
{
|
||||||
|
if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
|
||||||
|
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
|
||||||
|
} else if (ev->any.type == ET_TouchEnd)
|
||||||
|
rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delivers a touch events to all interested clients. For TouchBegin events,
|
||||||
|
* will update ti->listeners, ti->num_listeners, and ti->num_grabs.
|
||||||
|
* May also mutate ev (type and flags) upon successful delivery. If
|
||||||
|
* @resource is non-zero, will only attempt delivery to the owner of that
|
||||||
|
* resource.
|
||||||
|
*
|
||||||
|
* @return TRUE if the event was delivered at least once, FALSE otherwise
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
||||||
|
InternalEvent *ev, XID resource)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ev->any.type == ET_TouchBegin &&
|
||||||
|
!(ev->device_event.flags & (TOUCH_CLIENT_ID|TOUCH_REPLAYING)))
|
||||||
|
TouchSetupListeners(dev, ti, ev);
|
||||||
|
|
||||||
|
TouchEventHistoryPush(ti, &ev->device_event);
|
||||||
|
|
||||||
|
for (i = 0; i < ti->num_listeners; i++)
|
||||||
|
{
|
||||||
|
GrabPtr grab = NULL;
|
||||||
|
ClientPtr client;
|
||||||
|
WindowPtr win;
|
||||||
|
XI2Mask *mask;
|
||||||
|
TouchListener *listener = &ti->listeners[i];
|
||||||
|
|
||||||
|
if (resource && listener->listener != resource)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
|
||||||
|
&grab, &mask))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ti->emulate_pointer)
|
||||||
|
UpdateDeviceState(dev, &ev->device_event);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
InitProximityClassDeviceStruct(DeviceIntPtr dev)
|
InitProximityClassDeviceStruct(DeviceIntPtr dev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -496,7 +496,8 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
|
||||||
flags |= TOUCH_POINTER_EMULATED;
|
flags |= TOUCH_POINTER_EMULATED;
|
||||||
/* send fake begin event to next owner */
|
/* send fake begin event to next owner */
|
||||||
nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask);
|
nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask);
|
||||||
/* FIXME: deliver the event */
|
for (i = 0; i < nev; i++)
|
||||||
|
DeliverTouchEvents(dev, ti, tel + i, resource);
|
||||||
|
|
||||||
valuator_mask_free(&mask);
|
valuator_mask_free(&mask);
|
||||||
FreeEventList(tel, GetMaximumEventsNum());
|
FreeEventList(tel, GetMaximumEventsNum());
|
||||||
|
@ -506,7 +507,7 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
|
||||||
{
|
{
|
||||||
DeviceEvent *ev = &ti->history[i];
|
DeviceEvent *ev = &ti->history[i];
|
||||||
ev->flags |= TOUCH_REPLAYING;
|
ev->flags |= TOUCH_REPLAYING;
|
||||||
/* FIXME: deliver the event */
|
DeliverTouchEvents(dev, ti, (InternalEvent*)ev, resource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -405,6 +405,12 @@ extern int DeliverOneGrabbedEvent(
|
||||||
DeviceIntPtr /* dev */,
|
DeviceIntPtr /* dev */,
|
||||||
enum InputLevel /* level */);
|
enum InputLevel /* level */);
|
||||||
|
|
||||||
|
extern void DeliverTouchEvents(
|
||||||
|
DeviceIntPtr /* dev */,
|
||||||
|
TouchPointInfoPtr /* ti */,
|
||||||
|
InternalEvent* /* ev */,
|
||||||
|
XID /* resource */);
|
||||||
|
|
||||||
extern void InitializeSprite(
|
extern void InitializeSprite(
|
||||||
DeviceIntPtr /* pDev */,
|
DeviceIntPtr /* pDev */,
|
||||||
WindowPtr /* pWin */);
|
WindowPtr /* pWin */);
|
||||||
|
|
Loading…
Reference in New Issue