/* * $Id: region.c,v 1.7 2005/07/03 07:37:35 daniels Exp $ * * Copyright © 2003 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Keith Packard not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Keith Packard makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif #include "xfixesint.h" #include "scrnintstr.h" #ifdef RENDER #include <picturestr.h> extern int RenderErrBase; #endif #include <regionstr.h> #include <gcstruct.h> #include <window.h> RESTYPE RegionResType; static int RegionResFree (void * data, XID id) { RegionPtr pRegion = (RegionPtr) data; RegionDestroy(pRegion); return Success; } RegionPtr XFixesRegionCopy (RegionPtr pRegion) { RegionPtr pNew = RegionCreate(RegionExtents(pRegion), RegionNumRects(pRegion)); if (!pNew) return 0; if (!RegionCopy(pNew, pRegion)) { RegionDestroy(pNew); return 0; } return pNew; } Bool XFixesRegionInit (void) { RegionResType = CreateNewResourceType(RegionResFree); return TRUE; } int ProcXFixesCreateRegion (ClientPtr client) { int things; RegionPtr pRegion; REQUEST (xXFixesCreateRegionReq); REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq); LEGAL_NEW_RESOURCE (stuff->region, client); things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq); if (things & 4) return BadLength; things >>= 3; pRegion = RegionFromRects(things, (xRectangle *) (stuff + 1), CT_UNSORTED); if (!pRegion) return BadAlloc; if (!AddResource (stuff->region, RegionResType, (void *) pRegion)) return BadAlloc; return(client->noClientException); } int SProcXFixesCreateRegion (ClientPtr client) { register int n; REQUEST(xXFixesCreateRegionReq); swaps(&stuff->length, n); REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq); swapl(&stuff->region, n); SwapRestS(stuff); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesCreateRegionFromBitmap (ClientPtr client) { RegionPtr pRegion; PixmapPtr pPixmap; REQUEST (xXFixesCreateRegionFromBitmapReq); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq); LEGAL_NEW_RESOURCE (stuff->region, client); pPixmap = (PixmapPtr) SecurityLookupIDByType (client, stuff->bitmap, RT_PIXMAP, SecurityReadAccess); if (!pPixmap) { client->errorValue = stuff->bitmap; return BadPixmap; } if (pPixmap->drawable.depth != 1) return BadMatch; pRegion = BitmapToRegion(pPixmap->drawable.pScreen, pPixmap); if (!pRegion) return BadAlloc; if (!AddResource (stuff->region, RegionResType, (void *) pRegion)) return BadAlloc; return(client->noClientException); } int SProcXFixesCreateRegionFromBitmap (ClientPtr client) { int n; REQUEST (xXFixesCreateRegionFromBitmapReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq); swapl(&stuff->region, n); swapl(&stuff->bitmap, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesCreateRegionFromWindow (ClientPtr client) { RegionPtr pRegion; Bool copy = TRUE; WindowPtr pWin; REQUEST (xXFixesCreateRegionFromWindowReq); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq); LEGAL_NEW_RESOURCE (stuff->region, client); pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } switch (stuff->kind) { case WindowRegionBounding: #ifdef SHAPE pRegion = wBoundingShape(pWin); if (!pRegion) #endif { pRegion = CreateBoundingShape (pWin); copy = FALSE; } break; case WindowRegionClip: #ifdef SHAPE pRegion = wClipShape(pWin); if (!pRegion) #endif { pRegion = CreateClipShape (pWin); copy = FALSE; } break; default: client->errorValue = stuff->kind; return BadValue; } if (copy && pRegion) pRegion = XFixesRegionCopy (pRegion); if (!pRegion) return BadAlloc; if (!AddResource (stuff->region, RegionResType, (void *) pRegion)) return BadAlloc; return(client->noClientException); } int SProcXFixesCreateRegionFromWindow (ClientPtr client) { int n; REQUEST (xXFixesCreateRegionFromWindowReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq); swapl(&stuff->region, n); swapl(&stuff->window, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesCreateRegionFromGC (ClientPtr client) { RegionPtr pRegion, pClip; GCPtr pGC; REQUEST (xXFixesCreateRegionFromGCReq); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq); LEGAL_NEW_RESOURCE (stuff->region, client); SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityReadAccess); switch (pGC->clientClipType) { case CT_PIXMAP: pRegion = BitmapToRegion(pGC->pScreen, (PixmapPtr) pGC->clientClip); if (!pRegion) return BadAlloc; break; case CT_REGION: pClip = (RegionPtr) pGC->clientClip; pRegion = XFixesRegionCopy (pClip); if (!pRegion) return BadAlloc; break; default: return BadImplementation; /* assume sane server bits */ } if (!AddResource (stuff->region, RegionResType, (void *) pRegion)) return BadAlloc; return(client->noClientException); } int SProcXFixesCreateRegionFromGC (ClientPtr client) { int n; REQUEST (xXFixesCreateRegionFromGCReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq); swapl(&stuff->region, n); swapl(&stuff->gc, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesCreateRegionFromPicture (ClientPtr client) { #ifdef RENDER RegionPtr pRegion; PicturePtr pPicture; REQUEST (xXFixesCreateRegionFromPictureReq); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq); LEGAL_NEW_RESOURCE (stuff->region, client); VERIFY_PICTURE(pPicture, stuff->picture, client, SecurityReadAccess, RenderErrBase + BadPicture); switch (pPicture->clientClipType) { case CT_PIXMAP: pRegion = BitmapToRegion(pPicture->pDrawable->pScreen, (PixmapPtr) pPicture->clientClip); if (!pRegion) return BadAlloc; break; case CT_REGION: pRegion = XFixesRegionCopy ((RegionPtr) pPicture->clientClip); if (!pRegion) return BadAlloc; break; default: return BadImplementation; /* assume sane server bits */ } if (!AddResource (stuff->region, RegionResType, (void *) pRegion)) return BadAlloc; return(client->noClientException); #else return BadRequest; #endif } int SProcXFixesCreateRegionFromPicture (ClientPtr client) { int n; REQUEST (xXFixesCreateRegionFromPictureReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq); swapl(&stuff->region, n); swapl(&stuff->picture, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesDestroyRegion (ClientPtr client) { REQUEST (xXFixesDestroyRegionReq); RegionPtr pRegion; REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq); VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess); FreeResource (stuff->region, RT_NONE); return(client->noClientException); } int SProcXFixesDestroyRegion (ClientPtr client) { int n; REQUEST (xXFixesDestroyRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq); swapl (&stuff->region, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesSetRegion (ClientPtr client) { int things; RegionPtr pRegion, pNew; REQUEST (xXFixesSetRegionReq); REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq); VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess); things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq); if (things & 4) return BadLength; things >>= 3; pNew = RegionFromRects(things, (xRectangle *) (stuff + 1), CT_UNSORTED); if (!pNew) return BadAlloc; if (!RegionCopy(pRegion, pNew)) { RegionDestroy(pNew); return BadAlloc; } RegionDestroy(pNew); return(client->noClientException); } int SProcXFixesSetRegion (ClientPtr client) { int n; REQUEST (xXFixesSetRegionReq); swaps (&stuff->length, n); REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq); swapl (&stuff->region, n); SwapRestS(stuff); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesCopyRegion (ClientPtr client) { RegionPtr pSource, pDestination; REQUEST (xXFixesCopyRegionReq); VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess); VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess); if (!RegionCopy(pDestination, pSource)) return BadAlloc; return(client->noClientException); } int SProcXFixesCopyRegion (ClientPtr client) { int n; REQUEST (xXFixesCopyRegionReq); swaps (&stuff->length, n); REQUEST_AT_LEAST_SIZE(xXFixesCopyRegionReq); swapl (&stuff->source, n); swapl (&stuff->destination, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesCombineRegion (ClientPtr client) { RegionPtr pSource1, pSource2, pDestination; int ret = Success; REQUEST (xXFixesCombineRegionReq); REQUEST_SIZE_MATCH (xXFixesCombineRegionReq); VERIFY_REGION(pSource1, stuff->source1, client, SecurityReadAccess); VERIFY_REGION(pSource2, stuff->source2, client, SecurityReadAccess); VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess); switch (stuff->xfixesReqType) { case X_XFixesUnionRegion: if (!RegionUnion(pDestination, pSource1, pSource2)) ret = BadAlloc; break; case X_XFixesIntersectRegion: if (!RegionIntersect(pDestination, pSource1, pSource2)) ret = BadAlloc; break; case X_XFixesSubtractRegion: if (!RegionSubtract(pDestination, pSource1, pSource2)) ret = BadAlloc; break; } if (ret == Success) ret = client->noClientException; return ret; } int SProcXFixesCombineRegion (ClientPtr client) { int n; REQUEST (xXFixesCombineRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH (xXFixesCombineRegionReq); swapl (&stuff->source1, n); swapl (&stuff->source2, n); swapl (&stuff->destination, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesInvertRegion (ClientPtr client) { RegionPtr pSource, pDestination; BoxRec bounds; int ret = Success; REQUEST(xXFixesInvertRegionReq); REQUEST_SIZE_MATCH(xXFixesInvertRegionReq); VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess); VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess); /* Compute bounds, limit to 16 bits */ bounds.x1 = stuff->x; bounds.y1 = stuff->y; if ((int) stuff->x + (int) stuff->width > MAXSHORT) bounds.x2 = MAXSHORT; else bounds.x2 = stuff->x + stuff->width; if ((int) stuff->y + (int) stuff->height > MAXSHORT) bounds.y2 = MAXSHORT; else bounds.y2 = stuff->y + stuff->height; if (!RegionInverse(pDestination, pSource, &bounds)) ret = BadAlloc; if (ret == Success) ret = client->noClientException; return ret; } int SProcXFixesInvertRegion (ClientPtr client) { int n; REQUEST(xXFixesInvertRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXFixesInvertRegionReq); swapl (&stuff->source, n); swaps (&stuff->x, n); swaps (&stuff->y, n); swaps (&stuff->width, n); swaps (&stuff->height, n); swapl (&stuff->destination, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesTranslateRegion (ClientPtr client) { RegionPtr pRegion; REQUEST(xXFixesTranslateRegionReq); REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq); VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess); RegionTranslate(pRegion, stuff->dx, stuff->dy); return (client->noClientException); } int SProcXFixesTranslateRegion (ClientPtr client) { int n; REQUEST(xXFixesTranslateRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq); swapl (&stuff->region, n); swaps (&stuff->dx, n); swaps (&stuff->dy, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesRegionExtents (ClientPtr client) { RegionPtr pSource, pDestination; REQUEST(xXFixesRegionExtentsReq); REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq); VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess); VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess); RegionReset(pDestination, RegionExtents(pSource)); return (client->noClientException); } int SProcXFixesRegionExtents (ClientPtr client) { int n; REQUEST(xXFixesRegionExtentsReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq); swapl (&stuff->source, n); swapl (&stuff->destination, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesFetchRegion (ClientPtr client) { RegionPtr pRegion; xXFixesFetchRegionReply *reply; xRectangle *pRect; BoxPtr pExtent; BoxPtr pBox; int i, nBox; REQUEST(xXFixesFetchRegionReq); REQUEST_SIZE_MATCH(xXFixesFetchRegionReq); VERIFY_REGION(pRegion, stuff->region, client, SecurityReadAccess); pExtent = RegionExtents(pRegion); pBox = RegionRects (pRegion); nBox = RegionNumRects (pRegion); reply = xalloc (sizeof (xXFixesFetchRegionReply) + nBox * sizeof (xRectangle)); if (!reply) return BadAlloc; reply->type = X_Reply; reply->sequenceNumber = client->sequence; reply->length = nBox << 1; reply->x = pExtent->x1; reply->y = pExtent->y1; reply->width = pExtent->x2 - pExtent->x1; reply->height = pExtent->y2 - pExtent->y1; pRect = (xRectangle *) (reply + 1); for (i = 0; i < nBox; i++) { pRect[i].x = pBox[i].x1; pRect[i].y = pBox[i].y1; pRect[i].width = pBox[i].x2 - pBox[i].x1; pRect[i].height = pBox[i].y2 - pBox[i].y1; } if (client->swapped) { int n; swaps (&reply->sequenceNumber, n); swapl (&reply->length, n); swaps (&reply->x, n); swaps (&reply->y, n); swaps (&reply->width, n); swaps (&reply->height, n); SwapShorts ((INT16 *) pRect, nBox * 4); } (void) WriteToClient(client, sizeof (xXFixesFetchRegionReply) + nBox * sizeof (xRectangle), (char *) reply); xfree (reply); return (client->noClientException); } int SProcXFixesFetchRegion (ClientPtr client) { int n; REQUEST(xXFixesFetchRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXFixesFetchRegionReq); swapl (&stuff->region, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesSetGCClipRegion (ClientPtr client) { GCPtr pGC; RegionPtr pRegion; XID vals[2]; REQUEST(xXFixesSetGCClipRegionReq); REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq); SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); VERIFY_REGION_OR_NONE (pRegion, stuff->region, client, SecurityReadAccess); if (pRegion) { pRegion = XFixesRegionCopy (pRegion); if (!pRegion) return BadAlloc; } vals[0] = stuff->xOrigin; vals[1] = stuff->yOrigin; DoChangeGC (pGC, GCClipXOrigin|GCClipYOrigin, vals, 0); (*pGC->funcs->ChangeClip)(pGC, pRegion ? CT_REGION : CT_NONE, (void *)pRegion, 0); return (client->noClientException); } int SProcXFixesSetGCClipRegion (ClientPtr client) { int n; REQUEST(xXFixesSetGCClipRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq); swapl (&stuff->gc, n); swapl (&stuff->region, n); swaps (&stuff->xOrigin, n); swaps (&stuff->yOrigin, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } typedef RegionPtr (*CreateDftPtr)(WindowPtr pWin); int ProcXFixesSetWindowShapeRegion (ClientPtr client) { #ifdef SHAPE WindowPtr pWin; ScreenPtr pScreen; RegionPtr pRegion; RegionPtr *pDestRegion; REQUEST(xXFixesSetWindowShapeRegionReq); REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq); pWin = (WindowPtr) LookupIDByType (stuff->dest, RT_WINDOW); if (!pWin) { client->errorValue = stuff->dest; return BadWindow; } VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, SecurityWriteAccess); pScreen = pWin->drawable.pScreen; switch (stuff->destKind) { case ShapeBounding: case ShapeClip: case ShapeInput: break; default: client->errorValue = stuff->destKind; return BadValue; } if (pRegion) { pRegion = XFixesRegionCopy (pRegion); if (!pRegion) return BadAlloc; if (!pWin->optional) MakeWindowOptional (pWin); switch (stuff->destKind) { default: case ShapeBounding: pDestRegion = &pWin->optional->boundingShape; break; case ShapeClip: pDestRegion = &pWin->optional->clipShape; break; case ShapeInput: pDestRegion = &pWin->optional->inputShape; break; } if (stuff->xOff || stuff->yOff) RegionTranslate(pRegion, stuff->xOff, stuff->yOff); } else { if (pWin->optional) { switch (stuff->destKind) { default: case ShapeBounding: pDestRegion = &pWin->optional->boundingShape; break; case ShapeClip: pDestRegion = &pWin->optional->clipShape; break; case ShapeInput: pDestRegion = &pWin->optional->inputShape; break; } } else pDestRegion = &pRegion; /* a NULL region pointer */ } if (*pDestRegion) RegionDestroy(*pDestRegion); *pDestRegion = pRegion; (*pScreen->SetShape) (pWin); SendShapeNotify (pWin, stuff->destKind); return (client->noClientException); #else return BadRequest; #endif } int SProcXFixesSetWindowShapeRegion (ClientPtr client) { int n; REQUEST(xXFixesSetWindowShapeRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq); swapl (&stuff->dest, n); swaps (&stuff->xOff, n); swaps (&stuff->yOff, n); swapl (&stuff->region, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesSetPictureClipRegion (ClientPtr client) { #ifdef RENDER PicturePtr pPicture; RegionPtr pRegion; ScreenPtr pScreen; PictureScreenPtr ps; REQUEST(xXFixesSetPictureClipRegionReq); REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq); VERIFY_PICTURE(pPicture, stuff->picture, client, SecurityWriteAccess, RenderErrBase + BadPicture); pScreen = pPicture->pDrawable->pScreen; ps = GetPictureScreen (pScreen); VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, SecurityReadAccess); return SetPictureClipRegion (pPicture, stuff->xOrigin, stuff->yOrigin, pRegion); #else return BadRequest; #endif } int SProcXFixesSetPictureClipRegion (ClientPtr client) { int n; REQUEST(xXFixesSetPictureClipRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq); swapl (&stuff->picture, n); swapl (&stuff->region, n); swaps (&stuff->xOrigin, n); swaps (&stuff->yOrigin, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); } int ProcXFixesExpandRegion (ClientPtr client) { RegionPtr pSource, pDestination; int ret = Success; REQUEST (xXFixesExpandRegionReq); BoxPtr pTmp; BoxPtr pSrc; int nBoxes; int i; REQUEST_SIZE_MATCH (xXFixesExpandRegionReq); VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess); VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess); nBoxes = RegionNumRects(pSource); pSrc = RegionRects(pSource); if (nBoxes) { pTmp = xalloc (nBoxes * sizeof (BoxRec)); if (!pTmp) return BadAlloc; for (i = 0; i < nBoxes; i++) { pTmp[i].x1 = pSrc[i].x1 - stuff->left; pTmp[i].x2 = pSrc[i].x2 + stuff->right; pTmp[i].y1 = pSrc[i].y1 - stuff->top; pTmp[i].y2 = pSrc[i].y2 + stuff->bottom; } RegionEmpty(pDestination); for (i = 0; i < nBoxes; i++) { RegionRec r; RegionInit(&r, &pTmp[i], 0); RegionUnion(pDestination, pDestination, &r); } } if (ret == Success) ret = client->noClientException; return ret; } int SProcXFixesExpandRegion (ClientPtr client) { int n; REQUEST (xXFixesExpandRegionReq); swaps (&stuff->length, n); REQUEST_SIZE_MATCH (xXFixesExpandRegionReq); swapl (&stuff->source, n); swapl (&stuff->destination, n); swaps (&stuff->left, n); swaps (&stuff->right, n); swaps (&stuff->top, n); swaps (&stuff->bottom, n); return (*ProcXFixesVector[stuff->xfixesReqType]) (client); }