Merge remote-tracking branch 'whot/touch-grab-race-condition-56578-v3'

This commit is contained in:
Keith Packard 2013-05-23 19:58:36 -06:00
commit c76a1b343d
21 changed files with 287 additions and 177 deletions

View File

@ -531,15 +531,16 @@ CreateSaverWindow(ScreenPtr pScreen)
mask |= CWBorderPixmap; mask |= CWBorderPixmap;
} }
if (pAttr->pCursor) { if (pAttr->pCursor) {
CursorPtr cursor;
if (!pWin->optional) if (!pWin->optional)
if (!MakeWindowOptional(pWin)) { if (!MakeWindowOptional(pWin)) {
FreeResource(pWin->drawable.id, RT_NONE); FreeResource(pWin->drawable.id, RT_NONE);
return FALSE; return FALSE;
} }
pAttr->pCursor->refcnt++; cursor = RefCursor(pAttr->pCursor);
if (pWin->optional->cursor) if (pWin->optional->cursor)
FreeCursor(pWin->optional->cursor, (Cursor) 0); FreeCursor(pWin->optional->cursor, (Cursor) 0);
pWin->optional->cursor = pAttr->pCursor; pWin->optional->cursor = cursor;
pWin->cursorIsNone = FALSE; pWin->cursorIsNone = FALSE;
CheckWindowOptionalNeed(pWin); CheckWindowOptionalNeed(pWin);
mask |= CWCursor; mask |= CWCursor;
@ -1065,8 +1066,7 @@ ScreenSaverSetAttributes(ClientPtr client)
client->errorValue = cursorID; client->errorValue = cursorID;
goto PatchUp; goto PatchUp;
} }
pCursor->refcnt++; pAttr->pCursor = RefCursor(pCursor);
pAttr->pCursor = pCursor;
pAttr->mask &= ~CWCursor; pAttr->mask &= ~CWCursor;
} }
break; break;

View File

@ -1036,46 +1036,21 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
static void static void
ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
{ {
int rc;
ClientPtr client; ClientPtr client;
XID error; XID error;
GrabPtr grab = ti->listeners[0].grab;
rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient, BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
DixSendAccess); ti->listeners[0].type != LISTENER_POINTER_GRAB);
if (rc != Success) { BUG_RETURN(!grab);
ErrorF("[Xi] Failed to lookup early accepting client.\n");
return; client = rClient(grab);
}
if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id, if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
ti->listeners[0].window->drawable.id, &error) != ti->listeners[0].window->drawable.id, &error) != Success)
Success)
ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n"); ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
} }
/**
* Generate and deliver a TouchEnd event.
*
* @param dev The device to deliver the event for.
* @param ti The touch point record to deliver the event for.
* @param flags Internal event flags. The called does not need to provide
* TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
* they are set appropriately.
* @param resource The client resource to deliver to, or 0 for all clients.
*/
static void
EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
{
InternalEvent event;
flags |= TOUCH_CLIENT_ID;
if (ti->emulate_pointer)
flags |= TOUCH_POINTER_EMULATED;
TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource);
GetDixTouchEnd(&event, dev, ti, flags);
DeliverTouchEvents(dev, ti, &event, resource);
}
/** /**
* Find the oldest touch that still has a pointer emulation client. * Find the oldest touch that still has a pointer emulation client.
* *
@ -1127,10 +1102,10 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
TouchOwnershipEvent *ev) TouchOwnershipEvent *ev)
{ {
TouchListener *listener = &ti->listeners[0]; /* new owner */ TouchListener *listener = &ti->listeners[0]; /* new owner */
int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
/* Deliver the ownership */ /* Deliver the ownership */
if (listener->state == LISTENER_AWAITING_OWNER || if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
listener->state == LISTENER_EARLY_ACCEPT)
DeliverTouchEvents(dev, ti, (InternalEvent *) ev, DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
listener->listener); listener->listener);
else if (listener->state == LISTENER_AWAITING_BEGIN) { else if (listener->state == LISTENER_AWAITING_BEGIN) {
@ -1144,15 +1119,24 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
TouchEventHistoryReplay(ti, dev, listener->listener); TouchEventHistoryReplay(ti, dev, listener->listener);
} }
/* If we've just removed the last grab and the touch has physically /* New owner has Begin/Update but not end. If touch is pending_finish,
* ended, send a TouchEnd event too and finalise the touch. */ * emulate the TouchEnd now */
if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) { if (ti->pending_finish) {
EmitTouchEnd(dev, ti, 0, 0); TouchEmitTouchEnd(dev, ti, 0, 0);
TouchEndTouch(dev, ti);
return; /* If the last owner is not a touch grab, finalise the touch, we
won't get more correspondence on this.
*/
if (ti->num_listeners == 1 &&
(ti->num_grabs == 0 ||
listener->grab->grabtype != XI2 ||
!xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
TouchEndTouch(dev, ti);
return;
}
} }
if (listener->state == LISTENER_EARLY_ACCEPT) if (accepted_early)
ActivateEarlyAccept(dev, ti); ActivateEarlyAccept(dev, ti);
} }
@ -1196,7 +1180,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
for (i = 0; i < ti->num_listeners; i++) { for (i = 0; i < ti->num_listeners; i++) {
if (ti->listeners[i].listener == resource) { if (ti->listeners[i].listener == resource) {
if (ti->listeners[i].state != LISTENER_HAS_END) if (ti->listeners[i].state != LISTENER_HAS_END)
EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource); TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
break; break;
} }
} }
@ -1243,12 +1227,12 @@ ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
* already seen the end. This ensures that the touch record is ended in * already seen the end. This ensures that the touch record is ended in
* the server. */ * the server. */
if (ti->listeners[0].state == LISTENER_HAS_END) if (ti->listeners[0].state == LISTENER_HAS_END)
EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener); TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
/* The touch owner has accepted the touch. Send TouchEnd events to /* The touch owner has accepted the touch. Send TouchEnd events to
* everyone else, and truncate the list of listeners. */ * everyone else, and truncate the list of listeners. */
for (i = 1; i < ti->num_listeners; i++) for (i = 1; i < ti->num_listeners; i++)
EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener); TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
while (ti->num_listeners > 1) while (ti->num_listeners > 1)
TouchRemoveListener(ti, ti->listeners[1].listener); TouchRemoveListener(ti, ti->listeners[1].listener);
@ -1417,7 +1401,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
} }
if (!deliveries) if (!deliveries)
DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype); deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
/* We must accept the touch sequence once a pointer listener has /* We must accept the touch sequence once a pointer listener has
* received one event past ButtonPress. */ * received one event past ButtonPress. */
@ -1425,8 +1409,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
!(ev->device_event.flags & TOUCH_CLIENT_ID)) !(ev->device_event.flags & TOUCH_CLIENT_ID))
TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
if (ev->any.type == ET_TouchEnd && if (deliveries && ev->any.type == ET_TouchEnd &&
!(ev->device_event.flags & TOUCH_CLIENT_ID) &&
!dev->button->buttonsDown && !dev->button->buttonsDown &&
dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
(*dev->deviceGrab.DeactivateGrab) (dev); (*dev->deviceGrab.DeactivateGrab) (dev);
@ -1445,8 +1428,11 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
*/ */
if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) { if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
TouchListener *l; TouchListener *l;
GrabPtr g;
devgrab = dev->deviceGrab.grab; devgrab = dev->deviceGrab.grab;
g = AllocGrab(devgrab);
BUG_WARN(!g);
*dev->deviceGrab.sync.event = ev->device_event; *dev->deviceGrab.sync.event = ev->device_event;
@ -1455,8 +1441,8 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
* event selection. Thus, we update the last listener in the array. * event selection. Thus, we update the last listener in the array.
*/ */
l = &ti->listeners[ti->num_listeners - 1]; l = &ti->listeners[ti->num_listeners - 1];
l->listener = devgrab->resource; l->listener = g->resource;
l->grab = devgrab; l->grab = g;
//l->resource_type = RT_NONE; //l->resource_type = RT_NONE;
if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin) if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
@ -1547,7 +1533,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
touchid = ev->device_event.touchid; touchid = ev->device_event.touchid;
if (type == ET_TouchBegin) { if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
emulate_pointer); emulate_pointer);
} }
@ -1614,7 +1600,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
* called after event type mutation. Touch end events are always processed * called after event type mutation. Touch end events are always processed
* in order to end touch records. */ * in order to end touch records. */
/* FIXME: check this */ /* FIXME: check this */
if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) || if ((type == ET_TouchBegin &&
!(ev->device_event.flags & TOUCH_REPLAYING) &&
!TouchBuildSprite(dev, ti, ev)) ||
(type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0)) (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
return; return;
@ -1622,7 +1610,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
/* WARNING: the event type may change to TouchUpdate in /* WARNING: the event type may change to TouchUpdate in
* DeliverTouchEvents if a TouchEnd was delivered to a grabbing * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
* owner */ * owner */
DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0); DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
if (ev->any.type == ET_TouchEnd) if (ev->any.type == ET_TouchEnd)
TouchEndTouch(dev, ti); TouchEndTouch(dev, ti);
@ -1850,6 +1838,14 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
listener->type == LISTENER_POINTER_GRAB) { listener->type == LISTENER_POINTER_GRAB) {
rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
grab, xi2mask); grab, xi2mask);
if (rc == Success) {
listener->state = LISTENER_IS_OWNER;
/* async grabs cannot replay, so automatically accept this touch */
if (dev->deviceGrab.grab &&
dev->deviceGrab.fromPassiveGrab &&
dev->deviceGrab.grab->pointerMode == GrabModeAsync)
ActivateEarlyAccept(dev, ti);
}
goto out; goto out;
} }
@ -1867,7 +1863,7 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
if (has_ownershipmask) if (has_ownershipmask)
TouchSendOwnershipEvent(dev, ti, 0, listener->listener); TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
if (!has_ownershipmask || listener->type == LISTENER_REGULAR) if (listener->type == LISTENER_REGULAR)
state = LISTENER_HAS_ACCEPTED; state = LISTENER_HAS_ACCEPTED;
else else
state = LISTENER_IS_OWNER; state = LISTENER_IS_OWNER;
@ -1890,13 +1886,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
grab, xi2mask); grab, xi2mask);
if (ti->num_listeners > 1) { /* Once we send a TouchEnd to a legacy listener, we're already well
ev->any.type = ET_TouchUpdate; * past the accepting/rejecting stage (can only happen on
ev->device_event.flags |= TOUCH_PENDING_END; * GrabModeSync + replay. This listener now gets the end event,
if (!(ev->device_event.flags & TOUCH_CLIENT_ID)) * and we can continue.
ti->pending_finish = TRUE; */
} if (rc == Success)
listener->state = LISTENER_HAS_END;
goto out; goto out;
} }
@ -1922,7 +1918,7 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
if ((ti->num_listeners > 1 || if ((ti->num_listeners > 1 ||
listener->state != LISTENER_HAS_ACCEPTED) && (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
(ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) { (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
ev->any.type = ET_TouchUpdate; ev->any.type = ET_TouchUpdate;
ev->device_event.flags |= TOUCH_PENDING_END; ev->device_event.flags |= TOUCH_PENDING_END;
@ -2850,7 +2846,7 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
(deliveryMask & DeviceButtonGrabMask)) { (deliveryMask & DeviceButtonGrabMask)) {
GrabPtr tempGrab; GrabPtr tempGrab;
tempGrab = AllocGrab(); tempGrab = AllocGrab(NULL);
if (!tempGrab) if (!tempGrab)
return; return;

View File

@ -127,7 +127,7 @@ ProcXUngrabDeviceButton(ClientPtr client)
(stuff->modifiers & ~AllModifiersMask)) (stuff->modifiers & ~AllModifiersMask))
return BadValue; return BadValue;
temporaryGrab = AllocGrab(); temporaryGrab = AllocGrab(NULL);
if (!temporaryGrab) if (!temporaryGrab)
return BadAlloc; return BadAlloc;

View File

@ -134,7 +134,7 @@ ProcXUngrabDeviceKey(ClientPtr client)
(stuff->modifiers & ~AllModifiersMask)) (stuff->modifiers & ~AllModifiersMask))
return BadValue; return BadValue;
temporaryGrab = AllocGrab(); temporaryGrab = AllocGrab(NULL);
if (!temporaryGrab) if (!temporaryGrab)
return BadAlloc; return BadAlloc;

View File

@ -307,7 +307,7 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
tempGrab = AllocGrab(); tempGrab = AllocGrab(NULL);
if (!tempGrab) if (!tempGrab)
return BadAlloc; return BadAlloc;

View File

@ -114,9 +114,13 @@ FreeCursor(pointer value, XID cid)
ScreenPtr pscr; ScreenPtr pscr;
DeviceIntPtr pDev = NULL; /* unused anyway */ DeviceIntPtr pDev = NULL; /* unused anyway */
if (--pCurs->refcnt != 0)
UnrefCursor(pCurs);
if (CursorRefCount(pCurs) != 0)
return Success; return Success;
BUG_WARN(CursorRefCount(pCurs) < 0);
for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
pscr = screenInfo.screens[nscr]; pscr = screenInfo.screens[nscr];
(void) (*pscr->UnrealizeCursor) (pDev, pscr, pCurs); (void) (*pscr->UnrealizeCursor) (pDev, pscr, pCurs);
@ -127,6 +131,33 @@ FreeCursor(pointer value, XID cid)
return Success; return Success;
} }
CursorPtr
RefCursor(CursorPtr cursor)
{
ErrorF("%s ::::: cursor is %p", __func__, cursor);
if (cursor) {
xorg_backtrace();
cursor->refcnt++;
}
ErrorF("\n");
return cursor;
}
CursorPtr
UnrefCursor(CursorPtr cursor)
{
if (cursor)
cursor->refcnt--;
return cursor;
}
int
CursorRefCount(const CursorPtr cursor)
{
return cursor ? cursor->refcnt : 0;
}
/* /*
* We check for empty cursors so that we won't have to display them * We check for empty cursors so that we won't have to display them
*/ */

View File

@ -281,7 +281,6 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
dev->deviceGrab.grabTime = currentTime; dev->deviceGrab.grabTime = currentTime;
dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
dev->deviceGrab.activeGrab = AllocGrab();
dev->deviceGrab.sync.event = calloc(1, sizeof(DeviceEvent)); dev->deviceGrab.sync.event = calloc(1, sizeof(DeviceEvent));
XkbSetExtension(dev, ProcessKeyboardEvent); XkbSetExtension(dev, ProcessKeyboardEvent);
@ -977,7 +976,8 @@ CloseDevice(DeviceIntPtr dev)
} }
} }
FreeGrab(dev->deviceGrab.activeGrab); if (dev->deviceGrab.grab)
FreeGrab(dev->deviceGrab.grab);
free(dev->deviceGrab.sync.event); free(dev->deviceGrab.sync.event);
free(dev->config_info); /* Allocated in xf86ActivateDevice. */ free(dev->config_info); /* Allocated in xf86ActivateDevice. */
free(dev->last.scroll); free(dev->last.scroll);
@ -1647,6 +1647,7 @@ InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches,
BUG_RETURN_VAL(device == NULL, FALSE); BUG_RETURN_VAL(device == NULL, FALSE);
BUG_RETURN_VAL(device->touch != NULL, FALSE); BUG_RETURN_VAL(device->touch != NULL, FALSE);
BUG_RETURN_VAL(device->valuator == NULL, FALSE);
/* Check the mode is valid, and at least X and Y axes. */ /* Check the mode is valid, and at least X and Y axes. */
BUG_RETURN_VAL(mode != XIDirectTouch && mode != XIDependentTouch, FALSE); BUG_RETURN_VAL(mode != XIDirectTouch && mode != XIDependentTouch, FALSE);

View File

@ -3399,6 +3399,7 @@ CloseDownClient(ClientPtr client)
clientinfo.setup = (xConnSetup *) NULL; clientinfo.setup = (xConnSetup *) NULL;
CallCallbacks((&ClientStateCallback), (pointer) &clientinfo); CallCallbacks((&ClientStateCallback), (pointer) &clientinfo);
} }
TouchListenerGone(client->clientAsMask);
FreeClientResources(client); FreeClientResources(client);
/* Disable client ID tracking. This must be done after /* Disable client ID tracking. This must be done after
* ClientStateCallback. */ * ClientStateCallback. */

View File

@ -931,8 +931,7 @@ ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
(*pScreen->DisplayCursor) (pDev, pScreen, cursor); (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
FreeCursor(pSprite->current, (Cursor) 0); FreeCursor(pSprite->current, (Cursor) 0);
pSprite->current = cursor; pSprite->current = RefCursor(cursor);
pSprite->current->refcnt++;
} }
} }
@ -1427,21 +1426,23 @@ UpdateTouchesForGrab(DeviceIntPtr mouse)
for (i = 0; i < mouse->touch->num_touches; i++) { for (i = 0; i < mouse->touch->num_touches; i++) {
TouchPointInfoPtr ti = mouse->touch->touches + i; TouchPointInfoPtr ti = mouse->touch->touches + i;
TouchListener *listener = &ti->listeners[0];
GrabPtr grab = mouse->deviceGrab.grab; GrabPtr grab = mouse->deviceGrab.grab;
if (ti->active && if (ti->active &&
CLIENT_BITS(ti->listeners[0].listener) == grab->resource) { CLIENT_BITS(listener->listener) == grab->resource) {
ti->listeners[0].listener = grab->resource; listener->listener = grab->resource;
ti->listeners[0].level = grab->grabtype; listener->level = grab->grabtype;
ti->listeners[0].state = LISTENER_IS_OWNER; listener->state = LISTENER_IS_OWNER;
ti->listeners[0].window = grab->window; listener->window = grab->window;
if (grab->grabtype == CORE || grab->grabtype == XI || if (grab->grabtype == CORE || grab->grabtype == XI ||
!xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
ti->listeners[0].type = LISTENER_POINTER_GRAB; listener->type = LISTENER_POINTER_GRAB;
else else
ti->listeners[0].type = LISTENER_GRAB; listener->type = LISTENER_GRAB;
ti->listeners[0].grab = grab; FreeGrab(listener->grab);
listener->grab = AllocGrab(grab);
} }
} }
} }
@ -1466,6 +1467,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
TimeStamp time, Bool autoGrab) TimeStamp time, Bool autoGrab)
{ {
GrabInfoPtr grabinfo = &mouse->deviceGrab; GrabInfoPtr grabinfo = &mouse->deviceGrab;
GrabPtr oldgrab = grabinfo->grab;
WindowPtr oldWin = (grabinfo->grab) ? WindowPtr oldWin = (grabinfo->grab) ?
grabinfo->grab->window : mouse->spriteInfo->sprite->win; grabinfo->grab->window : mouse->spriteInfo->sprite->win;
Bool isPassive = autoGrab & ~ImplicitGrabMask; Bool isPassive = autoGrab & ~ImplicitGrabMask;
@ -1488,16 +1490,15 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
grabinfo->grabTime = syncEvents.time; grabinfo->grabTime = syncEvents.time;
else else
grabinfo->grabTime = time; grabinfo->grabTime = time;
if (grab->cursor) grabinfo->grab = AllocGrab(grab);
grab->cursor->refcnt++;
CopyGrab(grabinfo->activeGrab, grab);
grabinfo->grab = grabinfo->activeGrab;
grabinfo->fromPassiveGrab = isPassive; grabinfo->fromPassiveGrab = isPassive;
grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
PostNewCursor(mouse); PostNewCursor(mouse);
UpdateTouchesForGrab(mouse); UpdateTouchesForGrab(mouse);
CheckGrabForSyncs(mouse, (Bool) grab->pointerMode, CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
(Bool) grab->keyboardMode); (Bool) grab->keyboardMode);
if (oldgrab)
FreeGrab(oldgrab);
} }
/** /**
@ -1547,13 +1548,13 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
if (grab->confineTo) if (grab->confineTo)
ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
PostNewCursor(mouse); PostNewCursor(mouse);
if (grab->cursor)
FreeCursor(grab->cursor, (Cursor) 0);
if (!wasImplicit && grab->grabtype == XI2) if (!wasImplicit && grab->grabtype == XI2)
ReattachToOldMaster(mouse); ReattachToOldMaster(mouse);
ComputeFreezes(); ComputeFreezes();
FreeGrab(grab);
} }
/** /**
@ -1566,6 +1567,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
Bool passive) Bool passive)
{ {
GrabInfoPtr grabinfo = &keybd->deviceGrab; GrabInfoPtr grabinfo = &keybd->deviceGrab;
GrabPtr oldgrab = grabinfo->grab;
WindowPtr oldWin; WindowPtr oldWin;
/* slave devices need to float for the duration of the grab. */ /* slave devices need to float for the duration of the grab. */
@ -1591,12 +1593,13 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
grabinfo->grabTime = syncEvents.time; grabinfo->grabTime = syncEvents.time;
else else
grabinfo->grabTime = time; grabinfo->grabTime = time;
CopyGrab(grabinfo->activeGrab, grab); grabinfo->grab = AllocGrab(grab);
grabinfo->grab = grabinfo->activeGrab;
grabinfo->fromPassiveGrab = passive; grabinfo->fromPassiveGrab = passive;
grabinfo->implicitGrab = passive & ImplicitGrabMask; grabinfo->implicitGrab = passive & ImplicitGrabMask;
CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode,
(Bool) grab->pointerMode); (Bool) grab->pointerMode);
if (oldgrab)
FreeGrab(oldgrab);
} }
/** /**
@ -1638,6 +1641,8 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
ReattachToOldMaster(keybd); ReattachToOldMaster(keybd);
ComputeFreezes(); ComputeFreezes();
FreeGrab(grab);
} }
void void
@ -1742,6 +1747,16 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
} }
break; break;
} }
/* We've unfrozen the grab. If the grab was a touch grab, we're now the
* owner and expected to accept/reject it. Reject == ReplayPointer which
* we've handled in ComputeFreezes() (during DeactivateGrab) above,
* anything else is accept.
*/
if (newState != NOT_GRABBED /* Replay */ &&
IsTouchEvent((InternalEvent*)grabinfo->sync.event)) {
TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid);
}
} }
/** /**
@ -1974,7 +1989,7 @@ ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
else else
return FALSE; return FALSE;
tempGrab = AllocGrab(); tempGrab = AllocGrab(NULL);
if (!tempGrab) if (!tempGrab)
return FALSE; return FALSE;
tempGrab->next = NULL; tempGrab->next = NULL;
@ -3194,11 +3209,10 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
pSprite->pEnqueueScreen = screenInfo.screens[0]; pSprite->pEnqueueScreen = screenInfo.screens[0];
pSprite->pDequeueScreen = pSprite->pEnqueueScreen; pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
} }
if (pCursor) pCursor = RefCursor(pCursor);
pCursor->refcnt++;
if (pSprite->current) if (pSprite->current)
FreeCursor(pSprite->current, None); FreeCursor(pSprite->current, None);
pSprite->current = pCursor; pSprite->current = RefCursor(pCursor);
if (pScreen) { if (pScreen) {
(*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current); (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
@ -3277,9 +3291,7 @@ UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
pSprite->hotLimits.x2 = pScreen->width; pSprite->hotLimits.x2 = pScreen->width;
pSprite->hotLimits.y2 = pScreen->height; pSprite->hotLimits.y2 = pScreen->height;
pSprite->win = win; pSprite->win = win;
pCursor = wCursor(win); pCursor = RefCursor(wCursor(win));
if (pCursor)
pCursor->refcnt++;
if (pSprite->current) if (pSprite->current)
FreeCursor(pSprite->current, 0); FreeCursor(pSprite->current, 0);
pSprite->current = pCursor; pSprite->current = pCursor;
@ -3881,7 +3893,7 @@ CheckPassiveGrabsOnWindow(WindowPtr pWin,
if (!grab) if (!grab)
return NULL; return NULL;
tempGrab = AllocGrab(); tempGrab = AllocGrab(NULL);
/* Fill out the grab details, but leave the type for later before /* Fill out the grab details, but leave the type for later before
* comparing */ * comparing */
@ -4839,7 +4851,6 @@ ProcGrabPointer(ClientPtr client)
GrabPtr grab; GrabPtr grab;
GrabMask mask; GrabMask mask;
WindowPtr confineTo; WindowPtr confineTo;
CursorPtr oldCursor;
BYTE status; BYTE status;
REQUEST(xGrabPointerReq); REQUEST(xGrabPointerReq);
@ -4862,15 +4873,10 @@ ProcGrabPointer(ClientPtr client)
return rc; return rc;
} }
oldCursor = NullCursor;
grab = device->deviceGrab.grab; grab = device->deviceGrab.grab;
if (grab) { if (grab && grab->confineTo && !confineTo)
if (grab->confineTo && !confineTo) ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE);
ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE,
FALSE);
oldCursor = grab->cursor;
}
mask.core = stuff->eventMask; mask.core = stuff->eventMask;
@ -4880,9 +4886,6 @@ ProcGrabPointer(ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
if (oldCursor && status == GrabSuccess)
FreeCursor(oldCursor, (Cursor) 0);
rep = (xGrabPointerReply) { rep = (xGrabPointerReply) {
.type = X_Reply, .type = X_Reply,
.status = status, .status = status,
@ -4938,9 +4941,7 @@ ProcChangeActivePointerGrab(ClientPtr client)
(CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
return Success; return Success;
oldCursor = grab->cursor; oldCursor = grab->cursor;
grab->cursor = newCursor; grab->cursor = RefCursor(newCursor);
if (newCursor)
newCursor->refcnt++;
PostNewCursor(device); PostNewCursor(device);
if (oldCursor) if (oldCursor)
FreeCursor(oldCursor, (Cursor) 0); FreeCursor(oldCursor, (Cursor) 0);
@ -5070,7 +5071,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
else { else {
GrabPtr tempGrab; GrabPtr tempGrab;
tempGrab = AllocGrab(); tempGrab = AllocGrab(NULL);
tempGrab->next = NULL; tempGrab->next = NULL;
tempGrab->window = pWin; tempGrab->window = pWin;
@ -5085,7 +5086,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
else else
xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
tempGrab->device = dev; tempGrab->device = dev;
tempGrab->cursor = cursor; tempGrab->cursor = RefCursor(cursor);
tempGrab->confineTo = confineTo; tempGrab->confineTo = confineTo;
tempGrab->grabtype = grabtype; tempGrab->grabtype = grabtype;
(*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE);
@ -5426,7 +5427,7 @@ ProcUngrabKey(ClientPtr client)
client->errorValue = stuff->modifiers; client->errorValue = stuff->modifiers;
return BadValue; return BadValue;
} }
tempGrab = AllocGrab(); tempGrab = AllocGrab(NULL);
if (!tempGrab) if (!tempGrab)
return BadAlloc; return BadAlloc;
tempGrab->resource = client->clientAsMask; tempGrab->resource = client->clientAsMask;
@ -5620,7 +5621,7 @@ ProcUngrabButton(ClientPtr client)
ptr = PickPointer(client); ptr = PickPointer(client);
tempGrab = AllocGrab(); tempGrab = AllocGrab(NULL);
if (!tempGrab) if (!tempGrab)
return BadAlloc; return BadAlloc;
tempGrab->resource = client->clientAsMask; tempGrab->resource = client->clientAsMask;

View File

@ -189,7 +189,7 @@ UngrabAllDevices(Bool kill_client)
} }
GrabPtr GrabPtr
AllocGrab(void) AllocGrab(const GrabPtr src)
{ {
GrabPtr grab = calloc(1, sizeof(GrabRec)); GrabPtr grab = calloc(1, sizeof(GrabRec));
@ -201,6 +201,12 @@ AllocGrab(void)
} }
} }
if (src && !CopyGrab(grab, src)) {
free(grab->xi2mask);
free(grab);
grab = NULL;
}
return grab; return grab;
} }
@ -213,7 +219,7 @@ CreateGrab(int client, DeviceIntPtr device, DeviceIntPtr modDevice,
{ {
GrabPtr grab; GrabPtr grab;
grab = AllocGrab(); grab = AllocGrab(NULL);
if (!grab) if (!grab)
return (GrabPtr) NULL; return (GrabPtr) NULL;
grab->resource = FakeClientID(client); grab->resource = FakeClientID(client);
@ -235,13 +241,11 @@ CreateGrab(int client, DeviceIntPtr device, DeviceIntPtr modDevice,
grab->detail.exact = keybut; grab->detail.exact = keybut;
grab->detail.pMask = NULL; grab->detail.pMask = NULL;
grab->confineTo = confineTo; grab->confineTo = confineTo;
grab->cursor = cursor; grab->cursor = RefCursor(cursor);
grab->next = NULL; grab->next = NULL;
if (grabtype == XI2) if (grabtype == XI2)
xi2mask_merge(grab->xi2mask, mask->xi2mask); xi2mask_merge(grab->xi2mask, mask->xi2mask);
if (cursor)
cursor->refcnt++;
return grab; return grab;
} }
@ -249,8 +253,7 @@ CreateGrab(int client, DeviceIntPtr device, DeviceIntPtr modDevice,
void void
FreeGrab(GrabPtr pGrab) FreeGrab(GrabPtr pGrab)
{ {
if (pGrab->grabtype == XI2 && pGrab->type == XI_TouchBegin) BUG_RETURN(!pGrab);
TouchListenerGone(pGrab->resource);
free(pGrab->modifiersDetail.pMask); free(pGrab->modifiersDetail.pMask);
free(pGrab->detail.pMask); free(pGrab->detail.pMask);
@ -269,9 +272,6 @@ CopyGrab(GrabPtr dst, const GrabPtr src)
Mask *details_mask = NULL; Mask *details_mask = NULL;
XI2Mask *xi2mask; XI2Mask *xi2mask;
if (src->cursor)
src->cursor->refcnt++;
if (src->modifiersDetail.pMask) { if (src->modifiersDetail.pMask) {
int len = MasksPerDetailMask * sizeof(Mask); int len = MasksPerDetailMask * sizeof(Mask);
@ -309,6 +309,7 @@ CopyGrab(GrabPtr dst, const GrabPtr src)
dst->modifiersDetail.pMask = mdetails_mask; dst->modifiersDetail.pMask = mdetails_mask;
dst->detail.pMask = details_mask; dst->detail.pMask = details_mask;
dst->xi2mask = xi2mask; dst->xi2mask = xi2mask;
dst->cursor = RefCursor(src->cursor);
xi2mask_merge(dst->xi2mask, src->xi2mask); xi2mask_merge(dst->xi2mask, src->xi2mask);

View File

@ -263,6 +263,7 @@ void
TouchFreeTouchPoint(DeviceIntPtr device, int index) TouchFreeTouchPoint(DeviceIntPtr device, int index)
{ {
TouchPointInfoPtr ti; TouchPointInfoPtr ti;
int i;
if (!device->touch || index >= device->touch->num_touches) if (!device->touch || index >= device->touch->num_touches)
return; return;
@ -271,6 +272,9 @@ TouchFreeTouchPoint(DeviceIntPtr device, int index)
if (ti->active) if (ti->active)
TouchEndTouch(device, ti); TouchEndTouch(device, ti);
for (i = 0; i < ti->num_listeners; i++)
TouchRemoveListener(ti, ti->listeners[0].listener);
valuator_mask_free(&ti->valuators); valuator_mask_free(&ti->valuators);
free(ti->sprite.spriteTrace); free(ti->sprite.spriteTrace);
ti->sprite.spriteTrace = NULL; ti->sprite.spriteTrace = NULL;
@ -365,6 +369,8 @@ TouchBeginTouch(DeviceIntPtr dev, int sourceid, uint32_t touchid,
void void
TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti) TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
{ {
int i;
if (ti->emulate_pointer) { if (ti->emulate_pointer) {
GrabPtr grab; GrabPtr grab;
@ -376,6 +382,9 @@ TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
} }
} }
for (i = 0; i < ti->num_listeners; i++)
TouchRemoveListener(ti, ti->listeners[0].listener);
ti->active = FALSE; ti->active = FALSE;
ti->pending_finish = FALSE; ti->pending_finish = FALSE;
ti->sprite.spriteTraceGood = 0; ti->sprite.spriteTraceGood = 0;
@ -474,7 +483,21 @@ 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;
DeliverTouchEvents(dev, ti, (InternalEvent *) ev, resource); ev->resource = resource;
/* FIXME:
We're replaying ti->history which contains the TouchBegin +
all TouchUpdates for ti. This needs to be passed on to the next
listener. If that is a touch listener, everything is dandy.
If the TouchBegin however triggers a sync passive grab, the
TouchUpdate events must be sent to EnqueueEvent so the events end
up in syncEvents.pending to be forwarded correctly in a
subsequent ComputeFreeze().
However, if we just send them to EnqueueEvent the sync'ing device
prevents handling of touch events for ownership listeners who
want the events right here, right now.
*/
dev->public.processInputProc((InternalEvent*)ev, dev);
} }
} }
@ -678,15 +701,23 @@ void
TouchAddListener(TouchPointInfoPtr ti, XID resource, int resource_type, TouchAddListener(TouchPointInfoPtr ti, XID resource, int resource_type,
enum InputLevel level, enum TouchListenerType type, enum InputLevel level, enum TouchListenerType type,
enum TouchListenerState state, WindowPtr window, enum TouchListenerState state, WindowPtr window,
GrabPtr grab) const GrabPtr grab)
{ {
GrabPtr g = NULL;
/* We need a copy of the grab, not the grab itself since that may be
* deleted by a UngrabButton request and leaves us with a dangling
* pointer */
if (grab)
g = AllocGrab(grab);
ti->listeners[ti->num_listeners].listener = resource; ti->listeners[ti->num_listeners].listener = resource;
ti->listeners[ti->num_listeners].resource_type = resource_type; ti->listeners[ti->num_listeners].resource_type = resource_type;
ti->listeners[ti->num_listeners].level = level; ti->listeners[ti->num_listeners].level = level;
ti->listeners[ti->num_listeners].state = state; ti->listeners[ti->num_listeners].state = state;
ti->listeners[ti->num_listeners].type = type; ti->listeners[ti->num_listeners].type = type;
ti->listeners[ti->num_listeners].window = window; ti->listeners[ti->num_listeners].window = window;
ti->listeners[ti->num_listeners].grab = grab; ti->listeners[ti->num_listeners].grab = g;
if (grab) if (grab)
ti->num_grabs++; ti->num_grabs++;
ti->num_listeners++; ti->num_listeners++;
@ -704,21 +735,25 @@ TouchRemoveListener(TouchPointInfoPtr ti, XID resource)
int i; int i;
for (i = 0; i < ti->num_listeners; i++) { for (i = 0; i < ti->num_listeners; i++) {
if (ti->listeners[i].listener == resource) { int j;
int j; TouchListener *listener = &ti->listeners[i];
if (ti->listeners[i].grab) { if (listener->listener != resource)
ti->listeners[i].grab = NULL; continue;
ti->num_grabs--;
}
for (j = i; j < ti->num_listeners - 1; j++) if (listener->grab) {
ti->listeners[j] = ti->listeners[j + 1]; FreeGrab(listener->grab);
ti->num_listeners--; listener->grab = NULL;
ti->listeners[ti->num_listeners].listener = 0; ti->num_grabs--;
ti->listeners[ti->num_listeners].state = LISTENER_AWAITING_BEGIN;
return TRUE;
} }
for (j = i; j < ti->num_listeners - 1; j++)
ti->listeners[j] = ti->listeners[j + 1];
ti->num_listeners--;
ti->listeners[ti->num_listeners].listener = 0;
ti->listeners[ti->num_listeners].state = LISTENER_AWAITING_BEGIN;
return TRUE;
} }
return FALSE; return FALSE;
} }
@ -874,7 +909,7 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
SpritePtr sprite = &ti->sprite; SpritePtr sprite = &ti->sprite;
WindowPtr win; WindowPtr win;
if (dev->deviceGrab.grab) if (dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab)
TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab); TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
/* We set up an active touch listener for existing touches, but not any /* We set up an active touch listener for existing touches, but not any
@ -954,11 +989,11 @@ TouchListenerGone(XID resource)
continue; continue;
for (j = 0; j < ti->num_listeners; j++) { for (j = 0; j < ti->num_listeners; j++) {
if (ti->listeners[j].listener != resource) if (CLIENT_BITS(ti->listeners[j].listener) != resource)
continue; continue;
nev = GetTouchOwnershipEvents(events, dev, ti, XIRejectTouch, nev = GetTouchOwnershipEvents(events, dev, ti, XIRejectTouch,
resource, 0); ti->listeners[j].listener, 0);
for (k = 0; k < nev; k++) for (k = 0; k < nev; k++)
mieqProcessDeviceEvent(dev, events + k, NULL); mieqProcessDeviceEvent(dev, events + k, NULL);
@ -1061,3 +1096,46 @@ TouchEndPhysicallyActiveTouches(DeviceIntPtr dev)
FreeEventList(eventlist, GetMaximumEventsNum()); FreeEventList(eventlist, GetMaximumEventsNum());
} }
/**
* Generate and deliver a TouchEnd event.
*
* @param dev The device to deliver the event for.
* @param ti The touch point record to deliver the event for.
* @param flags Internal event flags. The called does not need to provide
* TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
* they are set appropriately.
* @param resource The client resource to deliver to, or 0 for all clients.
*/
void
TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
{
InternalEvent event;
/* We're not processing a touch end for a frozen device */
if (dev->deviceGrab.sync.frozen)
return;
flags |= TOUCH_CLIENT_ID;
if (ti->emulate_pointer)
flags |= TOUCH_POINTER_EMULATED;
TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource);
GetDixTouchEnd(&event, dev, ti, flags);
DeliverTouchEvents(dev, ti, &event, resource);
if (ti->num_grabs == 0)
UpdateDeviceState(dev, &event.device_event);
}
void
TouchAcceptAndEnd(DeviceIntPtr dev, int touchid)
{
TouchPointInfoPtr ti = TouchFindByClientID(dev, touchid);
if (!ti)
return;
TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
if (ti->pending_finish)
TouchEmitTouchEnd(dev, ti, 0, 0);
if (ti->num_listeners <= 1)
TouchEndTouch(dev, ti);
}

View File

@ -547,8 +547,7 @@ InitRootWindow(WindowPtr pWin)
(*pScreen->PositionWindow) (pWin, 0, 0); (*pScreen->PositionWindow) (pWin, 0, 0);
pWin->cursorIsNone = FALSE; pWin->cursorIsNone = FALSE;
pWin->optional->cursor = rootCursor; pWin->optional->cursor = RefCursor(rootCursor);
rootCursor->refcnt++;
if (party_like_its_1989) { if (party_like_its_1989) {
MakeRootTile(pWin); MakeRootTile(pWin);
@ -1416,8 +1415,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
else if (pWin->parent && pCursor == wCursor(pWin->parent)) else if (pWin->parent && pCursor == wCursor(pWin->parent))
checkOptional = TRUE; checkOptional = TRUE;
pOldCursor = pWin->optional->cursor; pOldCursor = pWin->optional->cursor;
pWin->optional->cursor = pCursor; pWin->optional->cursor = RefCursor(pCursor);
pCursor->refcnt++;
pWin->cursorIsNone = FALSE; pWin->cursorIsNone = FALSE;
/* /*
* check on any children now matching the new cursor * check on any children now matching the new cursor
@ -3323,8 +3321,7 @@ MakeWindowOptional(WindowPtr pWin)
parentOptional = FindWindowWithOptional(pWin)->optional; parentOptional = FindWindowWithOptional(pWin)->optional;
optional->visual = parentOptional->visual; optional->visual = parentOptional->visual;
if (!pWin->cursorIsNone) { if (!pWin->cursorIsNone) {
optional->cursor = parentOptional->cursor; optional->cursor = RefCursor(parentOptional->cursor);
optional->cursor->refcnt++;
} }
else { else {
optional->cursor = None; optional->cursor = None;
@ -3412,8 +3409,7 @@ ChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor)
if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor)) if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
pNode->cursor = None; pNode->cursor = None;
else { else {
pNode->cursor = pCursor; pNode->cursor = RefCursor(pCursor);
pCursor->refcnt++;
} }
pNode = pPrev = NULL; pNode = pPrev = NULL;
@ -3421,8 +3417,7 @@ ChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor)
for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) { if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) {
if (pNode->cursor == None) { /* inherited from parent */ if (pNode->cursor == None) { /* inherited from parent */
pNode->cursor = pOldCursor; pNode->cursor = RefCursor(pOldCursor);
pOldCursor->refcnt++;
} }
else if (pNode->cursor == pCursor) { else if (pNode->cursor == pCursor) {
pNode->cursor = None; pNode->cursor = None;

View File

@ -481,7 +481,7 @@ xf86_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
++cursor->refcnt; cursor = RefCursor(cursor);
if (xf86_config->cursor) if (xf86_config->cursor)
FreeCursor(xf86_config->cursor, None); FreeCursor(xf86_config->cursor, None);
xf86_config->cursor = cursor; xf86_config->cursor = cursor;
@ -500,7 +500,7 @@ xf86_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor)
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
++cursor->refcnt; cursor = RefCursor(cursor);
if (xf86_config->cursor) if (xf86_config->cursor)
FreeCursor(xf86_config->cursor, None); FreeCursor(xf86_config->cursor, None);
xf86_config->cursor = cursor; xf86_config->cursor = cursor;

View File

@ -271,7 +271,7 @@ xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
(xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
xf86CursorScreenKey); xf86CursorScreenKey);
if (pCurs->refcnt <= 1) if (CursorRefCount(pCurs) <= 1)
dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
NULL); NULL);
@ -285,7 +285,7 @@ xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
(xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
xf86CursorScreenKey); xf86CursorScreenKey);
if (pCurs->refcnt <= 1) { if (CursorRefCount(pCurs) <= 1) {
free(dixLookupScreenPrivate free(dixLookupScreenPrivate
(&pCurs->devPrivates, CursorScreenKey, pScreen)); (&pCurs->devPrivates, CursorScreenKey, pScreen));
dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
@ -322,37 +322,37 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
/* only update for VCP, otherwise we get cursor jumps when removing a /* only update for VCP, otherwise we get cursor jumps when removing a
sprite. The second cursor is never HW rendered anyway. */ sprite. The second cursor is never HW rendered anyway. */
if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) { if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) {
pCurs->refcnt++; CursorPtr cursor = RefCursor(pCurs);
if (ScreenPriv->CurrentCursor) if (ScreenPriv->CurrentCursor)
FreeCursor(ScreenPriv->CurrentCursor, None); FreeCursor(ScreenPriv->CurrentCursor, None);
ScreenPriv->CurrentCursor = pCurs; ScreenPriv->CurrentCursor = cursor;
ScreenPriv->x = x; ScreenPriv->x = x;
ScreenPriv->y = y; ScreenPriv->y = y;
ScreenPriv->CursorToRestore = NULL; ScreenPriv->CursorToRestore = NULL;
ScreenPriv->HotX = pCurs->bits->xhot; ScreenPriv->HotX = cursor->bits->xhot;
ScreenPriv->HotY = pCurs->bits->yhot; ScreenPriv->HotY = cursor->bits->yhot;
if (!infoPtr->pScrn->vtSema) if (!infoPtr->pScrn->vtSema)
ScreenPriv->SavedCursor = pCurs; ScreenPriv->SavedCursor = cursor;
if (infoPtr->pScrn->vtSema && xorg_list_is_empty(&pScreen->pixmap_dirty_list) && if (infoPtr->pScrn->vtSema && xorg_list_is_empty(&pScreen->pixmap_dirty_list) &&
(ScreenPriv->ForceHWCursorCount || (ScreenPriv->ForceHWCursorCount ||
(( ((
#ifdef ARGB_CURSOR #ifdef ARGB_CURSOR
pCurs->bits->argb && cursor->bits->argb &&
infoPtr->UseHWCursorARGB && infoPtr->UseHWCursorARGB &&
(*infoPtr->UseHWCursorARGB)(pScreen, pCurs)) || (*infoPtr->UseHWCursorARGB)(pScreen, cursor)) ||
(pCurs->bits->argb == 0 && (cursor->bits->argb == 0 &&
#endif #endif
(pCurs->bits->height <= infoPtr->MaxHeight) && (cursor->bits->height <= infoPtr->MaxHeight) &&
(pCurs->bits->width <= infoPtr->MaxWidth) && (cursor->bits->width <= infoPtr->MaxWidth) &&
(!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, pCurs)))))) { (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, cursor)))))) {
if (ScreenPriv->SWCursor) /* remove the SW cursor */ if (ScreenPriv->SWCursor) /* remove the SW cursor */
(*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen,
NullCursor, x, y); NullCursor, x, y);
xf86SetCursor(pScreen, pCurs, x, y); xf86SetCursor(pScreen, cursor, x, y);
ScreenPriv->SWCursor = FALSE; ScreenPriv->SWCursor = FALSE;
ScreenPriv->isUp = TRUE; ScreenPriv->isUp = TRUE;

View File

@ -71,6 +71,10 @@ extern _X_EXPORT CursorPtr rootCursor;
extern _X_EXPORT int FreeCursor(pointer /*pCurs */ , extern _X_EXPORT int FreeCursor(pointer /*pCurs */ ,
XID /*cid */ ); XID /*cid */ );
extern _X_EXPORT CursorPtr RefCursor(CursorPtr /* cursor */);
extern _X_EXPORT CursorPtr UnrefCursor(CursorPtr /* cursor */);
extern _X_EXPORT int CursorRefCount(const CursorPtr /* cursor */);
extern _X_EXPORT int AllocARGBCursor(unsigned char * /*psrcbits */ , extern _X_EXPORT int AllocARGBCursor(unsigned char * /*psrcbits */ ,
unsigned char * /*pmaskbits */ , unsigned char * /*pmaskbits */ ,
CARD32 * /*argb */ , CARD32 * /*argb */ ,

View File

@ -31,7 +31,7 @@ struct _GrabParameters;
extern void PrintDeviceGrabInfo(DeviceIntPtr dev); extern void PrintDeviceGrabInfo(DeviceIntPtr dev);
extern void UngrabAllDevices(Bool kill_client); extern void UngrabAllDevices(Bool kill_client);
extern GrabPtr AllocGrab(void); extern GrabPtr AllocGrab(const GrabPtr src);
extern void FreeGrab(GrabPtr grab); extern void FreeGrab(GrabPtr grab);
extern Bool CopyGrab(GrabPtr dst, const GrabPtr src); extern Bool CopyGrab(GrabPtr dst, const GrabPtr src);

View File

@ -123,6 +123,7 @@ struct _DeviceEvent {
int corestate; /**< Core key/button state BEFORE the event */ int corestate; /**< Core key/button state BEFORE the event */
int key_repeat; /**< Internally-generated key repeat event */ int key_repeat; /**< Internally-generated key repeat event */
uint32_t flags; /**< Flags to be copied into the generated event */ uint32_t flags; /**< Flags to be copied into the generated event */
uint32_t resource; /**< Touch event resource, only for TOUCH_REPLAYING */
}; };
/** /**

View File

@ -590,6 +590,8 @@ extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev); extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev);
extern void TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti, extern void TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti,
Time time, XID resource); Time time, XID resource);
extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource);
extern void TouchAcceptAndEnd(DeviceIntPtr dev, int touchid);
/* misc event helpers */ /* misc event helpers */
extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients); extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients);

View File

@ -485,7 +485,7 @@ typedef struct _GrabInfoRec {
TimeStamp grabTime; TimeStamp grabTime;
Bool fromPassiveGrab; /* true if from passive grab */ Bool fromPassiveGrab; /* true if from passive grab */
Bool implicitGrab; /* implicit from ButtonPress */ Bool implicitGrab; /* implicit from ButtonPress */
GrabPtr activeGrab; GrabPtr unused; /* Kept for ABI stability, remove soon */
GrabPtr grab; GrabPtr grab;
CARD8 activatingKey; CARD8 activatingKey;
void (*ActivateGrab) (DeviceIntPtr /*device */ , void (*ActivateGrab) (DeviceIntPtr /*device */ ,

View File

@ -383,8 +383,7 @@ AnimCursorCreate(CursorPtr *cursors, CARD32 *deltas, int ncursor,
ac->elts = (AnimCurElt *) (ac + 1); ac->elts = (AnimCurElt *) (ac + 1);
for (i = 0; i < ncursor; i++) { for (i = 0; i < ncursor; i++) {
cursors[i]->refcnt++; ac->elts[i].pCursor = RefCursor(cursors[i]);
ac->elts[i].pCursor = cursors[i];
ac->elts[i].delay = deltas[i]; ac->elts[i].delay = deltas[i];
} }

View File

@ -613,12 +613,12 @@ ReplaceCursorLookup(pointer value, XID id, pointer closure)
} }
if (pCursor && pCursor != rcl->pNew) { if (pCursor && pCursor != rcl->pNew) {
if ((*rcl->testCursor) (pCursor, rcl->closure)) { if ((*rcl->testCursor) (pCursor, rcl->closure)) {
rcl->pNew->refcnt++; CursorPtr curs = RefCursor(rcl->pNew);
/* either redirect reference or update resource database */ /* either redirect reference or update resource database */
if (pCursorRef) if (pCursorRef)
*pCursorRef = rcl->pNew; *pCursorRef = curs;
else else
ChangeResourceValue(id, RT_CURSOR, rcl->pNew); ChangeResourceValue(id, RT_CURSOR, curs);
FreeCursor(pCursor, cursor); FreeCursor(pCursor, cursor);
} }
} }