summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Bosveld <Joel.Bosveld@gmail.com>2009-06-26 16:55:39 +0800
committerJoel Bosveld <Joel.Bosveld@gmail.com>2009-06-26 16:55:39 +0800
commit2cea332a7d0a54071b8dbb5a8153894063c92136 (patch)
tree3533433c96dd64498f637466d88f431a93d7ed7f
parent5cf0b4a333426b64d11ace31d3ae7009f482d0d4 (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.c31
-rw-r--r--composite/compext.c54
-rw-r--r--composite/compint.h54
-rw-r--r--composite/compwindow.c110
-rw-r--r--dix/devices.c3
-rw-r--r--dix/dispatch.c6
-rw-r--r--dix/events.c31
-rw-r--r--include/inputstr.h5
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;