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

List:       freedesktop-xorg
Subject:    gsoc and input redirection/transformation
From:       Joel Bosveld <joel.bosveld () gmail ! com>
Date:       2009-03-28 14:27:57
Message-ID: 6e4dc1c0903280727i3e0544c9l1b993b0a64eac284 () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Hi,

I was considering submitting a proposal for Google Summer of Code, to get
input redirection in a state where it is able to be merged. It was suggested
on irc to bring this to the list, so here it is.  I was wondering if such a
project would be feasible, or suitable, for gsoc.

Looking over the previous posts on ML relating to IR, there is still a bit
of work to get correct behaviour with some (a lot of?) applications - this
has also been confirmed by my tests (with my not-published simple compiz
test plugin).  I'm not sure whether these problems are fixable in X, or
whether it would require patches to applications to remove assumptions that
break down with IR. I would guess the later, based on this:
http://lists.freedesktop.org/pipermail/xorg/2008-February/032747.html

Another feature that could be implemented is actual redirection, rather than
just transformation:
http://lists.freedesktop.org/archives/compiz/2007-June/002314.html

Also, making sure everything works with MPX, XI2 - I did try this last year
some time, and it worked as well as the single pointer case. There is a
small part of the patch that still needs to be 'ported' to work master,
relating to sending motionNotify events when input mesh changes (which I
have just commented out for now)

Posts on ML indicate that there may be some work needed for transformations
of non top-level windows, and also some work with pointer grabs. Any thing
else that might need work?

I have attached patches that should apply to current (as of a few days, at
least) master. They are based on David Reveman's latest patches (that I
could find), with some modifications by SmSpillaz and myself.

So, would such a task be suitable for gsoc?

Joel.

[Attachment #5 (text/html)]

Hi,<br><br>I was considering submitting a proposal for Google Summer of Code, to get \
input redirection in a state where it is able to be merged. It was suggested on irc \
to bring this to the list, so here it is.  I was wondering if such a project would be \
feasible, or suitable, for gsoc.<br> <br>Looking over the previous posts on ML \
relating to IR, there is still a bit of work to get correct behaviour with some (a \
lot of?) applications - this has also been confirmed by my tests (with my \
not-published simple compiz test plugin).  I&#39;m not sure whether these problems \
are fixable in X, or whether it would require patches to applications to remove \
assumptions that break down with IR. I would guess the later, based on this: <a \
href="http://lists.freedesktop.org/pipermail/xorg/2008-February/032747.html">http://lists.freedesktop.org/pipermail/xorg/2008-February/032747.html</a><br>
 <br>Another feature that could be implemented is actual redirection, rather than \
just transformation: <a \
href="http://lists.freedesktop.org/archives/compiz/2007-June/002314.html">http://lists.freedesktop.org/archives/compiz/2007-June/002314.html</a><br>
 <br>Also, making sure everything works with MPX, XI2 - I did try this last year some \
time, and it worked as well as the single pointer case. There is a small part of the \
patch that still needs to be &#39;ported&#39; to work master, relating to sending \
motionNotify events when input mesh changes (which I have just commented out for \
now)<br> <br>Posts on ML indicate that there may be some work needed for \
transformations of non top-level windows, and also some work with pointer grabs. Any \
thing else that might need work?<br><br>I have attached patches that should apply to \
current (as of a few days, at least) master. They are based on David Reveman&#39;s \
latest patches (that I could find), with some modifications by SmSpillaz and \
myself.<br> <br>So, would such a task be suitable for gsoc?<br><br>Joel.<br>

--000e0cd25530e0d88e04662ea74b--


["compositeproto.diff" (application/octet-stream)]

diff --git a/composite.h b/composite.h
index 30b190f..eb1efba 100644
--- a/composite.h
+++ b/composite.h
@@ -63,8 +63,9 @@
 #define X_CompositeNameWindowPixmap		6
 #define X_CompositeGetOverlayWindow             7
 #define X_CompositeReleaseOverlayWindow         8
+#define X_CompositeSetTriangularCoordinateMesh	9
 
-#define CompositeNumberRequests	    (X_CompositeReleaseOverlayWindow + 1)
+#define CompositeNumberRequests	    (X_CompositeSetTriangularCoordinateMesh + 1)
 
 #define CompositeNumberEvents			0
 
diff --git a/compositeproto.h b/compositeproto.h
index 2e392e2..9180cf7 100644
--- a/compositeproto.h
+++ b/compositeproto.h
@@ -186,6 +186,15 @@ typedef struct {
 
 #define sz_xCompositeReleaseOverlayWindowReq sizeof(xCompositeReleaseOverlayWindowReq)
 
+typedef struct {
+    CARD8   reqType;
+    CARD8   compositeReqType;
+    CARD16  length;
+    Window  window B32;
+} xCompositeSetTriangularCoordinateMeshReq;
+
+#define sz_xCompositeSetTriangularCoordinateMeshReq sizeof(xCompositeSetTriangularCoordinateMeshReq)
+
 #undef Window
 #undef Region
 #undef Pixmap
diff --git a/configure.ac b/configure.ac
index 3a5fc5e..85acb1d 100644
--- 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.4], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
+AC_INIT([CompositeProto], [0.5], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 

["libXcomposite.diff" (application/octet-stream)]

diff --git a/configure.ac b/configure.ac
index d5c0791..5374460 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,7 +32,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.4.0, \
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], libXcomposite) \
+AC_INIT(libXcomposite, 0.5.0, \
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], libXcomposite)  \
AM_INIT_AUTOMAKE([dist-bzip2])  AM_MAINTAINER_MODE
 
@@ -61,7 +61,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)  \
XCOMPOSITE_CFLAGS="$CWARNFLAGS $XCOMPOSITE_CFLAGS"  AC_SUBST(XCOMPOSITE_CFLAGS)
 AC_SUBST(XCOMPOSITE_LIBS)
diff --git a/include/X11/extensions/Xcomposite.h \
b/include/X11/extensions/Xcomposite.h index b97e390..a6a70c5 100644
--- a/include/X11/extensions/Xcomposite.h
+++ b/include/X11/extensions/Xcomposite.h
@@ -45,6 +45,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_ */
diff --git a/src/Xcomposite.c b/src/Xcomposite.c
index b5637b0..ff2d741 100644
--- a/src/Xcomposite.c
+++ b/src/Xcomposite.c
@@ -393,3 +393,42 @@ 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 ();
+}
+
diff --git a/src/xcompositeint.h b/src/xcompositeint.h
index 7f0f868..3f5745e 100644
--- a/src/xcompositeint.h
+++ b/src/xcompositeint.h
@@ -49,6 +49,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>
 
@@ -81,4 +82,17 @@ 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_ */


["xserver.diff" (application/octet-stream)]

diff --git a/composite/compalloc.c b/composite/compalloc.c
index 1bac9a4..c0c11b9 100644
--- a/composite/compalloc.c
+++ b/composite/compalloc.c
@@ -142,6 +142,7 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
 	cw->oldy = COMP_ORIGIN_INVALID;
 	cw->damageRegistered = FALSE;
 	cw->damaged = FALSE;
+	cw->pInputMesh = NULL;
 	dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
     }
     ccw->next = cw->clients;
diff --git a/composite/compext.c b/composite/compext.c
index 4fff20e..0345878 100644
--- a/composite/compext.c
+++ b/composite/compext.c
@@ -382,6 +382,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;
+}
+
 static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     ProcCompositeQueryVersion,
     ProcCompositeRedirectWindow,
@@ -392,6 +431,7 @@ static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     ProcCompositeNameWindowPixmap,
     ProcCompositeGetOverlayWindow,
     ProcCompositeReleaseOverlayWindow,
+    ProcCompositeSetTriangularCoordinateMesh
 };
 
 static int
@@ -516,6 +556,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);
+}
+
 static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     SProcCompositeQueryVersion,
     SProcCompositeRedirectWindow,
@@ -526,6 +579,7 @@ static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     SProcCompositeNameWindowPixmap,
     SProcCompositeGetOverlayWindow,
     SProcCompositeReleaseOverlayWindow,
+    SProcCompositeSetTriangularCoordinateMesh
 };
 
 static int
diff --git a/composite/compint.h b/composite/compint.h
index 1c19ccd..6ff4c9c 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -84,6 +84,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 */
@@ -95,6 +110,7 @@ typedef struct _CompWindow {
     int			    oldy;
     PixmapPtr		    pOldPixmap;
     int			    borderClipX, borderClipY;
+    CompTriangularMeshPtr   pInputMesh;
 } CompWindowRec, *CompWindowPtr;
 
 #define COMP_ORIGIN_INVALID	    0x80000000
@@ -319,4 +335,39 @@ CompositeRealChildHead (WindowPtr pWin);
 int
 DeleteWindowNoInputDevices(pointer value, XID wid);
 
+Bool
+CompositeXYParentToChild (WindowPtr pChild,
+			  int	   parentX,
+			  int	   parentY,
+			  int	   *childX,
+			  int	   *childY);
+
+Bool
+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 577fa73..318a38a 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -821,3 +821,344 @@ 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);
+}
+
+Bool
+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);
+		/* XXX fix the problem where the mesh could only end up in
+		 * the top left corner
+		 */
+		*childX += pChild->drawable.x;
+		*childY += pChild->drawable.y;
+		/* There is a mesh and the point was redirected,
+		 * handle as normal
+		 */
+		return TRUE;
+	    }
+
+	    map++;
+	}
+    }
+    *childX = parentX;
+    *childY = parentY;
+
+    /* There is a mesh, but nothing was redirected,
+     * don't process the event on the non-redirected
+     * window
+     */
+    if (cw && cw->pInputMesh)
+	return FALSE;
+
+    /* There is no mesh, handle events like normal */
+    if (!cw || !cw->pInputMesh)
+	return TRUE;
+}
+
+Bool
+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);
+
+		/* There is a mesh and the point was redirected,
+		 * handle as normal
+		 */
+		return TRUE;
+	    }
+
+	    map++;
+	}
+    }
+
+    *parentX = childX;
+    *parentY = childY;
+
+    /* There is a mesh, but nothing was redirected,
+     * don't process the event on the non-redirected
+     * window
+     */
+    if (cw && cw->pInputMesh)
+	return FALSE;
+
+    /* There is no mesh, handle events like normal */
+    if (!cw || !cw->pInputMesh)
+	return TRUE;
+}
+
+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 BadAlloc;
+
+	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;
+	}
+    }
+
+    /* Generate motionNotify event when mesh changes */
+    /*pSpriteWin = GetSpriteWindow (inputInfo.devices);
+    while (pSpriteWin)
+    {
+	if (pSpriteWin == pWin->parent)
+	{
+	    xEvent xE;
+	    int    x, y;
+
+	    GetSpritePosition (inputInfo.devices, &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;
+}
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 0ed95df..7360fa7 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -142,6 +142,10 @@ typedef const char *string;
 #include "Xserver-dtrace.h"
 #endif
 
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
+
 #define mskcnt ((MAXCLIENTS + 31) / 32)
 #define BITMASK(i) (1U << ((i) & 31))
 #define MASKIDX(i) ((i) >> 5)
@@ -1019,16 +1023,59 @@ ProcTranslateCoords(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)
 	{
 	    BoxRec  box;
+
+	    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 +
@@ -1051,15 +1098,14 @@ ProcTranslateCoords(ClientPtr client)
 				    y - pWin->drawable.y, &box))
 		)
             {
+		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);
diff --git a/dix/events.c b/dix/events.c
index e73044e..45f6290 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -131,6 +131,7 @@ of the copyright holder.
 #include "panoramiX.h"
 #include "panoramiXsrv.h"
 #endif
+#include "compint.h"
 #include "globals.h"
 
 #include <X11/extensions/XKBproto.h>
@@ -1874,6 +1875,7 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
     }
 }
 
+
 /**
  * Deliver events to a window. At this point, we do not yet know if the event
  * actually needs to be delivered. May activate a grab if the event is a
@@ -2458,18 +2460,46 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
  * @returns the window at the given coordinates.
  */
 static WindowPtr
-XYToWindow(DeviceIntPtr pDev, int x, int y)
+XYToWindow(DeviceIntPtr pDev, int rootX, int rootY)
 {
     WindowPtr  pWin;
     BoxRec		box;
+    int			x, y;
     SpritePtr pSprite;
+    Bool      handle = TRUE;
 
     pSprite = pDev->spriteInfo->sprite;
     pSprite->spriteTraceGood = 1;	/* root window still there */
     pWin = RootWindow(pDev)->firstChild;
     while (pWin)
     {
-	if ((pWin->mapped) &&
+	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;
+	    }
+
+	    handle = CompositeXYParentToChild (pWin, x, y, &x, &y);
+
+	    if (pWin->parent)
+	    {
+		x += pWin->parent->drawable.x;
+		y += pWin->parent->drawable.y;
+	    }
+	}
+#endif
+
+
+	if ((pWin->mapped) && (handle) &&
 	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
 	    (x < pWin->drawable.x + (int)pWin->drawable.width +
 	     wBorderWidth(pWin)) &&
@@ -2502,6 +2532,8 @@ XYToWindow(DeviceIntPtr pDev, int x, int y)
 		                    pSprite->spriteTraceSize*sizeof(WindowPtr));
 	    }
 	    pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
+	    rootX = x;
+	    rootY = y;
 	    pWin = pWin->firstChild;
 	}
 	else
@@ -4629,6 +4661,7 @@ ProcQueryPointer(ClientPtr client)
     DeviceIntPtr keyboard;
     SpritePtr pSprite;
     int rc;
+    int rootX, rootY;
     REQUEST(xResourceReq);
     REQUEST_SIZE_MATCH(xResourceReq);
 
@@ -4651,14 +4684,27 @@ ProcQueryPointer(ClientPtr client)
     rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
     rep.length = 0;
     rep.root = (RootWindow(mouse))->drawable.id;
+    rep.child = None;
+
+#ifdef COMPOSITE
+    /*
+     * Return coordinates in windows root coordinate space.
+     */
+    CompositeXYScreenToWindowRootCoordinate (pWin,
+					     pSprite->hot.x, pSprite->hot.y,
+					     &rootX, &rootY);
     rep.rootX = pSprite->hot.x;
     rep.rootY = pSprite->hot.y;
-    rep.child = None;
+#else
+    rep.rootX = rootX = pSprite->hot.x;
+    rep.rootY = rootY = pSprite->hot.y;
+#endif
+
     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
 	rep.sameScreen = xTrue;
-	rep.winX = pSprite->hot.x - pWin->drawable.x;
-	rep.winY = pSprite->hot.y - pWin->drawable.y;
+	rep.winX = rootX - pWin->drawable.x;
+	rep.winY = rootY - pWin->drawable.y;
 	for (t = pSprite->win; t; t = t->parent)
 	    if (t->parent == pWin)
 	    {
@@ -5327,9 +5373,95 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
     int       i,
               eventlength = sizeof(xEvent);
 
+#ifdef COMPOSITE
+    xEvent    stackCopy;
+    xEvent    *compEventCopy = &stackCopy;
+#endif
+
     if (!XkbFilterEvents(pClient, count, events))
 	return;
 
+#ifdef COMPOSITE
+Bool Must_have_memory;
+    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++)
+    {
+	deviceKeyButtonPointer *deviceEvent;
+	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;
+	default:
+	    if (events[i].u.u.type == DeviceMotionNotify  ||
+		events[i].u.u.type == DeviceButtonPress	  ||
+		events[i].u.u.type == DeviceButtonRelease ||
+		events[i].u.u.type == DeviceKeyPress	  ||
+		events[i].u.u.type == DeviceKeyRelease)
+	    {
+		deviceEvent = (deviceKeyButtonPointer *) &events[i];
+
+		pWin = LookupIDByType (deviceEvent->event, RT_WINDOW);
+		if (pWin)
+		{
+		    x = deviceEvent->root_x;
+		    y = deviceEvent->root_y;
+
+		    CompositeXYScreenToWindowRootCoordinate (pWin, x, y,
+							     &x, &y);
+
+		    dx = x - deviceEvent->root_x;
+		    dy = y - deviceEvent->root_y;
+
+		    //deviceEvent->root_x  += dx;
+		    //deviceEvent->root_y  += dy;
+		    deviceEvent->event_x += dx;
+		    deviceEvent->event_y += dy;
+		}
+	    }
+	    break;
+	}
+    }
+#endif
+
 #ifdef PANORAMIX
     if(!noPanoramiXExtension &&
        (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
@@ -5429,6 +5561,12 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
          * matter. And we're all set. Woohoo. */
 	WriteToClient(pClient, count * eventlength, (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