[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freedesktop-xorg
Subject:    Re: [compiz] status of input redirection
From:       David Reveman <davidr () novell ! com>
Date:       2007-06-01 19:47:17
Message-ID: 1180727237.20101.25.camel () ion ! ximian
[Download RAW message or body]

On Fri, 2007-06-01 at 13:28 -0400, Kristian Høgsberg wrote:
> On 5/31/07, David Reveman <davidr@novell.com> wrote:
> > On Tue, 2007-05-29 at 08:53 +0200, dragoran wrote:
> > > There where some patches to implement input redirection in xorg a while
> > > ago...
> > > what happend to them? are they still beeing worked on?
> >
> > The attached patches work well. The server patch needs some more work if
> > we want to allow different pickers and I haven't had time to do that
> > yet.
> 
> Can we merge the server patch as is and punt on the pluggable picker
> idea for now?  I mean, can we do this in a way that lets the
> interested parties add this support in a second step without breaking
> backwards compatibility?  If that's doable, I don't think we need to
> block on the pluggable picker idea now.

I've attached a new patch with a more appropriate change to
WriteEventsToClient.

I'm OK with merging the patch in it's current state. Pluggable pickers
can definitely be added later without breaking backwards compatibility.

There's a few things that needs to be improved but I think the current
patch is good enough for common use in compositing managers.

TODO:

I've tried to move the event coordinate transformation into
FixUpEventFromWindow, which means making copies of events in a lot of
places as FixUpEventFromWindow is sometimes called multiple times with
the same xEvent. However, I never got that to work correctly and I
haven't had time to figure out exactly why yet.

The pointer grab code might need some more work but the patch should of
course not affect non-transformed input in any way.

I think that transformed input of non top-level windows isn't working
correctly. This should be easy to fix though, I just need to write a
good test app.

-David

["xserver-input-transform-3.patch" (xserver-input-transform-3.patch)]

--- a/composite/compalloc.c
+++ b/composite/compalloc.c
@@ -141,6 +141,7 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
 	cw->oldy = COMP_ORIGIN_INVALID;
 	cw->damageRegistered = FALSE;
 	cw->damaged = FALSE;
+	cw->pInputMesh = NULL;
 	pWin->devPrivates[CompWindowPrivateIndex].ptr = cw;
     }
     ccw->next = cw->clients;
--- a/composite/compext.c
+++ b/composite/compext.c
@@ -512,6 +512,45 @@ ProcCompositeReleaseOverlayWindow (ClientPtr client)
     return client->noClientException;
 }
 
+static int
+ProcCompositeSetTriangularCoordinateMesh (ClientPtr client)
+{
+    CompWindowPtr cw;
+    WindowPtr	  pWin;
+    int		  n, status;
+
+    REQUEST (xCompositeSetTriangularCoordinateMeshReq);
+    REQUEST_AT_LEAST_SIZE (xCompositeSetTriangularCoordinateMeshReq);
+
+    pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+    if (!pWin || !pWin->parent)
+    {
+	client->errorValue = stuff->window;
+	return BadWindow;
+    }
+
+    cw = GetCompWindow (pWin);
+    if (!cw)
+    {
+	client->errorValue = stuff->window;
+	return BadWindow;
+    }
+
+    n = (client->req_len << 2) -
+	sizeof (xCompositeSetTriangularCoordinateMeshReq);
+    if (n && (n % (sizeof (xTriangle) * 2)))
+	return BadLength;
+
+    n /= sizeof (xTriangle);
+
+    status = CompositeSetTriangularCoordinateMesh (client, pWin, n,
+						   (xTriangle *) &stuff[1]);
+    if (status)
+	return status;
+
+    return client->noClientException;
+}
+
 int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     ProcCompositeQueryVersion,
     ProcCompositeRedirectWindow,
@@ -522,6 +561,7 @@ int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     ProcCompositeNameWindowPixmap,
     ProcCompositeGetOverlayWindow,
     ProcCompositeReleaseOverlayWindow,
+    ProcCompositeSetTriangularCoordinateMesh
 };
 
 static int
@@ -646,6 +686,19 @@ SProcCompositeReleaseOverlayWindow (ClientPtr client)
     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
 }
 
+int
+SProcCompositeSetTriangularCoordinateMesh (ClientPtr client)
+{
+    int n;
+    REQUEST(xCompositeSetTriangularCoordinateMeshReq);
+
+    swaps (&stuff->length, n);
+    REQUEST_AT_LEAST_SIZE(xCompositeSetTriangularCoordinateMeshReq);
+    swapl (&stuff->window, n);
+    SwapRestL (stuff);
+    return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
 int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     SProcCompositeQueryVersion,
     SProcCompositeRedirectWindow,
@@ -656,6 +709,7 @@ int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     SProcCompositeNameWindowPixmap,
     SProcCompositeGetOverlayWindow,
     SProcCompositeReleaseOverlayWindow,
+    SProcCompositeSetTriangularCoordinateMesh
 };
 
 static int
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -85,6 +85,21 @@ typedef struct _CompClientWindow {
     int				update;
 }  CompClientWindowRec, *CompClientWindowPtr;
 
+typedef struct _CompTriangle {
+    xTriangle    tri;
+    xFixed_48_16 area;
+} CompTriangle;
+
+typedef struct _CompTriangleMap {
+    CompTriangle parent;
+    CompTriangle child;
+} CompTriangleMap;
+
+typedef struct _CompTriangularMesh {
+    CompTriangleMap *map;
+    int		    nMap;
+} CompTriangularMeshRec, *CompTriangularMeshPtr;
+
 typedef struct _CompWindow {
     RegionRec		    borderClip;
     DamagePtr		    damage;	/* for automatic update mode */
@@ -96,6 +111,7 @@ typedef struct _CompWindow {
     int			    oldy;
     PixmapPtr		    pOldPixmap;
     int			    borderClipX, borderClipY;
+    CompTriangularMeshPtr   pInputMesh;
 } CompWindowRec, *CompWindowPtr;
 
 #define COMP_ORIGIN_INVALID	    0x80000000
@@ -311,4 +327,38 @@ CompositeRealChildHead (WindowPtr pWin);
 int
 DeleteWindowNoInputDevices(pointer value, XID wid);
 
+void
+CompositeXYParentToChild (WindowPtr pChild,
+			  int	   parentX,
+			  int	   parentY,
+			  int	   *childX,
+			  int	   *childY);
+
+void
+CompositeXYChildToParent (WindowPtr pChild,
+			  int	   childX,
+			  int	   childY,
+			  int	   *parentX,
+			  int	   *parentY);
+
+void
+CompositeXYScreenToWindowRootCoordinate (WindowPtr pWin,
+					 int	   x,
+					 int	   y,
+					 int	   *rootX,
+					 int	   *rootY);
+
+void
+CompositeXYScreenFromWindowRootCoordinate (WindowPtr pWin,
+					   int	     x,
+					   int	     y,
+					   int	     *screenX,
+					   int	     *screenY);
+
+int
+CompositeSetTriangularCoordinateMesh (ClientPtr pClient,
+				      WindowPtr pWin,
+				      int	n,
+				      xTriangle *tri);
+
 #endif /* _COMPINT_H_ */
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -47,6 +47,7 @@
 #endif
 
 #include "compint.h"
+#include "inputstr.h"
 
 #ifdef COMPOSITE_DEBUG
 static int
@@ -812,3 +813,316 @@ CompositeRealChildHead (WindowPtr pWin)
 	return pChildBefore;
     }
 }
+
+static int
+Orientation (xPointFixed *v1,
+	     xPointFixed *v2,
+	     xPointFixed *p)
+{
+    xFixed_48_16 a, b, c;
+
+    a = (xFixed_48_16) (v2->x - v1->x) * (p->y  - v1->y);
+    b = (xFixed_48_16) (p->x  - v1->x) * (v2->y - v1->y);
+
+    c = a - b;
+
+    return (c > 0) ? 1 : (c < 0) ? -1 : 0;
+}
+
+static Bool
+PointInTriangle (xTriangle   *triangle,
+		 xPointFixed *p)
+{
+    int o1, o2, o3;
+
+    o1 = Orientation (&triangle->p1, &triangle->p2, p);
+    o2 = Orientation (&triangle->p2, &triangle->p3, p);
+    o3 = Orientation (&triangle->p3, &triangle->p1, p);
+
+    /*
+     * 0 orientation means point is on the edge and we allow that as it is
+     * better that two triangles with coincident edges overlap than that
+     * there is a gap between them.
+     */
+    if (o2 == 0)
+	o2 = o3;
+    if (o1 == 0)
+	o1 = o2;
+
+    /*
+     * Point is in triangle if edge orientation relative to opposite point is
+     * the same for all edges.
+     */
+    return (o1 == o2) && (o2 == o3);
+}
+
+static Bool
+XYInTriangle (xTriangle *triangle,
+	      int	x,
+	      int	y)
+{
+    xPointFixed p;
+
+    p.x = IntToxFixed (x);
+    p.y = IntToxFixed (y);
+
+    return PointInTriangle (triangle, &p);
+}
+
+static xFixed_48_16
+TriangleArea (xPointFixed *p1,
+	      xPointFixed *p2,
+	      xPointFixed *p3)
+{
+    return (((xFixed_48_16) p3->x - p2->x) *
+	    ((xFixed_48_16) p3->y - p1->y) -
+	    ((xFixed_48_16) p3->y - p2->y) *
+	    ((xFixed_48_16) p3->x - p1->x)) >> 16;
+}
+
+/*
+ * Inverse mapping of point P located in triangle.
+ */
+static void
+MapPoint (CompTriangle *from,
+	  CompTriangle *to,
+	  xPointFixed  *p,
+	  xPointFixed  *result)
+{
+    xFixed_48_16 u, v, w;
+    xFixed_48_16 x, y;
+
+    u = (TriangleArea (&from->tri.p1, &from->tri.p2, p) << 16) / from->area;
+    v = (TriangleArea (&from->tri.p3, &from->tri.p1, p) << 16) / from->area;
+    w = (TriangleArea (&from->tri.p2, &from->tri.p3, p) << 16) / from->area;
+
+    x = to->tri.p3.x * u + to->tri.p2.x * v + to->tri.p1.x * w;
+    y = to->tri.p3.y * u + to->tri.p2.y * v + to->tri.p1.y * w;
+
+    result->x = x >> 16;
+    result->y = y >> 16;
+}
+
+static void
+XYMapPoint (CompTriangle *from,
+	    CompTriangle *to,
+	    int		 fromX,
+	    int		 fromY,
+	    int		 *toX,
+	    int		 *toY)
+{
+    xPointFixed in, out;
+
+    in.x = IntToxFixed (fromX);
+    in.y = IntToxFixed (fromY);
+
+    MapPoint (from, to, &in, &out);
+
+    *toX = xFixedToInt (out.x + xFixed1 / 2);
+    *toY = xFixedToInt (out.y + xFixed1 / 2);
+}
+
+void
+CompositeXYParentToChild (WindowPtr pChild,
+			  int	   parentX,
+			  int	   parentY,
+			  int	   *childX,
+			  int	   *childY)
+{
+    CompWindowPtr cw = GetCompWindow (pChild);
+
+    if (cw && cw->pInputMesh)
+    {
+	CompTriangleMap *map = cw->pInputMesh->map;
+	int	        nMap = cw->pInputMesh->nMap;
+
+	while (nMap--)
+	{
+	    if (!map->parent.area)
+		continue;
+
+	    if (XYInTriangle (&map->parent.tri, parentX, parentY))
+	    {
+		XYMapPoint (&map->parent, &map->child,
+			    parentX, parentY,
+			    childX, childY);
+		return;
+	    }
+
+	    map++;
+	}
+    }
+
+    *childX = parentX;
+    *childY = parentY;
+}
+
+void
+CompositeXYChildToParent (WindowPtr pChild,
+			  int	   childX,
+			  int	   childY,
+			  int	   *parentX,
+			  int	   *parentY)
+{
+    CompWindowPtr cw = GetCompWindow (pChild);
+
+    if (cw && cw->pInputMesh)
+    {
+	CompTriangleMap *map = cw->pInputMesh->map;
+	int	        nMap = cw->pInputMesh->nMap;
+
+	while (nMap--)
+	{
+	    if (!map->child.area)
+		continue;
+
+	    if (XYInTriangle (&map->child.tri, childX, childY))
+	    {
+		XYMapPoint (&map->child, &map->parent,
+			    childX, childY,
+			    parentX, parentY);
+
+		return;
+	    }
+
+	    map++;
+	}
+    }
+
+    *parentX = childX;
+    *parentY = childY;
+}
+
+void
+CompositeXYScreenToWindowRootCoordinate (WindowPtr pWin,
+					 int	   x,
+					 int	   y,
+					 int	   *rootX,
+					 int	   *rootY)
+{
+    if (!pWin->parent)
+    {
+	*rootX = x;
+	*rootY = y;
+    }
+    else
+    {
+	CompositeXYScreenToWindowRootCoordinate (pWin->parent, x, y, &x, &y);
+	CompositeXYParentToChild (pWin, x, y, rootX, rootY);
+    }
+}
+
+void
+CompositeXYScreenFromWindowRootCoordinate (WindowPtr pWin,
+					   int	     x,
+					   int	     y,
+					   int	     *screenX,
+					   int	     *screenY)
+{
+    if (!pWin->parent)
+    {
+	*screenX = x;
+	*screenY = y;
+    }
+    else
+    {
+	CompositeXYChildToParent (pWin, x, y, &x, &y);
+	CompositeXYScreenFromWindowRootCoordinate (pWin->parent,
+						   x, y, screenX, screenY);
+    }
+}
+
+int
+CompositeSetTriangularCoordinateMesh (ClientPtr pClient,
+				      WindowPtr pWin,
+				      int	n,
+				      xTriangle *tri)
+{
+    CompSubwindowsPtr   csw = GetCompSubwindows (pWin->parent);
+    CompWindowPtr	cw = GetCompWindow (pWin);
+    CompClientWindowPtr	ccw;
+    WindowPtr		pSpriteWin;
+
+    /*
+     * sub-window must be Manual update
+     */
+    if (!csw || csw->update != CompositeRedirectManual)
+	return BadAccess;
+
+    /*
+     * must be Manual update client
+     */
+    for (ccw = csw->clients; ccw; ccw = ccw->next)
+	if (ccw->update == CompositeRedirectManual &&
+	    CLIENT_ID (ccw->id) != pClient->index)
+	    return BadAccess;
+
+    if (n)
+    {
+	CompTriangularMeshPtr mesh;
+	int		      i;
+
+	mesh = xalloc (sizeof (CompTriangularMeshRec) +
+		       sizeof (CompTriangleMap) * n / 2);
+	if (!mesh)
+	    return FALSE;
+
+	mesh->map  = (CompTriangleMap *) (mesh + 1);
+	mesh->nMap = n / 2;
+
+	for (i = 0; i < n; i += 2)
+	{
+	    mesh->map[i / 2].parent.tri  = tri[i];
+	    mesh->map[i / 2].parent.area =
+		TriangleArea (&tri[i].p1, &tri[i].p2, &tri[i].p3);
+
+	    mesh->map[i / 2].child.tri  = tri[i + 1];
+	    mesh->map[i / 2].child.area =
+		TriangleArea (&tri[i + 1].p1, &tri[i + 1].p2, &tri[i + 1].p3);
+	}
+
+	if (cw->pInputMesh)
+	    xfree (cw->pInputMesh);
+
+	cw->pInputMesh = mesh;
+    }
+    else
+    {
+	if (cw->pInputMesh)
+	{
+	    xfree (cw->pInputMesh);
+	    cw->pInputMesh = NULL;
+	}
+    }
+
+    pSpriteWin = GetSpriteWindow ();
+    while (pSpriteWin)
+    {
+	/*
+	 * Generate synthetic motion event if sprite window got an
+	 * ancestor that might be affected by the coordinate mapping
+	 * used for this window.
+	 */
+	if (pSpriteWin == pWin->parent)
+	{
+	    xEvent xE;
+	    int    x, y;
+
+	    GetSpritePosition (&x, &y);
+
+	    xE.u.keyButtonPointer.rootX = x;
+	    xE.u.keyButtonPointer.rootY = y;
+	    xE.u.keyButtonPointer.time = currentTime.milliseconds;
+	    xE.u.u.type = MotionNotify;
+
+	    (*inputInfo.pointer->public.processInputProc) (&xE,
+							   inputInfo.pointer,
+							   1);
+	    break;
+	}
+
+	pSpriteWin = pSpriteWin->parent;
+    }
+
+    return 0;
+}
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -122,6 +122,9 @@ int ProcInitialConnection();
 #ifdef LBX
 #include "lbxserve.h"
 #endif
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
 
 #define mskcnt ((MAXCLIENTS + 31) / 32)
 #define BITMASK(i) (1U << ((i) & 31))
@@ -1232,18 +1235,61 @@ ProcTranslateCoords(register ClientPtr client)
     }
     else
     {
-	INT16 x, y;
+	int x, y, rootX, rootY;
 	rep.sameScreen = xTrue;
 	rep.child = None;
 	/* computing absolute coordinates -- adjust to destination later */
 	x = pWin->drawable.x + stuff->srcX;
 	y = pWin->drawable.y + stuff->srcY;
+
+#ifdef COMPOSITE
+	/*
+	 * 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);
+#endif
+
+	/* adjust to destination coordinates */
+	rep.dstX = x - pDst->drawable.x;
+	rep.dstY = y - pDst->drawable.y;
+
+	rootX = x;
+	rootY = y;
+
 	pWin = pDst->firstChild;
 	while (pWin)
 	{
 #ifdef SHAPE
 	    BoxRec  box;
 #endif
+
+	x = rootX;
+	y = rootY;
+
+#ifdef COMPOSITE
+	    /*
+	     * Transform from parent to child.
+	     */
+	    if (pWin->mapped)
+	    {
+		if (pWin->parent)
+		{
+		    x = rootX - pWin->parent->drawable.x;
+		    y = rootY - pWin->parent->drawable.y;
+		}
+
+		CompositeXYParentToChild (pWin, x, y, &x, &y);
+
+		if (pWin->parent)
+		{
+		    x += pWin->parent->drawable.x;
+		    y += pWin->parent->drawable.y;
+		}
+	    }
+#endif
+
 	    if ((pWin->mapped) &&
 		(x >= pWin->drawable.x - wBorderWidth (pWin)) &&
 		(x < pWin->drawable.x + (int)pWin->drawable.width +
@@ -1268,15 +1314,14 @@ ProcTranslateCoords(register ClientPtr client)
 #endif
 		)
             {
+		rootX = x;
+		rootY = y;
 		rep.child = pWin->drawable.id;
 		pWin = (WindowPtr) NULL;
 	    }
 	    else
 		pWin = pWin->nextSib;
 	}
-	/* adjust to destination coordinates */
-	rep.dstX = x - pDst->drawable.x;
-	rep.dstY = y - pDst->drawable.y;
     }
     WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
     return(client->noClientException);
--- a/dix/events.c
+++ b/dix/events.c
@@ -131,6 +131,9 @@ of the copyright holder.
 #include "panoramiX.h"
 #include "panoramiXsrv.h"
 #endif
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
 #include "globals.h"
 
 #ifdef XKB
@@ -2002,15 +2005,41 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
 }
 
 static WindowPtr 
-XYToWindow(int x, int y)
+XYToWindow(int rootX, int rootY)
 {
     register WindowPtr  pWin;
     BoxRec		box;
+    int			x, y;
 
     spriteTraceGood = 1;	/* root window still there */
     pWin = ROOT->firstChild;
     while (pWin)
     {
+	x = rootX;
+	y = rootY;
+
+#ifdef COMPOSITE
+	/*
+	 * Transform from parent to child.
+	 */
+	if (pWin->mapped)
+	{
+	    if (pWin->parent)
+	    {
+		x = rootX - pWin->parent->drawable.x;
+		y = rootY - pWin->parent->drawable.y;
+	    }
+
+	    CompositeXYParentToChild (pWin, x, y, &x, &y);
+
+	    if (pWin->parent)
+	    {
+		x += pWin->parent->drawable.x;
+		y += pWin->parent->drawable.y;
+	    }
+	}
+#endif
+
 	if ((pWin->mapped) &&
 	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
 	    (x < pWin->drawable.x + (int)pWin->drawable.width +
@@ -2041,6 +2070,8 @@ XYToWindow(int x, int y)
 		Must_have_memory = FALSE; /* XXX */
 	    }
 	    spriteTrace[spriteTraceGood++] = pWin;
+	    rootX = x;
+	    rootY = y;
 	    pWin = pWin->firstChild;
 	}
 	else
@@ -4043,6 +4074,7 @@ ProcQueryPointer(ClientPtr client)
     WindowPtr pWin, t;
     REQUEST(xResourceReq);
     DeviceIntPtr mouse = inputInfo.pointer;
+    int rootX, rootY;
 
     REQUEST_SIZE_MATCH(xResourceReq);
     pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess);
@@ -4055,14 +4087,27 @@ ProcQueryPointer(ClientPtr client)
     rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
     rep.length = 0;
     rep.root = (ROOT)->drawable.id;
-    rep.rootX = sprite.hot.x;
-    rep.rootY = sprite.hot.y;
     rep.child = None;
+
+#ifdef COMPOSITE
+    /*
+     * Return coordinates in windows root coordinate space.
+     */
+    CompositeXYScreenToWindowRootCoordinate (pWin,
+					     sprite.hot.x, sprite.hot.y,
+					     &rootX, &rootY);
+    rep.rootX = rootX;
+    rep.rootY = rootY;
+#else
+    rep.rootX = rootX = sprite.hot.x;
+    rep.rootY = rootY = sprite.hot.y;
+#endif
+
     if (sprite.hot.pScreen == pWin->drawable.pScreen)
     {
 	rep.sameScreen = xTrue;
-	rep.winX = sprite.hot.x - pWin->drawable.x;
-	rep.winY = sprite.hot.y - pWin->drawable.y;
+	rep.winX = rootX - pWin->drawable.x;
+	rep.winY = rootY - pWin->drawable.y;
 	for (t = sprite.win; t; t = t->parent)
 	    if (t->parent == pWin)
 	    {
@@ -4618,11 +4663,67 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
     xEvent    eventTo, *eventFrom;
     int       i;
 
+#ifdef COMPOSITE
+    xEvent    stackCopy;
+    xEvent    *compEventCopy = &stackCopy;
+#endif
+
 #ifdef XKB
     if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
 	return;
 #endif
 
+#ifdef COMPOSITE
+    if (count > 1)
+    {
+	Must_have_memory = TRUE; /* XXX */
+	compEventCopy = xalloc (count * sizeof (xEvent));
+	Must_have_memory = FALSE; /* XXX */
+    }
+
+    memcpy (compEventCopy, events, count * sizeof (xEvent));
+    events = compEventCopy;
+
+    for (i = 0; i < count; i++)
+    {
+	WindowPtr pWin;
+	int	  x, y, dx, dy;
+
+	switch (events[i].u.u.type) {
+	case MotionNotify:
+	case ButtonPress:
+	case ButtonRelease:
+	case KeyPress:
+	case KeyRelease:
+	case EnterNotify:
+	case LeaveNotify:
+	    pWin = LookupIDByType (events[i].u.keyButtonPointer.event,
+				   RT_WINDOW);
+	    if (pWin)
+	    {
+		x = events[i].u.keyButtonPointer.rootX;
+		y = events[i].u.keyButtonPointer.rootY;
+
+		/*
+		 * rootX and rootY are in screen coordinate space.
+		 * Transform to windows root coordinate space before writing
+		 * events to client.
+		 */
+		CompositeXYScreenToWindowRootCoordinate (pWin, x, y, &x, &y);
+
+		dx = x - events[i].u.keyButtonPointer.rootX;
+		dy = y - events[i].u.keyButtonPointer.rootY;
+
+		events[i].u.keyButtonPointer.rootX  += dx;
+		events[i].u.keyButtonPointer.rootY  += dy;
+		events[i].u.keyButtonPointer.eventX += dx;
+		events[i].u.keyButtonPointer.eventY += dy;
+	    }
+	    break;
+	}
+    }
+#endif
+
 #ifdef PANORAMIX
     if(!noPanoramiXExtension && 
        (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) 
@@ -4681,4 +4782,10 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
     {
 	(void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
     }
+
+#ifdef COMPOSITE
+    if (compEventCopy != &stackCopy)
+	xfree (compEventCopy);
+#endif
+
 }


_______________________________________________
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic