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