input transformations

Deron Johnson Deron.Johnson at Sun.COM
Mon Feb 5 11:11:15 PST 2007


It's hard for me to evaluate this without some higher level context.
What sort of window transformations are you aiming to support
3D perspective affine transformations? What sort of 3D objects will the
windows be mapped onto? There are a variety of possibilities:
a quad of infinite thinness, a flat slab (rectangular parallelipiped) or
any arbitrarily shaped 3D object. And, do you want to permit interaction
with transformed windows or use transformation only for transitional 
effects?
If you want the former you will need to perform mouse-over picking with
input pointer events. If you merely want the latter then it simplifies the
problem considerably. If you can give me a brief summary of what
effects you are trying to achieve I can be in a better position to
help evaluate this proposal. Thanks.


David Reveman wrote:

>I spent some time this week trying to add support for input
>transformations to the server. I tried a few different approaches. The
>patches I've attached are what's currently working best for me.
>
>In this approach I allow every window to have it's own root window
>coordinate space. A window's root window coordinate space is affected by
>all it's ancestors. Composite clients can set a triangular mesh that
>maps root window coordinates from a composite window to one of its
>redirected child-windows. Event coordinates are generated in the event
>windows root coordinate space.
>
>Simple cases where the same root coordinate space is used for all
>windows, like when zooming or rotating the desktop works just fine. More
>complex cases where each redirected window has a different root
>coordinate space like the scale plugin in compiz, which transforms and
>tiles all windows so that they don't overlap, also work surprisingly
>well but there are some obvious issues. Most of them seem to be things
>that need to be fixed on the client side, though. E.g. there's no way to
>know which coordinate space to use for override-redirect windows like
>tool-tips and menus. The compositing manager can make a decent guess
>from the window location but without any hint telling the compositing
>manager which top-level window it's related to, it's hard.
>
>Anyhow, I'm not sure my current approach is the best way to allow
>interaction with transformed windows but it seems to work pretty well
>with what we want to do in compiz. I have a local branch of compiz with
>some input transformation hacks, I'll clean it up and push it out in the
>next couple of days.
>
>It seems to me like we need to experiment a bit before we can decide
>what's the best solution. My current patches are at least something to
>start with and I look forward to discussing it more next week at
>xdevconf.
>
>- David
>  
>
>------------------------------------------------------------------------
>
>--- a/composite.h
>+++ b/composite.h
>@@ -63,8 +63,9 @@
> #define X_CompositeNameWindowPixmap		6
> #define X_CompositeGetOverlayWindow             7
> #define X_CompositeReleaseOverlayWindow         8
>-#define X_CompositeRedirectCoordinate		9
>-#define X_CompositeTransformCoordinate		10
>+#define X_CompositeSetTriangularCoordinateMesh	9
>+#define X_CompositeRedirectCoordinate		10
>+#define X_CompositeTransformCoordinate		11
> 
> #define CompositeNumberRequests	    (X_CompositeTransformCoordinate + 1)
> 
>--- a/compositeproto.h
>+++ b/compositeproto.h
>@@ -192,6 +192,15 @@ typedef struct {
>     CARD8   compositeReqType;
>     CARD16  length;
>     Window  window B32;
>+} xCompositeSetTriangularCoordinateMeshReq;
>+
>+#define sz_xCompositeSetTriangularCoordinateMeshReq	8
>+
>+typedef struct {
>+    CARD8   reqType;
>+    CARD8   compositeReqType;
>+    CARD16  length;
>+    Window  window B32;
>     BOOL    redirect;
>     BYTE    unused1;
>     CARD16  unused2 B16;
>--- a/configure.ac
>+++ b/configure.ac
>@@ -24,7 +24,7 @@ dnl
> dnl Process this file with autoconf to create configure.
> 
> AC_PREREQ([2.57])
>-AC_INIT([CompositeProto], [0.3], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
>+AC_INIT([CompositeProto], [0.4], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
> AM_INIT_AUTOMAKE([foreign dist-bzip2])
> AM_MAINTAINER_MODE
> 
>  
>
>------------------------------------------------------------------------
>
>--- a/configure.ac
>+++ b/configure.ac
>@@ -34,7 +34,7 @@ dnl protocol, so Xcomposite version l.n.m corresponds to protocol version l.n
> dnl that 'revision' number appears in Xcomposite.h and has to be manually
> dnl synchronized.
> dnl
>-AC_INIT(libXcomposite, 0.3.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], libXcomposite)
>+AC_INIT(libXcomposite, 0.4.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], libXcomposite)
> AM_INIT_AUTOMAKE([dist-bzip2])
> AM_MAINTAINER_MODE
> 
>@@ -52,7 +52,7 @@ if test "$VERSION" = "" ; then
> fi
> COMPOSITEEXT_VERSION=[`echo $VERSION | sed 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/'`]
> AC_SUBST(COMPOSITEEXT_VERSION)
>-PKG_CHECK_MODULES(XCOMPOSITE, [compositeproto >= $COMPOSITEEXT_VERSION] x11 xfixes xext fixesproto)
>+PKG_CHECK_MODULES(XCOMPOSITE, [compositeproto >= $COMPOSITEEXT_VERSION] x11 xfixes xext fixesproto xrender renderproto)
> AC_SUBST(XCOMPOSITE_CFLAGS)
> AC_SUBST(XCOMPOSITE_LIBS)
> 
>--- a/include/X11/extensions/Xcomposite.h
>+++ b/include/X11/extensions/Xcomposite.h
>@@ -47,6 +47,7 @@
> 
> #include <X11/extensions/composite.h>
> #include <X11/extensions/Xfixes.h>
>+#include <X11/extensions/Xrender.h>
> #include <X11/Xfuncproto.h>
> 
> /*
>@@ -92,6 +93,12 @@ XCompositeGetOverlayWindow (Display *dpy, Window window);
> void
> XCompositeReleaseOverlayWindow (Display *dpy, Window window);
> 
>+void
>+XCompositeSetTriangularCoordinateMesh (Display		  *dpy,
>+				       Window		  window,
>+				       _Xconst XTriangle *triangle,
>+				       int		  nTriangle);
>+
> _XFUNCPROTOEND
> 
> #endif /* _XCOMPOSITE_H_ */
>--- a/src/Xcomposite.c
>+++ b/src/Xcomposite.c
>@@ -391,3 +391,40 @@ XCompositeReleaseOverlayWindow (Display *dpy, Window window)
>     UnlockDisplay (dpy);
>     SyncHandle ();
> }
>+
>+void
>+XCompositeSetTriangularCoordinateMesh (Display		  *dpy,
>+				       Window		  window,
>+				       _Xconst XTriangle *triangle,
>+				       int		  nTriangle)
>+{
>+    XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy);
>+    xCompositeSetTriangularCoordinateMeshReq *req;
>+    int					     n;
>+    long				     len;
>+
>+    XCompositeSimpleCheckExtension (dpy, info);
>+    LockDisplay (dpy);
>+    while (nTriangle)
>+    {
>+	GetReq (CompositeSetTriangularCoordinateMesh, req);
>+	req->reqType = info->codes->major_opcode;
>+	req->compositeReqType = X_CompositeSetTriangularCoordinateMesh;
>+	req->window = window;
>+	n = nTriangle;
>+	len = ((long) n) * (SIZEOF (xTriangle) >> 2);
>+	if (!dpy->bigreq_size && len > (dpy->max_request_size - req->length))
>+	{
>+	    n = (dpy->max_request_size - req->length) /
>+		(SIZEOF (xTriangle) >> 2);
>+	    len = ((long) n) * (SIZEOF (xTriangle) >> 2);
>+	}
>+	SetReqLen (req, len, len);
>+	len <<= 2;
>+	DataInt32 (dpy, (int *) triangle, len);
>+	nTriangle -= n;
>+	triangle  += n;
>+    }
>+    UnlockDisplay (dpy);
>+    SyncHandle ();
>+}
>--- a/src/xcompositeint.h
>+++ b/src/xcompositeint.h
>@@ -51,6 +51,7 @@
> #include <X11/Xlib.h>
> #include <X11/Xlibint.h>
> #include <X11/Xutil.h>
>+#include <X11/extensions/renderproto.h>
> #include <X11/extensions/compositeproto.h>
> #include <X11/extensions/Xcomposite.h>
> 
>@@ -83,4 +84,16 @@ XCompositeFindDisplay (Display *dpy);
> #define XCompositeSimpleCheckExtension(dpy,i) \
>   if (!XCompositeHasExtension(i)) { return; }
> 
>+/*
>+ * Xlib uses long for 32-bit values.  Xcomposite uses int.  This
>+ * matters on alpha.  Note that this macro assumes that int is 32 bits
>+ * except on WORD64 machines where it is 64 bits.
>+ */
>+
>+#ifdef WORD64
>+#define DataInt32(dpy,d,len)	Data32(dpy,(long *) (d),len)
>+#else
>+#define DataInt32(dpy,d,len)	Data(dpy,(char *) (d),len)
>+#endif
>+
> #endif /* _XCOMPOSITEINT_H_ */
>  
>
>------------------------------------------------------------------------
>
>--- 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,49 @@ ProcCompositeReleaseOverlayWindow (ClientPtr client)
>     return client->noClientException;
> }
> 
>+static int
>+ProcCompositeSetTriangularCoordinateMesh (ClientPtr client)
>+{
>+    CompWindowPtr cw;
>+    WindowPtr	  pWin;
>+    int		  n;
>+
>+    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 % (sizeof (xTriangle) * 2))
>+	return BadLength;
>+
>+    n /= sizeof (xTriangle);
>+    if (n)
>+    {
>+	int status;
>+
>+	status = CompositeSetTriangularCoordinateMesh (client, pWin, n,
>+						       (xTriangle *) &stuff[1]);
>+	if (status)
>+	    return status;
>+    }
>+
>+    return client->noClientException;
>+}
>+
> int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
>     ProcCompositeQueryVersion,
>     ProcCompositeRedirectWindow,
>@@ -522,6 +565,7 @@ int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
>     ProcCompositeNameWindowPixmap,
>     ProcCompositeGetOverlayWindow,
>     ProcCompositeReleaseOverlayWindow,
>+    ProcCompositeSetTriangularCoordinateMesh
> };
> 
> static int
>@@ -646,6 +690,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 +713,7 @@ int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
>     SProcCompositeNameWindowPixmap,
>     SProcCompositeGetOverlayWindow,
>     SProcCompositeReleaseOverlayWindow,
>+    SProcCompositeSetTriangularCoordinateMesh
> };
> 
> static int
>diff --git a/composite/compint.h b/composite/compint.h
>index 9395512..988a23b 100644
>--- 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_ */
>diff --git a/composite/compwindow.c b/composite/compwindow.c
>index 87055b7..13d7420 100644
>--- a/composite/compwindow.c
>+++ b/composite/compwindow.c
>@@ -812,3 +812,283 @@ 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 (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 (XYInTriangle (&map->parent.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;
>+
>+    /*
>+     * 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;
>+	}
>+    }
>+
>+    /* XXX: we need to generate synthetic motion events here if this is the
>+       sprite window or one of its ancestors. */
>+
>+    return 0;
>+}
>--- a/configure.ac
>+++ b/configure.ac
>@@ -528,7 +528,7 @@ fi
> AM_CONDITIONAL(COMPOSITE, [test "x$COMPOSITE" = xyes])
> if test "x$COMPOSITE" = xyes; then
> 	AC_DEFINE(COMPOSITE, 1, [Support Composite Extension])
>-	REQUIRED_MODULES="$REQUIRED_MODULES [compositeproto >= 0.3]"
>+	REQUIRED_MODULES="$REQUIRED_MODULES [compositeproto >= 0.4]"
> 	COMPOSITE_LIB='$(top_builddir)/composite/libcomposite.la'
> 	COMPOSITE_INC='-I$(top_srcdir)/composite'
> fi
>--- 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,51 @@ 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.
>+	 *
>+	 * XXX: I'm not sure that input transformations should affect
>+	 * TranslateCoords request.
>+	 */
>+	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
>+
>+#ifdef COMPOSITE
>+	    /*
>+	     * Transform from parents root coordinate space to childs
>+	     * root coordinate space.
>+	     */
>+	    if (pWin->mapped)
>+		CompositeXYParentToChild (pWin, rootX, rootY, &x, &y);
>+#else
>+	    x = rootX;
>+	    y = rootY;
>+#endif
>+
> 	    if ((pWin->mapped) &&
> 		(x >= pWin->drawable.x - wBorderWidth (pWin)) &&
> 		(x < pWin->drawable.x + (int)pWin->drawable.width +
>@@ -1268,15 +1304,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
>@@ -1993,15 +1996,29 @@ 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)
>     {
>+
>+#ifdef COMPOSITE
>+	/*
>+	 * Transform from parents root coordinate space to childs
>+	 * root coordinate space.
>+	 */
>+	if (pWin->mapped)
>+	    CompositeXYParentToChild (pWin, rootX, rootY, &x, &y);
>+#else
>+	x = rootX;
>+	y = rootY;
>+#endif
>+
> 	if ((pWin->mapped) &&
> 	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
> 	    (x < pWin->drawable.x + (int)pWin->drawable.width +
>@@ -2032,6 +2049,8 @@ XYToWindow(int x, int y)
> 		Must_have_memory = FALSE; /* XXX */
> 	    }
> 	    spriteTrace[spriteTraceGood++] = pWin;
>+	    rootX = x;
>+	    rootY = y;
> 	    pWin = pWin->firstChild;
> 	}
> 	else
>@@ -4028,6 +4047,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);
>@@ -4040,14 +4060,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)
> 	    {
>@@ -4603,11 +4636,59 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
>     xEvent    eventTo, *eventFrom;
>     int       i;
> 
>+#ifdef COMPOSITE
>+    xEvent copy[count];
>+#endif
>+
> #ifdef XKB
>     if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
> 	return;
> #endif
> 
>+#ifdef COMPOSITE
>+    memcpy (copy, events, count * sizeof (xEvent));
>+    events = copy;
>+
>+    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)) 
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>xorg mailing list
>xorg at lists.freedesktop.org
>http://lists.freedesktop.org/mailman/listinfo/xorg
>  
>




More information about the xorg mailing list