Input shaping

Soeren Sandmann sandmann at redhat.com
Thu Mar 24 12:05:46 PST 2005


In this thread:

      http://lists.freedesktop.org/pipermail/xorg/2005-January/005962.html

Keith describes and extension to the Shape extension allowing windows
to have an "input shape" in addition to the exisiting clip and
bounding shapes.

The patch attached to that message was committed to Keith's xserver 
tree, but not
to the xorg tree. At

   http://www.daimi.au.dk/~sandmann/input-shape.patch

there is a port of his patch to the xorg tree. The patch is also 
attached to this message.

If this is considered a good idea, I will update the protocol and 
library documentation
for the shape protocol.


I originally posted about this to the xorg list, and Roland pointed out 
that xorg-arch
is really the right list to discuss this since it is an API extension. 
He also pointed out that
the Xnest and Xdmx may need to be updated to be in sync with this change.



Søren

-------------- next part --------------
Index: include/extensions/shape.h
===================================================================
RCS file: /cvs/xorg/xc/include/extensions/shape.h,v
retrieving revision 1.2
diff -u -p -u -r1.2 shape.h
--- include/extensions/shape.h	23 Apr 2004 18:43:06 -0000	1.2
+++ include/extensions/shape.h	15 Mar 2005 22:47:17 -0000
@@ -50,6 +50,7 @@ in this Software without prior written a
 
 #define ShapeBounding			0
 #define ShapeClip			1
+#define ShapeInput			2
 
 #define ShapeNotifyMask			(1L << 0)
 #define ShapeNotify			0
Index: include/extensions/shapestr.h
===================================================================
RCS file: /cvs/xorg/xc/include/extensions/shapestr.h,v
retrieving revision 1.1.1.1
diff -u -p -u -r1.1.1.1 shapestr.h
--- include/extensions/shapestr.h	14 Nov 2003 16:48:43 -0000	1.1.1.1
+++ include/extensions/shapestr.h	15 Mar 2005 22:47:17 -0000
@@ -42,7 +42,7 @@ in this Software without prior written a
 #define SHAPENAME "SHAPE"
 
 #define SHAPE_MAJOR_VERSION	1	/* current version numbers */
-#define SHAPE_MINOR_VERSION	0
+#define SHAPE_MINOR_VERSION	1
 
 typedef struct _ShapeQueryVersion {
 	CARD8	reqType;		/* always ShapeReqCode */
Index: lib/X11/CrWindow.c
Index: programs/Xserver/Xext/shape.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xext/shape.c,v
retrieving revision 1.4
diff -u -p -u -r1.4 shape.c
--- programs/Xserver/Xext/shape.c	29 Jul 2004 23:43:39 -0000	1.4
+++ programs/Xserver/Xext/shape.c	15 Mar 2005 22:47:18 -0000
@@ -320,7 +320,6 @@ ProcShapeRectangles (client)
     RegionPtr		srcRgn;
     RegionPtr		*destRgn;
     CreateDftPtr	createDefault;
-    int			destBounding;
 
     REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
     UpdateCurrentTime();
@@ -329,13 +328,14 @@ ProcShapeRectangles (client)
 	return BadWindow;
     switch (stuff->destKind) {
     case ShapeBounding:
-	destBounding = 1;
 	createDefault = CreateBoundingShape;
 	break;
     case ShapeClip:
-	destBounding = 0;
 	createDefault = CreateClipShape;
 	break;
+    case ShapeInput:
+	createDefault = CreateBoundingShape;
+	break;
     default:
 	client->errorValue = stuff->destKind;
 	return BadValue;
@@ -359,10 +359,19 @@ ProcShapeRectangles (client)
 
     if (!pWin->optional)
 	MakeWindowOptional (pWin);
-    if (destBounding)
+    switch (stuff->destKind) {
+    case ShapeBounding:
 	destRgn = &pWin->optional->boundingShape;
-    else
+	break;
+    case ShapeClip:
 	destRgn = &pWin->optional->clipShape;
+	break;
+    case ShapeInput:
+	destRgn = &pWin->optional->inputShape;
+	break;
+    default:
+	return BadValue;
+    }
 
     return RegionOperate (client, pWin, (int)stuff->destKind,
 			  destRgn, srcRgn, (int)stuff->op,
@@ -410,7 +419,6 @@ ProcShapeMask (client)
     RegionPtr		*destRgn;
     PixmapPtr		pPixmap;
     CreateDftPtr	createDefault;
-    int			destBounding;
 
     REQUEST_SIZE_MATCH (xShapeMaskReq);
     UpdateCurrentTime();
@@ -419,13 +427,14 @@ ProcShapeMask (client)
 	return BadWindow;
     switch (stuff->destKind) {
     case ShapeBounding:
-	destBounding = 1;
 	createDefault = CreateBoundingShape;
 	break;
     case ShapeClip:
-	destBounding = 0;
 	createDefault = CreateClipShape;
 	break;
+    case ShapeInput:
+	createDefault = CreateBoundingShape;
+	break;
     default:
 	client->errorValue = stuff->destKind;
 	return BadValue;
@@ -448,10 +457,19 @@ ProcShapeMask (client)
 
     if (!pWin->optional)
 	MakeWindowOptional (pWin);
-    if (destBounding)
+    switch (stuff->destKind) {
+    case ShapeBounding:
 	destRgn = &pWin->optional->boundingShape;
-    else
+	break;
+    case ShapeClip:
 	destRgn = &pWin->optional->clipShape;
+	break;
+    case ShapeInput:
+	destRgn = &pWin->optional->inputShape;
+	break;
+    default:
+	return BadValue;
+    }
 
     return RegionOperate (client, pWin, (int)stuff->destKind,
 			  destRgn, srcRgn, (int)stuff->op,
@@ -508,7 +526,6 @@ ProcShapeCombine (client)
     CreateDftPtr	createDefault;
     CreateDftPtr	createSrc;
     RegionPtr		tmp;
-    int			destBounding;
 
     REQUEST_SIZE_MATCH (xShapeCombineReq);
     UpdateCurrentTime();
@@ -519,13 +536,14 @@ ProcShapeCombine (client)
 	MakeWindowOptional (pDestWin);
     switch (stuff->destKind) {
     case ShapeBounding:
-	destBounding = 1;
 	createDefault = CreateBoundingShape;
 	break;
     case ShapeClip:
-	destBounding = 0;
 	createDefault = CreateClipShape;
 	break;
+    case ShapeInput:
+	createDefault = CreateBoundingShape;
+	break;
     default:
 	client->errorValue = stuff->destKind;
 	return BadValue;
@@ -544,6 +562,10 @@ ProcShapeCombine (client)
 	srcRgn = wClipShape (pSrcWin);
 	createSrc = CreateClipShape;
 	break;
+    case ShapeInput:
+	srcRgn = wInputShape (pSrcWin);
+	createSrc = CreateBoundingShape;
+	break;
     default:
 	client->errorValue = stuff->srcKind;
 	return BadValue;
@@ -562,10 +584,19 @@ ProcShapeCombine (client)
 
     if (!pDestWin->optional)
 	MakeWindowOptional (pDestWin);
-    if (destBounding)
+    switch (stuff->destKind) {
+    case ShapeBounding:
 	destRgn = &pDestWin->optional->boundingShape;
-    else
+	break;
+    case ShapeClip:
 	destRgn = &pDestWin->optional->clipShape;
+	break;
+    case ShapeInput:
+	destRgn = &pDestWin->optional->inputShape;
+	break;
+    default:
+	return BadValue;
+    }
 
     return RegionOperate (client, pDestWin, (int)stuff->destKind,
 			  destRgn, srcRgn, (int)stuff->op,
@@ -627,6 +658,9 @@ ProcShapeOffset (client)
     case ShapeClip:
 	srcRgn = wClipShape(pWin);
 	break;
+    case ShapeInput:
+	srcRgn = wInputShape (pWin);
+	break;
     default:
 	client->errorValue = stuff->destKind;
 	return BadValue;
@@ -888,7 +922,8 @@ SendShapeNotify (pWin, which)
     pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType);
     if (!pHead)
 	return;
-    if (which == ShapeBounding) {
+    switch (which) {
+    case ShapeBounding:
 	region = wBoundingShape(pWin);
 	if (region) {
 	    extents = *REGION_EXTENTS(pWin->drawable.pScreen, region);
@@ -900,7 +935,8 @@ SendShapeNotify (pWin, which)
 	    extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
 	    shaped = xFalse;
 	}
-    } else {
+	break;
+    case ShapeClip:
 	region = wClipShape(pWin);
 	if (region) {
 	    extents = *REGION_EXTENTS(pWin->drawable.pScreen, region);
@@ -912,6 +948,22 @@ SendShapeNotify (pWin, which)
 	    extents.y2 = pWin->drawable.height;
 	    shaped = xFalse;
 	}
+	break;
+    case ShapeInput:
+	region = wInputShape(pWin);
+	if (region) {
+	    extents = *REGION_EXTENTS(pWin->drawable.pScreen, region);
+	    shaped = xTrue;
+	} else {
+	    extents.x1 = -wBorderWidth (pWin);
+	    extents.y1 = -wBorderWidth (pWin);
+	    extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
+	    extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
+	    shaped = xFalse;
+	}
+	break;
+    default:
+	return;
     }
     for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
 	client = pShapeEvent->client;
@@ -995,6 +1047,9 @@ ProcShapeGetRectangles (client)
     case ShapeClip:
 	region = wClipShape(pWin);
 	break;
+    case ShapeInput:
+	region = wInputShape (pWin);
+	break;
     default:
 	client->errorValue = stuff->kind;
 	return BadValue;
@@ -1017,6 +1072,12 @@ ProcShapeGetRectangles (client)
 	    rects->width = pWin->drawable.width;
 	    rects->height = pWin->drawable.height;
 	    break;
+	case ShapeInput:
+	    rects->x = - (int) wBorderWidth (pWin);
+	    rects->y = - (int) wBorderWidth (pWin);
+	    rects->width = pWin->drawable.width + wBorderWidth (pWin);
+	    rects->height = pWin->drawable.height + wBorderWidth (pWin);
+	    break;
 	}
     } else {
 	BoxPtr box;
Index: programs/Xserver/dix/dispatch.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/dix/dispatch.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 dispatch.c
--- programs/Xserver/dix/dispatch.c	7 Mar 2005 23:02:58 -0000	1.7
+++ programs/Xserver/dix/dispatch.c	15 Mar 2005 22:47:18 -0000
@@ -1249,6 +1249,12 @@ ProcTranslateCoords(register ClientPtr c
 		&& (!wBoundingShape(pWin) ||
 		    POINT_IN_REGION(pWin->drawable.pScreen, 
 					&pWin->borderSize, x, y, &box))
+		
+		&& (!wInputShape(pWin) ||
+		    POINT_IN_REGION(pWin->drawable.pScreen,
+				    wInputShape(pWin),
+				    x - pWin->drawable.x,
+				    y - pWin->drawable.y, &box))
 #endif
 		)
             {
Index: programs/Xserver/dix/events.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/dix/events.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 events.c
--- programs/Xserver/dix/events.c	7 Mar 2005 23:02:58 -0000	1.7
+++ programs/Xserver/dix/events.c	15 Mar 2005 22:47:18 -0000
@@ -1896,26 +1896,32 @@ static WindowPtr 
 XYToWindow(int x, int y)
 {
     register WindowPtr  pWin;
+    BoxRec		box;
 
     spriteTraceGood = 1;	/* root window still there */
     pWin = ROOT->firstChild;
     while (pWin)
     {
 	if ((pWin->mapped) &&
-		(x >= pWin->drawable.x - wBorderWidth (pWin)) &&
-		(x < pWin->drawable.x + (int)pWin->drawable.width +
-		    wBorderWidth(pWin)) &&
-		(y >= pWin->drawable.y - wBorderWidth (pWin)) &&
-		(y < pWin->drawable.y + (int)pWin->drawable.height +
-		    wBorderWidth (pWin))
+	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
+	    (x < pWin->drawable.x + (int)pWin->drawable.width +
+	     wBorderWidth(pWin)) &&
+	    (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
+	    (y < pWin->drawable.y + (int)pWin->drawable.height +
+	     wBorderWidth (pWin))
 #ifdef SHAPE
-		/* When a window is shaped, a further check
-		 * is made to see if the point is inside
-		 * borderSize
-		 */
-		&& (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+	    /* When a window is shaped, a further check
+	     * is made to see if the point is inside
+	     * borderSize
+	     */
+	    && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+	    && (!wInputShape(pWin) ||
+		POINT_IN_REGION(pWin->drawable.pScreen,
+				wInputShape(pWin),
+				x - pWin->drawable.x,
+				y - pWin->drawable.y, &box))
 #endif
-		)
+	    )
 	{
 	    if (spriteTraceGood >= spriteTraceSize)
 	    {
@@ -2161,7 +2167,12 @@ XineramaPointInWindowIsVisible(
 	x = xoff - panoramiXdataPtr[i].x;
 	y = yoff - panoramiXdataPtr[i].y;
 
-	if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
+	if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)
+	   && (!wInputShape(pWin) ||
+	       POINT_IN_REGION(pWin->drawable.pScreen,
+			       wInputShape(pWin),
+			       x - pWin->drawable.x, 
+			       y - pWin->drawable.y, &box)))
             return TRUE;
 
     }
Index: programs/Xserver/dix/window.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/dix/window.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 window.c
--- programs/Xserver/dix/window.c	7 Mar 2005 23:02:59 -0000	1.7
+++ programs/Xserver/dix/window.c	15 Mar 2005 22:47:19 -0000
@@ -414,6 +414,7 @@ CreateRootWindow(ScreenPtr pScreen)
 #ifdef SHAPE
     pWin->optional->boundingShape = NULL;
     pWin->optional->clipShape = NULL;
+    pWin->optional->inputShape = NULL;
 #endif
 #ifdef XINPUT
     pWin->optional->inputMasks = NULL;
@@ -800,6 +801,8 @@ FreeWindowResources(register WindowPtr p
 	REGION_DESTROY(pScreen, wBoundingShape (pWin));
     if (wClipShape (pWin))
 	REGION_DESTROY(pScreen, wClipShape (pWin));
+    if (wInputShape (pWin))
+	REGION_DESTROY(pScreen, wInputShape (pWin));
 #endif
     if (pWin->borderIsPixel == FALSE)
 	(*pScreen->DestroyPixmap)(pWin->border.pixmap);
@@ -3182,7 +3185,12 @@ PointInWindowIsVisible(register WindowPt
     if (!pWin->realized)
 	return (FALSE);
     if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip,
-						  x, y, &box))
+						  x, y, &box)
+	&& (!wInputShape(pWin) ||
+	    POINT_IN_REGION(pWin->drawable.pScreen,
+			    wInputShape(pWin),
+			    x - pWin->drawable.x, 
+			    y - pWin->drawable.y, &box)))
 	return(TRUE);
     return(FALSE);
 }
@@ -3558,6 +3566,8 @@ CheckWindowOptionalNeed (register Window
 	return;
     if (optional->clipShape != NULL)
 	return;
+    if (optional->inputShape != NULL)
+	return;
 #endif
 #ifdef XINPUT
     if (optional->inputMasks != NULL)
@@ -3603,6 +3613,7 @@ MakeWindowOptional (register WindowPtr p
 #ifdef SHAPE
     optional->boundingShape = NULL;
     optional->clipShape = NULL;
+    optional->inputShape = NULL;
 #endif
 #ifdef XINPUT
     optional->inputMasks = NULL;
Index: programs/Xserver/include/windowstr.h
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/include/windowstr.h,v
retrieving revision 1.4
diff -u -p -u -r1.4 windowstr.h
--- programs/Xserver/include/windowstr.h	31 Jul 2004 08:24:13 -0000	1.4
+++ programs/Xserver/include/windowstr.h	15 Mar 2005 22:47:21 -0000
@@ -86,6 +86,7 @@ typedef struct _WindowOpt {
 #ifdef SHAPE
     RegionPtr		boundingShape;	   /* default: NULL */
     RegionPtr		clipShape;	   /* default: NULL */
+    RegionPtr		inputShape;	   /* default: NULL */
 #endif
 #ifdef XINPUT
     struct _OtherInputMasks *inputMasks;   /* default: NULL */
@@ -174,6 +175,7 @@ extern Mask	    DontPropagateMasks[];
 #ifdef SHAPE
 #define wBoundingShape(w)	wUseDefault(w, boundingShape, NULL)
 #define wClipShape(w)		wUseDefault(w, clipShape, NULL)
+#define wInputShape(w)          wUseDefault(w, inputShape, NULL)
 #endif
 #define wClient(w)		(clients[CLIENT_ID((w)->drawable.id)])
 #define wBorderWidth(w)		((int) (w)->borderWidth)
Index: programs/Xserver/xfixes/region.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/xfixes/region.c,v
retrieving revision 1.3
diff -u -p -u -r1.3 region.c
--- programs/Xserver/xfixes/region.c	31 Jul 2004 07:26:50 -0000	1.3
+++ programs/Xserver/xfixes/region.c	15 Mar 2005 22:47:23 -0000
@@ -675,7 +675,6 @@ ProcXFixesSetWindowShapeRegion (ClientPt
     ScreenPtr	    pScreen;
     RegionPtr	    pRegion;
     RegionPtr	    *pDestRegion;
-    int		    destBounding;
     REQUEST(xXFixesSetWindowShapeRegionReq);
 
     REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
@@ -686,18 +685,16 @@ ProcXFixesSetWindowShapeRegion (ClientPt
 	return BadWindow;
     }
     VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, SecurityWriteAccess);
+    pScreen = pWin->drawable.pScreen;
     switch (stuff->destKind) {
     case ShapeBounding:
-	destBounding = 1;
-	break;
     case ShapeClip:
-	destBounding = 0;
+    case ShapeInput:
 	break;
     default:
 	client->errorValue = stuff->destKind;
 	return BadValue;
     }
-    pScreen = pWin->drawable.pScreen;
     if (pRegion)
     {
 	pRegion = XFixesRegionCopy (pRegion);
@@ -705,10 +702,18 @@ ProcXFixesSetWindowShapeRegion (ClientPt
 	    return BadAlloc;
 	if (!pWin->optional)
 	    MakeWindowOptional (pWin);
-	if (destBounding)
+	switch (stuff->destKind) {
+	default:
+	case ShapeBounding:
 	    pDestRegion = &pWin->optional->boundingShape;
-	else
+	    break;
+	case ShapeClip:
 	    pDestRegion = &pWin->optional->clipShape;
+	    break;
+	case ShapeInput:
+	    pDestRegion = &pWin->optional->inputShape;
+	    break;
+	}
 	if (stuff->xOff || stuff->yOff)
 	    REGION_TRANSLATE (0, pRegion, stuff->xOff, stuff->yOff);
     }
@@ -716,10 +721,18 @@ ProcXFixesSetWindowShapeRegion (ClientPt
     {
 	if (pWin->optional)
 	{
-	    if (destBounding)
+	    switch (stuff->destKind) {
+	    default:
+	    case ShapeBounding:
 		pDestRegion = &pWin->optional->boundingShape;
-	    else
+		break;
+	    case ShapeClip:
 		pDestRegion = &pWin->optional->clipShape;
+		break;
+	    case ShapeInput:
+		pDestRegion = &pWin->optional->inputShape;
+		break;
+	    }
 	}
 	else
 	    pDestRegion = &pRegion; /* a NULL region pointer */


More information about the xorg-arch mailing list