diff options
author | Joel Bosveld <Joel.Bosveld@gmail.com> | 2009-06-26 16:55:39 +0800 |
---|---|---|
committer | Joel Bosveld <Joel.Bosveld@gmail.com> | 2009-06-26 16:55:39 +0800 |
commit | 2cea332a7d0a54071b8dbb5a8153894063c92136 (patch) | |
tree | 3533433c96dd64498f637466d88f431a93d7ed7f | |
parent | 5cf0b4a333426b64d11ace31d3ae7009f482d0d4 (diff) |
composite: first stab at input redirection (rather than transformation)
TODO:
more checks on the windows
handle resizes, unmaps, ...
prevent children from being created on redirected windows
and more
-rw-r--r-- | composite/compalloc.c | 31 | ||||
-rw-r--r-- | composite/compext.c | 54 | ||||
-rw-r--r-- | composite/compint.h | 54 | ||||
-rw-r--r-- | composite/compwindow.c | 110 | ||||
-rw-r--r-- | dix/devices.c | 3 | ||||
-rw-r--r-- | dix/dispatch.c | 6 | ||||
-rw-r--r-- | dix/events.c | 31 | ||||
-rw-r--r-- | include/inputstr.h | 5 |
8 files changed, 250 insertions, 44 deletions
diff --git a/composite/compalloc.c b/composite/compalloc.c index 3372c151d..d5d15592e 100644 --- a/composite/compalloc.c +++ b/composite/compalloc.c @@ -150,6 +150,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) cw->damageRegistered = FALSE; cw->damaged = FALSE; cw->pInputMesh = NULL; + cw->redirectInfo.pDest = NULL; + cw->redirectInfo.redirected = NULL; + cw->redirectInfo.nRedirected = 0; dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); } ccw->next = cw->clients; @@ -236,6 +239,34 @@ compFreeClientWindow (WindowPtr pWin, XID id) if (cw->pInputMesh) xfree (cw->pInputMesh); + if (cw->redirectInfo.pDest) + { + CompWindowPtr crw = GetCompWindow (cw->redirectInfo.pDest); + int i; + for (i = 0; i < crw->redirectInfo.nRedirected; i++) + { + if (crw->redirectInfo.redirected[i] == pWin) + { + crw->redirectInfo.redirected[i] = + crw->redirectInfo.redirected[ + --crw->redirectInfo.nRedirected]; + /* maybe redirected should be realloc'd */ + } + } + } + + if (cw->redirectInfo.redirected) + { + int i; + for (i = 0; i < cw->redirectInfo.nRedirected; i++) + { + CompWindowPtr crw = GetCompWindow ( + cw->redirectInfo.redirected[i]); + crw->redirectInfo.pDest = NULL; + } + xfree (cw->redirectInfo.redirected); + } + REGION_UNINIT (pScreen, &cw->borderClip); dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); diff --git a/composite/compext.c b/composite/compext.c index 6a031c9ba..1a57fefc1 100644 --- a/composite/compext.c +++ b/composite/compext.c @@ -405,6 +405,41 @@ ProcCompositeSetTriangularCoordinateMesh (ClientPtr client) return client->noClientException; } +static int +ProcCompositeRedirectWindowInput (ClientPtr client) +{ + WindowPtr pWin, pDest; + CompWindowPtr cw; + + REQUEST(xCompositeRedirectWindowInputReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectWindowInputReq); + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess|DixManageAccess|DixBlendAccess); + VERIFY_WINDOW(pDest, stuff->destination, client, + DixSetAttrAccess|DixManageAccess|DixBlendAccess); + + cw = GetCompWindow (pWin); + if (!cw) + { + client->errorValue = stuff->window; + return BadWindow; + } + + cw = GetCompWindow (pDest); + if (!cw) + { + client->errorValue = stuff->destination; + return BadWindow; + } + + /* XXX check that pWin isn't an ancestor of pDest + * XXX check pWin is input only with no children + */ + + return CompositeRedirectWindowInput (client, pWin, pDest); +} + static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { ProcCompositeQueryVersion, ProcCompositeRedirectWindow, @@ -415,7 +450,8 @@ static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { ProcCompositeNameWindowPixmap, ProcCompositeGetOverlayWindow, ProcCompositeReleaseOverlayWindow, - ProcCompositeSetTriangularCoordinateMesh + ProcCompositeSetTriangularCoordinateMesh, + ProcCompositeRedirectWindowInput }; static int @@ -555,6 +591,19 @@ SProcCompositeSetTriangularCoordinateMesh (ClientPtr client) return (*ProcCompositeVector[stuff->compositeReqType]) (client); } +static int +SProcCompositeRedirectWindowInput (ClientPtr client) +{ + int n; + REQUEST(xCompositeRedirectWindowInputReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCompositeRedirectWindowInputReq); + swapl (&stuff->window, n); + swapl (&stuff->destination, n); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { SProcCompositeQueryVersion, SProcCompositeRedirectWindow, @@ -565,7 +614,8 @@ static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { SProcCompositeNameWindowPixmap, SProcCompositeGetOverlayWindow, SProcCompositeReleaseOverlayWindow, - SProcCompositeSetTriangularCoordinateMesh + SProcCompositeSetTriangularCoordinateMesh, + SProcCompositeRedirectWindowInput }; static int diff --git a/composite/compint.h b/composite/compint.h index 7975b9cfe..e4f47b64d 100644 --- a/composite/compint.h +++ b/composite/compint.h @@ -111,6 +111,12 @@ typedef struct _CompTriangularMesh { int nNorm; } CompTriangularMeshRec, *CompTriangularMeshPtr; +typedef struct _CompRedirectInfo { + WindowPtr pDest; /* where input of this window should be redirected */ + WindowPtr *redirected; /* windows which redirect to this one */ + int nRedirected; +} CompRedirectInfoRec; + typedef struct _CompWindow { RegionRec borderClip; DamagePtr damage; /* for automatic update mode */ @@ -123,6 +129,7 @@ typedef struct _CompWindow { PixmapPtr pOldPixmap; int borderClipX, borderClipY; CompTriangularMeshPtr pInputMesh; + CompRedirectInfoRec redirectInfo; } CompWindowRec, *CompWindowPtr; #define COMP_ORIGIN_INVALID 0x80000000 @@ -345,31 +352,35 @@ DeleteWindowNoInputDevices(pointer value, XID wid); Bool CompositeXYParentToChild (WindowPtr pChild, - int parentX, - int parentY, - int *childX, - int *childY); + WindowPtr pParent, + int parentX, + int parentY, + int *childX, + int *childY); Bool CompositeXYChildToParent (WindowPtr pChild, - int childX, - int childY, - int *parentX, - int *parentY); + WindowPtr pParent, + int childX, + int childY, + int *parentX, + int *parentY); void -CompositeXYScreenToWindowRootCoordinate (WindowPtr pWin, - int x, - int y, - int *rootX, - int *rootY); +CompositeXYScreenToWindowRootCoordinate (WindowPtr pWin, + DeviceIntPtr pDev, + int x, + int y, + int *rootX, + int *rootY); void -CompositeXYScreenFromWindowRootCoordinate (WindowPtr pWin, - int x, - int y, - int *screenX, - int *screenY); +CompositeXYScreenFromWindowRootCoordinate (WindowPtr pWin, + DeviceIntPtr pDev, + int x, + int y, + int *screenX, + int *screenY); int CompositeSetTriangularCoordinateMesh (ClientPtr pClient, @@ -380,5 +391,12 @@ CompositeSetTriangularCoordinateMesh (ClientPtr pClient, xTriangle *tri, unsigned flags); +WindowPtr +CompositeGetRedirectedWindowInput (WindowPtr pWin); + +int +CompositeRedirectWindowInput (ClientPtr pClient, + WindowPtr pWin, + WindowPtr pDest); #endif /* _COMPINT_H_ */ diff --git a/composite/compwindow.c b/composite/compwindow.c index 06c1c0c0d..4456125cc 100644 --- a/composite/compwindow.c +++ b/composite/compwindow.c @@ -941,6 +941,7 @@ XYMapPoint (CompTriangle *from, Bool CompositeXYParentToChild (WindowPtr pChild, + WindowPtr pParent, int parentX, int parentY, int *childX, @@ -948,6 +949,17 @@ CompositeXYParentToChild (WindowPtr pChild, { CompWindowPtr cw = GetCompWindow (pChild); + if (pParent || (pParent = pChild->parent)) + { + parentX -= pParent->drawable.x; + parentY -= pParent->drawable.y; + } + if (pChild->parent) + { + parentX += pChild->parent->drawable.x; + parentY += pChild->parent->drawable.y; + } + if (cw && cw->pInputMesh) { CompTriangleMap *map = cw->pInputMesh->map; @@ -999,6 +1011,7 @@ CompositeXYParentToChild (WindowPtr pChild, Bool CompositeXYChildToParent (WindowPtr pChild, + WindowPtr pParent, int childX, int childY, int *parentX, @@ -1006,6 +1019,17 @@ CompositeXYChildToParent (WindowPtr pChild, { CompWindowPtr cw = GetCompWindow (pChild); + if (pChild->parent) + { + childX -= pChild->parent->drawable.x; + childY -= pChild->parent->drawable.y; + } + if (pParent || (pParent = pChild->parent)) + { + childX += pParent->drawable.x; + childY += pParent->drawable.y; + } + if (cw && cw->pInputMesh) { CompTriangleMap *map = cw->pInputMesh->map; @@ -1025,10 +1049,10 @@ CompositeXYChildToParent (WindowPtr pChild, childX, childY, parentX, parentY); - if (pChild->parent) + if (pParent || (pParent = pChild->parent)) { - *parentX += pChild->parent->drawable.x; - *parentY += pChild->parent->drawable.y; + *parentX += pParent->drawable.x; + *parentY += pParent->drawable.y; } /* There is a mesh and the point was redirected, * handle as normal @@ -1056,35 +1080,59 @@ CompositeXYChildToParent (WindowPtr pChild, } void -CompositeXYScreenToWindowRootCoordinate (WindowPtr pWin, - int x, - int y, - int *rootX, - int *rootY) +CompositeXYScreenToWindowRootCoordinate (WindowPtr pWin, + DeviceIntPtr pDev, + int x, + int y, + int *rootX, + int *rootY) { - WindowPtr win = WindowTable[pWin->drawable.pScreen->myNum]; + WindowPtr win; + + if (pDev) + { + SpritePtr pSprite = pDev->spriteInfo->sprite; + int i; + for (i = 0; i < pSprite->spriteTraceGood; i++) + if (pWin == pSprite->spriteTraceUnredirected[i]) + { + int j; + for (j = 0; j < i; j++) + CompositeXYParentToChild ( + pSprite->spriteTraceUnredirected[j+1], + pSprite->spriteTraceUnredirected[j], + x, y, &x, &y); + *rootX = x; + *rootY = y; + return; + } + } + + win = WindowTable[pWin->drawable.pScreen->myNum]; + while (win != pWin) { WindowPtr tWin; - CompositeXYParentToChild (win, x, y, &x, &y); + CompositeXYParentToChild (win, NULL, x, y, &x, &y); for(tWin=pWin; tWin->parent != win; tWin=tWin->parent); win = tWin; } - CompositeXYParentToChild (pWin,x,y,rootX,rootY); + CompositeXYParentToChild (pWin, NULL, x, y, rootX, rootY); } void -CompositeXYScreenFromWindowRootCoordinate (WindowPtr pWin, - int x, - int y, - int *screenX, - int *screenY) +CompositeXYScreenFromWindowRootCoordinate (WindowPtr pWin, + DeviceIntPtr pDev, + int x, + int y, + int *screenX, + int *screenY) { while (pWin) { - CompositeXYChildToParent (pWin, x, y, &x, &y); + CompositeXYChildToParent (pWin, NULL, x, y, &x, &y); pWin = pWin->parent; } @@ -1204,3 +1252,31 @@ CompositeSetTriangularCoordinateMesh (ClientPtr pClient, } return 0; } + +WindowPtr +CompositeGetRedirectedWindowInput (WindowPtr pWin) +{ + CompWindowPtr cw = GetCompWindow (pWin); + return (cw && cw->redirectInfo.pDest) ? cw->redirectInfo.pDest : pWin; +} + +int +CompositeRedirectWindowInput (ClientPtr pClient, + WindowPtr pWin, + WindowPtr pDest) +{ + CompWindowPtr cw = GetCompWindow (pWin); + CompWindowPtr dw = GetCompWindow (pDest); + WindowPtr *tmp; + + cw->redirectInfo.pDest = pDest; + + tmp = xrealloc (dw->redirectInfo.redirected, + (dw->redirectInfo.nRedirected + 1) * sizeof (WindowPtr)); + if (!tmp) + return BadAlloc; + dw->redirectInfo.redirected = tmp; + dw->redirectInfo.redirected[dw->redirectInfo.nRedirected++] = pWin; + + return 0; +} diff --git a/dix/devices.c b/dix/devices.c index b237e03b1..7b3fe9b0f 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -895,6 +895,9 @@ CloseDevice(DeviceIntPtr dev) XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); if (DevHasCursor(dev) && dev->spriteInfo->sprite) { +#ifdef COMPOSITE + xfree(dev->spriteInfo->sprite->spriteTraceUnredirected); +#endif xfree(dev->spriteInfo->sprite->spriteTrace); xfree(dev->spriteInfo->sprite); } diff --git a/dix/dispatch.c b/dix/dispatch.c index 62e3fc0e5..7e193b26a 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -1193,8 +1193,8 @@ ProcTranslateCoords(ClientPtr client) * Transform from source window coordinate space to screen * and then to destination coordinate space. */ - CompositeXYScreenFromWindowRootCoordinate (pWin, x, y, &x, &y); - CompositeXYScreenToWindowRootCoordinate (pDst, x, y, &x, &y); + CompositeXYScreenFromWindowRootCoordinate (pWin, NULL, x, y, &x, &y); + CompositeXYScreenToWindowRootCoordinate (pDst, NULL, x, y, &x, &y); #endif /* adjust to destination coordinates */ @@ -1218,7 +1218,7 @@ ProcTranslateCoords(ClientPtr client) */ if (pWin->mapped) { - CompositeXYParentToChild (pWin, x, y, &x, &y); + CompositeXYParentToChild (pWin, NULL, x, y, &x, &y); } #endif diff --git a/dix/events.c b/dix/events.c index ea206f73d..75bb07428 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2280,7 +2280,7 @@ FixUpEventFromWindow( * Transform to windows root coordinate space before writing * events to client. */ - CompositeXYScreenToWindowRootCoordinate (pWin, root_x, root_y, + CompositeXYScreenToWindowRootCoordinate (pWin, pDev, root_x, root_y, &root_x, &root_y); root_x <<= 16; @@ -2317,7 +2317,7 @@ FixUpEventFromWindow( * Transform to windows root coordinate space before writing * events to client. */ - CompositeXYScreenToWindowRootCoordinate (pWin, root_x, root_y, + CompositeXYScreenToWindowRootCoordinate (pWin, pDev, root_x, root_y, &root_x, &root_y); #endif XE_KBPTR.sameScreen = xTrue; @@ -2638,7 +2638,9 @@ XYToWindow(DeviceIntPtr pDev, int rootX, int rootY) */ if (pWin->mapped) { - handle = CompositeXYParentToChild (pWin, x, y, &x, &y); + handle = CompositeXYParentToChild (pWin, + pSprite->spriteTraceUnredirected[pSprite->spriteTraceGood - 1], + x, y, &x, &y); } #endif @@ -2672,9 +2674,18 @@ XYToWindow(DeviceIntPtr pDev, int rootX, int rootY) if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) { pSprite->spriteTraceSize += 10; +#ifdef COMPOSITE + pSprite->spriteTraceUnredirected = xrealloc( + pSprite->spriteTraceUnredirected, + pSprite->spriteTraceSize*sizeof(WindowPtr)); +#endif pSprite->spriteTrace = xrealloc(pSprite->spriteTrace, pSprite->spriteTraceSize*sizeof(WindowPtr)); } +#ifdef COMPOSITE + pSprite->spriteTraceUnredirected[pSprite->spriteTraceGood] = pWin; + pWin = CompositeGetRedirectedWindowInput (pWin); +#endif pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; rootX = x; rootY = y; @@ -3014,6 +3025,12 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) { pSprite->current = wCursor(pWin); pSprite->current->refcnt++; +#ifdef COMPOSITE + pSprite->spriteTraceUnredirected = + (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr)); + if (!pSprite->spriteTraceUnredirected) + FatalError("Failed to allocate spriteTrace"); +#endif pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr)); if (!pSprite->spriteTrace) FatalError("Failed to allocate spriteTrace"); @@ -3027,6 +3044,9 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) } else { pSprite->current = NullCursor; +#ifdef COMPOSITE + pSprite->spriteTraceUnredirected = NULL; +#endif pSprite->spriteTrace = NULL; pSprite->spriteTraceSize = 0; pSprite->spriteTraceGood = 0; @@ -3103,6 +3123,9 @@ UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) pSprite->current = wCursor (win); pSprite->current->refcnt++; pSprite->spriteTraceGood = 1; +#ifdef COMPOSITE + pSprite->spriteTraceUnredirected[0] = win; +#endif pSprite->spriteTrace[0] = win; (*pScreen->CursorLimits) (pDev, pScreen, @@ -4972,7 +4995,7 @@ ProcQueryPointer(ClientPtr client) /* * Return coordinates in windows root coordinate space. */ - CompositeXYScreenToWindowRootCoordinate (pWin, rootX, rootY, + CompositeXYScreenToWindowRootCoordinate (pWin, NULL, rootX, rootY, &rootX, &rootY); #endif diff --git a/include/inputstr.h b/include/inputstr.h index b284ea4e9..7c4595a04 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -383,6 +383,11 @@ typedef struct { * windows must be checked. * spriteTraces should only be used at dix/events.c! */ WindowPtr *spriteTrace; +#ifdef COMPOSITE + /* the real (rather than redirected) heirachy, + * so we know which windows to transform with respect to */ + WindowPtr *spriteTraceUnredirected; +#endif int spriteTraceSize; int spriteTraceGood; |