diff options
Diffstat (limited to 'xorg-server/dix')
-rw-r--r-- | xorg-server/dix/dispatch.c | 9 | ||||
-rw-r--r-- | xorg-server/dix/events.c | 55 | ||||
-rw-r--r-- | xorg-server/dix/resource.c | 383 | ||||
-rw-r--r-- | xorg-server/dix/touch.c | 117 |
4 files changed, 475 insertions, 89 deletions
diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index 104dcc9b3..d97180548 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -214,7 +214,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; } @@ -393,6 +393,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) @@ -413,8 +416,8 @@ Dispatch(void) if (XSERVER_REQUEST_START_ENABLED()) XSERVER_REQUEST_START(LookupMajorName(client->majorOp), client->majorOp, - ((xReq *) client->requestBuffer)-> - length, client->index, + ((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 b9f9cfa3c..9496b6f19 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -1273,18 +1273,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)) @@ -1416,6 +1409,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 @@ -1464,6 +1489,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); } @@ -1480,6 +1506,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse) DeviceIntPtr dev; Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && mouse->deviceGrab.implicitGrab); + XID grab_resource = grab->resource; + int i; TouchRemovePointerGrab(mouse); @@ -1504,6 +1532,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 89d077642..2aafa343c 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, + .sizeFunc = GetDefaultBytes, + .findSubResFunc = DefaultFindSubRes, .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); } |