aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix')
-rw-r--r--xorg-server/dix/dispatch.c10
-rw-r--r--xorg-server/dix/events.c55
-rw-r--r--xorg-server/dix/resource.c383
-rw-r--r--xorg-server/dix/touch.c117
4 files changed, 476 insertions, 89 deletions
diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c
index 14f1af18a..60d57a352 100644
--- a/xorg-server/dix/dispatch.c
+++ b/xorg-server/dix/dispatch.c
@@ -218,7 +218,7 @@ UpdateCurrentTimeIf(void)
systime.milliseconds = GetTimeInMillis();
if (systime.milliseconds < currentTime.milliseconds)
systime.months++;
- if (*checkForInput[0] == *checkForInput[1])
+ if (CompareTimeStamps(systime, currentTime) == LATER)
currentTime = systime;
}
@@ -400,6 +400,9 @@ Dispatch(void)
}
/* now, finally, deal with client requests */
+ /* Update currentTime so request time checks, such as for input
+ * device grabs, are calculated correctly */
+ UpdateCurrentTimeIf();
result = ReadRequestFromClient(client);
if (result <= 0) {
if (result < 0)
@@ -422,8 +425,9 @@ Dispatch(void)
StartMajorOp=client->majorOp;
XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
client->majorOp,
- ((xReq *)client->requestBuffer)->length,
- client->index, client->requestBuffer);
+ ((xReq *) client->requestBuffer)->length,
+ client->index,
+ client->requestBuffer);
}
#endif
if (result > (maxBigRequestSize << 2))
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 1a2126884..6d5f67586 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -1276,18 +1276,11 @@ ComputeFreezes(void)
event->root_x, event->root_y);
if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) {
if (IsTouchEvent((InternalEvent *) event)) {
- InternalEvent *events = InitEventList(GetMaximumEventsNum());
- int i, nev;
TouchPointInfoPtr ti =
TouchFindByClientID(replayDev, event->touchid);
BUG_WARN(!ti);
- nev =
- GetTouchOwnershipEvents(events, replayDev, ti,
- XIRejectTouch,
- ti->listeners[0].listener, 0);
- for (i = 0; i < nev; i++)
- mieqProcessDeviceEvent(replayDev, events + i, NULL);
- ProcessInputEvents();
+
+ TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
}
else if (replayDev->focus &&
!IsPointerEvent((InternalEvent *) event))
@@ -1419,6 +1412,38 @@ ReattachToOldMaster(DeviceIntPtr dev)
}
/**
+ * Update touch records when an explicit grab is activated. Any touches owned by
+ * the grabbing client are updated so the listener state reflects the new grab.
+ */
+static void
+UpdateTouchesForGrab(DeviceIntPtr mouse)
+{
+ int i;
+
+ if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
+ return;
+
+ for (i = 0; i < mouse->touch->num_touches; i++) {
+ TouchPointInfoPtr ti = mouse->touch->touches + i;
+ GrabPtr grab = mouse->deviceGrab.grab;
+
+ if (ti->active &&
+ CLIENT_BITS(ti->listeners[0].listener) == grab->resource) {
+ ti->listeners[0].listener = grab->resource;
+ ti->listeners[0].level = grab->grabtype;
+ ti->listeners[0].state = LISTENER_IS_OWNER;
+ ti->listeners[0].window = grab->window;
+
+ if (grab->grabtype == CORE || grab->grabtype == XI ||
+ !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
+ ti->listeners[0].type = LISTENER_POINTER_GRAB;
+ else
+ ti->listeners[0].type = LISTENER_GRAB;
+ }
+ }
+}
+
+/**
* Activate a pointer grab on the given device. A pointer grab will cause all
* core pointer events of this device to be delivered to the grabbing client only.
* No other device will send core events to the grab client while the grab is
@@ -1467,6 +1492,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
grabinfo->fromPassiveGrab = isPassive;
grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
PostNewCursor(mouse);
+ UpdateTouchesForGrab(mouse);
CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
(Bool) grab->keyboardMode);
}
@@ -1483,6 +1509,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
DeviceIntPtr dev;
Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
mouse->deviceGrab.implicitGrab);
+ XID grab_resource = grab->resource;
+ int i;
TouchRemovePointerGrab(mouse);
@@ -1507,6 +1535,15 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
ReattachToOldMaster(mouse);
ComputeFreezes();
+
+ /* If an explicit grab was deactivated, we must remove it from the head of
+ * all the touches' listener lists. */
+ for (i = 0; mouse->touch && i < mouse->touch->num_touches; i++) {
+ TouchPointInfoPtr ti = mouse->touch->touches + i;
+
+ if (ti->active && TouchResourceIsOwner(ti, grab_resource))
+ TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);
+ }
}
/**
diff --git a/xorg-server/dix/resource.c b/xorg-server/dix/resource.c
index 865b5b219..1ab06d51d 100644
--- a/xorg-server/dix/resource.c
+++ b/xorg-server/dix/resource.c
@@ -141,6 +141,7 @@ Equipment Corporation.
#include "xace.h"
#include <assert.h>
#include "registry.h"
+#include "gcstruct.h"
#ifdef XSERVER_DTRACE
#include <sys/types.h>
@@ -182,50 +183,313 @@ RESTYPE TypeMask;
struct ResourceType {
DeleteType deleteFunc;
+ SizeType sizeFunc;
+ FindTypeSubResources findSubResFunc;
int errorValue;
};
+/**
+ * Used by all resources that don't specify a function to calculate
+ * resource size. Currently this is used for all resources with
+ * insignificant memory usage.
+ *
+ * @see GetResourceTypeSizeFunc, SetResourceTypeSizeFunc
+ *
+ * @param[in] value Pointer to resource object.
+ *
+ * @param[in] id Resource ID for the object.
+ *
+ * @param[out] size Fill all fields to zero to indicate that size of
+ * resource can't be determined.
+ */
+static void
+GetDefaultBytes(pointer value, XID id, ResourceSizePtr size)
+{
+ size->resourceSize = 0;
+ size->pixmapRefSize = 0;
+ size->refCnt = 1;
+}
+
+/**
+ * Used by all resources that don't specify a function to iterate
+ * through subresources. Currently this is used for all resources with
+ * insignificant memory usage.
+ *
+ * @see FindSubResources, SetResourceTypeFindSubResFunc
+ *
+ * @param[in] value Pointer to resource object.
+ *
+ * @param[in] func Function to call for each subresource.
+
+ * @param[out] cdata Pointer to opaque data.
+ */
+static void
+DefaultFindSubRes(pointer value, FindAllRes func, pointer cdata)
+{
+ /* do nothing */
+}
+
+/**
+ * Calculate drawable size in bytes. Reference counting is not taken
+ * into account.
+ *
+ * @param[in] drawable Pointer to a drawable.
+ *
+ * @return Estimate of total memory usage for the drawable.
+ */
+static unsigned long
+GetDrawableBytes(DrawablePtr drawable)
+{
+ int bytes = 0;
+
+ if (drawable)
+ {
+ int bytesPerPixel = drawable->bitsPerPixel >> 3;
+ int numberOfPixels = drawable->width * drawable->height;
+ bytes = numberOfPixels * bytesPerPixel;
+ }
+
+ return bytes;
+}
+
+/**
+ * Calculate pixmap size in bytes. Reference counting is taken into
+ * account. Any extra data attached by extensions and drivers is not
+ * taken into account. The purpose of this function is to estimate
+ * memory usage that can be attributed to single reference of the
+ * pixmap.
+ *
+ * @param[in] value Pointer to a pixmap.
+ *
+ * @param[in] id Resource ID of pixmap. If the pixmap hasn't been
+ * added as resource, just pass value->drawable.id.
+ *
+ * @param[out] size Estimate of memory usage attributed to a single
+ * pixmap reference.
+ */
+static void
+GetPixmapBytes(pointer value, XID id, ResourceSizePtr size)
+{
+ PixmapPtr pixmap = value;
+
+ size->resourceSize = 0;
+ size->pixmapRefSize = 0;
+ size->refCnt = pixmap->refcnt;
+
+ if (pixmap && pixmap->refcnt)
+ {
+ DrawablePtr drawable = &pixmap->drawable;
+ size->resourceSize = GetDrawableBytes(drawable);
+ size->pixmapRefSize = size->resourceSize / pixmap->refcnt;
+ }
+}
+
+/**
+ * Calculate window size in bytes. The purpose of this function is to
+ * estimate memory usage that can be attributed to all pixmap
+ * references of the window.
+ *
+ * @param[in] value Pointer to a window.
+ *
+ * @param[in] id Resource ID of window.
+ *
+ * @param[out] size Estimate of memory usage attributed to a all
+ * pixmap references of a window.
+ */
+static void
+GetWindowBytes(pointer value, XID id, ResourceSizePtr size)
+{
+ SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
+ ResourceSizeRec pixmapSize = { 0, 0, 0 };
+ WindowPtr window = value;
+
+ /* Currently only pixmap bytes are reported to clients. */
+ size->resourceSize = 0;
+
+ /* Calculate pixmap reference sizes. */
+ size->pixmapRefSize = 0;
+
+ size->refCnt = 1;
+
+ if (window->backgroundState == BackgroundPixmap)
+ {
+ PixmapPtr pixmap = window->background.pixmap;
+ pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+ size->pixmapRefSize += pixmapSize.pixmapRefSize;
+ }
+ if (window->border.pixmap && !window->borderIsPixel)
+ {
+ PixmapPtr pixmap = window->border.pixmap;
+ pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+ size->pixmapRefSize += pixmapSize.pixmapRefSize;
+ }
+}
+
+/**
+ * Iterate through subresources of a window. The purpose of this
+ * function is to gather accurate information on what resources
+ * a resource uses.
+ *
+ * @note Currently only sub-pixmaps are iterated
+ *
+ * @param[in] value Pointer to a window
+ *
+ * @param[in] func Function to call with each subresource
+ *
+ * @param[out] cdata Pointer to opaque data
+ */
+static void
+FindWindowSubRes(pointer value, FindAllRes func, pointer cdata)
+{
+ WindowPtr window = value;
+
+ /* Currently only pixmap subresources are reported to clients. */
+
+ if (window->backgroundState == BackgroundPixmap)
+ {
+ PixmapPtr pixmap = window->background.pixmap;
+ func(window->background.pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+ }
+ if (window->border.pixmap && !window->borderIsPixel)
+ {
+ PixmapPtr pixmap = window->border.pixmap;
+ func(window->background.pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+ }
+}
+
+/**
+ * Calculate graphics context size in bytes. The purpose of this
+ * function is to estimate memory usage that can be attributed to all
+ * pixmap references of the graphics context.
+ *
+ * @param[in] value Pointer to a graphics context.
+ *
+ * @param[in] id Resource ID of graphics context.
+ *
+ * @param[out] size Estimate of memory usage attributed to a all
+ * pixmap references of a graphics context.
+ */
+static void
+GetGcBytes(pointer value, XID id, ResourceSizePtr size)
+{
+ SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
+ ResourceSizeRec pixmapSize = { 0, 0, 0 };
+ GCPtr gc = value;
+
+ /* Currently only pixmap bytes are reported to clients. */
+ size->resourceSize = 0;
+
+ /* Calculate pixmap reference sizes. */
+ size->pixmapRefSize = 0;
+
+ size->refCnt = 1;
+ if (gc->stipple)
+ {
+ PixmapPtr pixmap = gc->stipple;
+ pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+ size->pixmapRefSize += pixmapSize.pixmapRefSize;
+ }
+ if (gc->tile.pixmap && !gc->tileIsPixel)
+ {
+ PixmapPtr pixmap = gc->tile.pixmap;
+ pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+ size->pixmapRefSize += pixmapSize.pixmapRefSize;
+ }
+}
+
+/**
+ * Iterate through subresources of a graphics context. The purpose of
+ * this function is to gather accurate information on what resources a
+ * resource uses.
+ *
+ * @note Currently only sub-pixmaps are iterated
+ *
+ * @param[in] value Pointer to a window
+ *
+ * @param[in] func Function to call with each subresource
+ *
+ * @param[out] cdata Pointer to opaque data
+ */
+static void
+FindGCSubRes(pointer value, FindAllRes func, pointer cdata)
+{
+ GCPtr gc = value;
+
+ /* Currently only pixmap subresources are reported to clients. */
+
+ if (gc->stipple)
+ {
+ PixmapPtr pixmap = gc->stipple;
+ func(pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+ }
+ if (gc->tile.pixmap && !gc->tileIsPixel)
+ {
+ PixmapPtr pixmap = gc->tile.pixmap;
+ func(pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+ }
+}
+
static struct ResourceType *resourceTypes;
static const struct ResourceType predefTypes[] = {
/* [RT_NONE & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */(DeleteType)NoopDDA,
+ /*.sizeFunc = */GetDefaultBytes,
+ /*.findSubResFunc = */DefaultFindSubRes,
/*.errorValue = */BadValue,
},
/* [RT_WINDOW & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */DeleteWindow,
+ /*.sizeFunc = */GetWindowBytes,
+ /*.findSubResFunc = */FindWindowSubRes,
/*.errorValue = */BadWindow,
},
/* [RT_PIXMAP & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */dixDestroyPixmap,
+ /*.sizeFunc = */GetPixmapBytes,
+ /*.findSubResFunc = */DefaultFindSubRes,
/*.errorValue = */BadPixmap,
},
/* [RT_GC & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */FreeGC,
+ /*.sizeFunc = */GetGcBytes,
+ /*.findSubResFunc = */FindGCSubRes,
/*.errorValue = */BadGC,
},
/* [RT_FONT & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */CloseFont,
+ /*.sizeFunc = */GetDefaultBytes,
+ /*.findSubResFunc = */DefaultFindSubRes,
/*.errorValue = */BadFont,
},
/* [RT_CURSOR & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */FreeCursor,
+ /*.sizeFunc = */GetDefaultBytes,
+ /*.findSubResFunc = */DefaultFindSubRes,
/*.errorValue = */BadCursor,
},
/* [RT_COLORMAP & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */FreeColormap,
+ /*.sizeFunc = */GetDefaultBytes,
+ /*.findSubResFunc = */DefaultFindSubRes,
/*.errorValue = */BadColor,
},
/* [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */FreeClientPixels,
+ /*.sizeFunc = */GetDefaultBytes,
+ /*.findSubResFunc = */DefaultFindSubRes,
/*.errorValue = */BadColor,
},
/* [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */OtherClientGone,
+ /*.sizeFunc = */GetDefaultBytes,
+ /*.findSubResFunc = */DefaultFindSubRes,
/*.errorValue = */BadValue,
},
/* [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = */ {
/*.deleteFunc = */DeletePassiveGrab,
+ /*.deleteFunc = */DeletePassiveGrab,
+ /*.sizeFunc = */GetDefaultBytes,
/*.errorValue = */BadValue,
},
};
@@ -256,6 +520,8 @@ CreateNewResourceType(DeleteType deleteFunc, const char *name)
lastResourceType = next;
resourceTypes = types;
resourceTypes[next].deleteFunc = deleteFunc;
+ resourceTypes[next].sizeFunc = GetDefaultBytes;
+ resourceTypes[next].findSubResFunc = DefaultFindSubRes;
resourceTypes[next].errorValue = BadValue;
/* Called even if name is NULL, to remove any previous entry */
@@ -264,6 +530,57 @@ CreateNewResourceType(DeleteType deleteFunc, const char *name)
return next;
}
+/**
+ * Get the function used to calculate resource size. Extensions and
+ * drivers need to be able to determine the current size calculation
+ * function if they want to wrap or override it.
+ *
+ * @param[in] type Resource type used in size calculations.
+ *
+ * @return Function to calculate the size of a single
+ * resource.
+ */
+SizeType
+GetResourceTypeSizeFunc(RESTYPE type)
+{
+ return resourceTypes[type & TypeMask].sizeFunc;
+}
+
+/**
+ * Override the default function that calculates resource size. For
+ * example, video driver knows better how to calculate pixmap memory
+ * usage and can therefore wrap or override size calculation for
+ * RT_PIXMAP.
+ *
+ * @param[in] type Resource type used in size calculations.
+ *
+ * @param[in] sizeFunc Function to calculate the size of a single
+ * resource.
+ */
+void
+SetResourceTypeSizeFunc(RESTYPE type, SizeType sizeFunc)
+{
+ resourceTypes[type & TypeMask].sizeFunc = sizeFunc;
+}
+
+/**
+ * Provide a function for iterating the subresources of a resource.
+ * This allows for example more accurate accounting of the (memory)
+ * resources consumed by a resource.
+ *
+ * @see FindSubResources
+ *
+ * @param[in] type Resource type used in size calculations.
+ *
+ * @param[in] sizeFunc Function to calculate the size of a single
+ * resource.
+ */
+void
+SetResourceTypeFindSubResFunc(RESTYPE type, FindTypeSubResources findFunc)
+{
+ resourceTypes[type & TypeMask].findSubResFunc = findFunc;
+}
+
void
SetResourceTypeErrorValue(RESTYPE type, int errorValue)
{
@@ -326,25 +643,32 @@ InitClientResources(ClientPtr client)
return TRUE;
}
-static int
-Hash(int client, XID id)
+int
+HashResourceID(XID id, int numBits)
{
id &= RESOURCE_ID_MASK;
- switch (clientTable[client].hashsize) {
- case 6:
- return ((int) (0x03F & (id ^ (id >> 6) ^ (id >> 12))));
- case 7:
- return ((int) (0x07F & (id ^ (id >> 7) ^ (id >> 13))));
- case 8:
- return ((int) (0x0FF & (id ^ (id >> 8) ^ (id >> 16))));
- case 9:
- return ((int) (0x1FF & (id ^ (id >> 9))));
- case 10:
- return ((int) (0x3FF & (id ^ (id >> 10))));
- case 11:
- return ((int) (0x7FF & (id ^ (id >> 11))));
- }
- return -1;
+ switch (numBits)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
+ case 7:
+ return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
+ case 8:
+ return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
+ case 9:
+ return ((int)(0x1FF & (id ^ (id>>9))));
+ case 10:
+ return ((int)(0x3FF & (id ^ (id>>10))));
+ case 11:
+ return ((int)(0x7FF & (id ^ (id>>11))));
+ }
+ if (numBits >= 11)
+ return ((int)(0x7FF & (id ^ (id>>11))));
+ else
+ {
+ assert(numBits >= 0);
+ return id & ~((~0) << numBits);
+ }
}
static XID
@@ -355,7 +679,7 @@ AvailableID(int client, XID id, XID maxid, XID goodid)
if ((goodid >= id) && (goodid <= maxid))
return goodid;
for (; id <= maxid; id++) {
- res = clientTable[client].resources[Hash(client, id)];
+ res = clientTable[client].resources[HashResourceID(id, clientTable[client].hashsize)];
while (res && (res->id != id))
res = res->next;
if (!res)
@@ -481,7 +805,7 @@ AddResource(XID id, RESTYPE type, pointer value)
}
if ((rrec->elements >= 4 * rrec->buckets) && (rrec->hashsize < MAXHASHSIZE))
RebuildTable(client);
- head = &rrec->resources[Hash(client, id)];
+ head = &rrec->resources[HashResourceID(id, clientTable[client].hashsize)];
res = malloc(sizeof(ResourceRec));
if (!res) {
(*resourceTypes[type & TypeMask].deleteFunc) (value, id);
@@ -529,7 +853,7 @@ RebuildTable(int client)
for (res = *rptr; res; res = next) {
next = res->next;
res->next = NULL;
- tptr = &tails[Hash(client, res->id)];
+ tptr = &tails[HashResourceID(res->id, clientTable[client].hashsize)];
**tptr = res;
*tptr = &res->next;
}
@@ -561,7 +885,7 @@ FreeResource(XID id, RESTYPE skipDeleteFuncType)
int elements;
if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- head = &clientTable[cid].resources[Hash(cid, id)];
+ head = &clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
eltptr = &clientTable[cid].elements;
prev = head;
@@ -595,7 +919,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
ResourcePtr *prev, *head;
if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- head = &clientTable[cid].resources[Hash(cid, id)];
+ head = &clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
prev = head;
while ((res = *prev)) {
@@ -630,7 +954,7 @@ ChangeResourceValue(XID id, RESTYPE rtype, pointer value)
ResourcePtr res;
if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
+ res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
for (; res; res = res->next)
if ((res->id == id) && (res->type == rtype)) {
@@ -674,6 +998,15 @@ FindClientResourcesByType(ClientPtr client,
}
}
+void FindSubResources(pointer resource,
+ RESTYPE type,
+ FindAllRes func,
+ pointer cdata)
+{
+ struct ResourceType rtype = resourceTypes[type & TypeMask];
+ rtype.findSubResFunc(resource, func, cdata);
+}
+
void
FindAllClientResources(ClientPtr client, FindAllRes func, pointer cdata)
{
@@ -859,7 +1192,7 @@ dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype,
return BadImplementation;
if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
+ res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
for (; res; res = res->next)
if (res->id == id && res->type == rtype)
@@ -892,7 +1225,7 @@ dixLookupResourceByClass(pointer *result, XID id, RESTYPE rclass,
*result = NULL;
if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
+ res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
for (; res; res = res->next)
if (res->id == id && (res->type & rclass))
diff --git a/xorg-server/dix/touch.c b/xorg-server/dix/touch.c
index 0829b6545..dd16367d0 100644
--- a/xorg-server/dix/touch.c
+++ b/xorg-server/dix/touch.c
@@ -364,14 +364,6 @@ TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
{
if (ti->emulate_pointer) {
GrabPtr grab;
- DeviceEvent ev;
-
- memset(&ev, 0, sizeof(ev));
- ev.type = ET_TouchEnd;
- ev.detail.button = 1;
- ev.touchid = ti->client_id;
- ev.flags = TOUCH_POINTER_EMULATED | TOUCH_END;
- UpdateDeviceState(dev, &ev);
if ((grab = dev->deviceGrab.grab)) {
if (dev->deviceGrab.fromPassiveGrab &&
@@ -482,10 +474,22 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
flags = TOUCH_CLIENT_ID | TOUCH_REPLAYING;
if (ti->emulate_pointer)
flags |= TOUCH_POINTER_EMULATED;
- /* send fake begin event to next owner */
+ /* Generate events based on a fake touch begin event to get DCCE events if
+ * needed */
+ /* FIXME: This needs to be cleaned up */
nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask);
- for (i = 0; i < nev; i++)
- DeliverTouchEvents(dev, ti, tel + i, resource);
+ for (i = 0; i < nev; i++) {
+ /* Send saved touch begin event */
+ if (tel[i].any.type == ET_TouchBegin) {
+ DeviceEvent *ev = &ti->history[0];
+ ev->flags |= TOUCH_REPLAYING;
+ DeliverTouchEvents(dev, ti, (InternalEvent*)ev, resource);
+ }
+ else {/* Send DCCE event */
+ tel[i].any.time = ti->history[0].time;
+ DeliverTouchEvents(dev, ti, tel + i, resource);
+ }
+ }
valuator_mask_free(&mask);
FreeEventList(tel, GetMaximumEventsNum());
@@ -542,22 +546,12 @@ TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite)
* TouchBegin events.
*/
Bool
-TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
- InternalEvent *ev)
+TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+ InternalEvent *ev)
{
TouchClassPtr t = sourcedev->touch;
SpritePtr sprite = &ti->sprite;
- /* We may not have a sprite if there are no applicable grabs or
- * event selections, or if they've disappeared, or if all the grab
- * owners have rejected the touch. Don't bother delivering motion
- * events if not, but TouchEnd events still need to be processed so
- * we can call FinishTouchPoint and release it for later use. */
- if (ev->any.type == ET_TouchEnd)
- return TRUE;
- else if (ev->any.type != ET_TouchBegin)
- return (sprite->spriteTraceGood > 0);
-
if (t->mode == XIDirectTouch) {
/* Focus immediately under the touchpoint in direct touch mode.
* XXX: Do we need to handle crossing screens here? */
@@ -821,6 +815,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
if (mask & EVENT_CORE_MASK) {
int coretype = GetCoreType(TouchGetPointerEventType(ev));
Mask core_filter = event_get_filter_from_type(dev, coretype);
+ OtherClients *oclients;
/* window owner */
if (IsMaster(dev) && (win->eventMask & core_filter)) {
@@ -832,13 +827,12 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
}
/* all others */
- nt_list_for_each_entry(iclients, (InputClients *) wOtherClients(win),
- next) {
- if (!(iclients->mask[XIAllDevices] & core_filter))
+ nt_list_for_each_entry(oclients, wOtherClients(win), next) {
+ if (!(oclients->mask & core_filter))
continue;
TouchEventHistoryAllocate(ti);
- TouchAddListener(ti, iclients->resource, CORE,
+ TouchAddListener(ti, oclients->resource, CORE,
type, LISTENER_AWAITING_BEGIN, win);
return TRUE;
}
@@ -874,6 +868,11 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
if (dev->deviceGrab.grab)
TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
+ /* We set up an active touch listener for existing touches, but not any
+ * passive grab or regular listeners. */
+ if (ev->any.type != ET_TouchBegin)
+ return;
+
/* First, find all grabbing clients from the root window down
* to the deepest child window. */
for (i = 0; i < sprite->spriteTraceGood; i++) {
@@ -960,15 +959,48 @@ TouchListenerGone(XID resource)
}
int
+TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener,
+ int mode)
+{
+ InternalEvent *events;
+ int nev;
+ int i;
+
+ if (listener > 0) {
+ if (mode == XIRejectTouch)
+ TouchRejected(dev, ti, ti->listeners[listener].listener, NULL);
+ else
+ ti->listeners[listener].state = LISTENER_EARLY_ACCEPT;
+
+ return Success;
+ }
+
+ events = InitEventList(GetMaximumEventsNum());
+ if (!events) {
+ BUG_WARN_MSG(TRUE, "Failed to allocate touch ownership events\n");
+ return BadAlloc;
+ }
+
+ nev = GetTouchOwnershipEvents(events, dev, ti, mode,
+ ti->listeners[0].listener, 0);
+ BUG_WARN_MSG(nev == 0, "Failed to get touch ownership events\n");
+
+ for (i = 0; i < nev; i++)
+ mieqProcessDeviceEvent(dev, events + i, NULL);
+
+ ProcessInputEvents();
+
+ FreeEventList(events, GetMaximumEventsNum());
+
+ return nev ? Success : BadMatch;
+}
+
+int
TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
uint32_t touchid, Window grab_window, XID *error)
{
TouchPointInfoPtr ti;
- int nev, i;
- InternalEvent *events = InitEventList(GetMaximumEventsNum());
-
- if (!events)
- return BadAlloc;
+ int i;
if (!dev->touch) {
*error = dev->id;
@@ -989,24 +1021,5 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
if (i == ti->num_listeners)
return BadAccess;
- if (i > 0) {
- if (mode == XIRejectTouch)
- TouchRejected(dev, ti, ti->listeners[i].listener, NULL);
- else
- ti->listeners[i].state = LISTENER_EARLY_ACCEPT;
-
- return Success;
- }
-
- nev = GetTouchOwnershipEvents(events, dev, ti, mode,
- ti->listeners[0].listener, 0);
- if (nev == 0)
- return BadAlloc;
- for (i = 0; i < nev; i++)
- mieqProcessDeviceEvent(dev, events + i, NULL);
-
- ProcessInputEvents();
-
- FreeEventList(events, GetMaximumEventsNum());
- return Success;
+ return TouchListenerAcceptReject(dev, ti, i, mode);
}