xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

shape.c (34710B)


      1 /************************************************************
      2 
      3 Copyright 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24 
     25 ********************************************************/
     26 
     27 #ifdef HAVE_DIX_CONFIG_H
     28 #include <dix-config.h>
     29 #endif
     30 
     31 #include <stdlib.h>
     32 
     33 #include <X11/X.h>
     34 #include <X11/Xproto.h>
     35 #include "misc.h"
     36 #include "os.h"
     37 #include "windowstr.h"
     38 #include "scrnintstr.h"
     39 #include "pixmapstr.h"
     40 #include "extnsionst.h"
     41 #include "dixstruct.h"
     42 #include "resource.h"
     43 #include "opaque.h"
     44 #include <X11/extensions/shapeproto.h>
     45 #include "regionstr.h"
     46 #include "gcstruct.h"
     47 #include "extinit.h"
     48 #include "protocol-versions.h"
     49 
     50 typedef RegionPtr (*CreateDftPtr) (WindowPtr    /* pWin */
     51     );
     52 
     53 static int ShapeFreeClient(void * /* data */ ,
     54                            XID    /* id */
     55     );
     56 static int ShapeFreeEvents(void * /* data */ ,
     57                            XID    /* id */
     58     );
     59 static void SShapeNotifyEvent(xShapeNotifyEvent * /* from */ ,
     60                               xShapeNotifyEvent *       /* to */
     61     );
     62 
     63 /* SendShapeNotify, CreateBoundingShape and CreateClipShape are used
     64  * externally by the Xfixes extension and are now defined in window.h
     65  */
     66 
     67 #ifdef PANORAMIX
     68 #include "panoramiX.h"
     69 #include "panoramiXsrv.h"
     70 #endif
     71 
     72 static int ShapeEventBase = 0;
     73 static RESTYPE ClientType, ShapeEventType;      /* resource types for event masks */
     74 
     75 /*
     76  * each window has a list of clients requesting
     77  * ShapeNotify events.  Each client has a resource
     78  * for each window it selects ShapeNotify input for,
     79  * this resource is used to delete the ShapeNotifyRec
     80  * entry from the per-window queue.
     81  */
     82 
     83 typedef struct _ShapeEvent *ShapeEventPtr;
     84 
     85 typedef struct _ShapeEvent {
     86     ShapeEventPtr next;
     87     ClientPtr client;
     88     WindowPtr window;
     89     XID clientResource;
     90 } ShapeEventRec;
     91 
     92 /****************
     93  * ShapeExtensionInit
     94  *
     95  * Called from InitExtensions in main() or from QueryExtension() if the
     96  * extension is dynamically loaded.
     97  *
     98  ****************/
     99 
    100 static int
    101 RegionOperate(ClientPtr client,
    102               WindowPtr pWin,
    103               int kind,
    104               RegionPtr *destRgnp,
    105               RegionPtr srcRgn, int op, int xoff, int yoff, CreateDftPtr create)
    106 {
    107     if (srcRgn && (xoff || yoff))
    108         RegionTranslate(srcRgn, xoff, yoff);
    109     if (!pWin->parent) {
    110         if (srcRgn)
    111             RegionDestroy(srcRgn);
    112         return Success;
    113     }
    114 
    115     /* May/30/2001:
    116      * The shape.PS specs say if src is None, existing shape is to be
    117      * removed (and so the op-code has no meaning in such removal);
    118      * see shape.PS, page 3, ShapeMask.
    119      */
    120     if (srcRgn == NULL) {
    121         if (*destRgnp != NULL) {
    122             RegionDestroy(*destRgnp);
    123             *destRgnp = 0;
    124             /* go on to remove shape and generate ShapeNotify */
    125         }
    126         else {
    127             /* May/30/2001:
    128              * The target currently has no shape in effect, so nothing to
    129              * do here.  The specs say that ShapeNotify is generated whenever
    130              * the client region is "modified"; since no modification is done
    131              * here, we do not generate that event.  The specs does not say
    132              * "it is an error to request removal when there is no shape in
    133              * effect", so we return good status.
    134              */
    135             return Success;
    136         }
    137     }
    138     else
    139         switch (op) {
    140         case ShapeSet:
    141             if (*destRgnp)
    142                 RegionDestroy(*destRgnp);
    143             *destRgnp = srcRgn;
    144             srcRgn = 0;
    145             break;
    146         case ShapeUnion:
    147             if (*destRgnp)
    148                 RegionUnion(*destRgnp, *destRgnp, srcRgn);
    149             break;
    150         case ShapeIntersect:
    151             if (*destRgnp)
    152                 RegionIntersect(*destRgnp, *destRgnp, srcRgn);
    153             else {
    154                 *destRgnp = srcRgn;
    155                 srcRgn = 0;
    156             }
    157             break;
    158         case ShapeSubtract:
    159             if (!*destRgnp)
    160                 *destRgnp = (*create) (pWin);
    161             RegionSubtract(*destRgnp, *destRgnp, srcRgn);
    162             break;
    163         case ShapeInvert:
    164             if (!*destRgnp)
    165                 *destRgnp = RegionCreate((BoxPtr) 0, 0);
    166             else
    167                 RegionSubtract(*destRgnp, srcRgn, *destRgnp);
    168             break;
    169         default:
    170             client->errorValue = op;
    171             return BadValue;
    172         }
    173     if (srcRgn)
    174         RegionDestroy(srcRgn);
    175     (*pWin->drawable.pScreen->SetShape) (pWin, kind);
    176     SendShapeNotify(pWin, kind);
    177     return Success;
    178 }
    179 
    180 RegionPtr
    181 CreateBoundingShape(WindowPtr pWin)
    182 {
    183     BoxRec extents;
    184 
    185     extents.x1 = -wBorderWidth(pWin);
    186     extents.y1 = -wBorderWidth(pWin);
    187     extents.x2 = pWin->drawable.width + wBorderWidth(pWin);
    188     extents.y2 = pWin->drawable.height + wBorderWidth(pWin);
    189     return RegionCreate(&extents, 1);
    190 }
    191 
    192 RegionPtr
    193 CreateClipShape(WindowPtr pWin)
    194 {
    195     BoxRec extents;
    196 
    197     extents.x1 = 0;
    198     extents.y1 = 0;
    199     extents.x2 = pWin->drawable.width;
    200     extents.y2 = pWin->drawable.height;
    201     return RegionCreate(&extents, 1);
    202 }
    203 
    204 static int
    205 ProcShapeQueryVersion(ClientPtr client)
    206 {
    207     xShapeQueryVersionReply rep = {
    208         .type = X_Reply,
    209         .sequenceNumber = client->sequence,
    210         .length = 0,
    211         .majorVersion = SERVER_SHAPE_MAJOR_VERSION,
    212         .minorVersion = SERVER_SHAPE_MINOR_VERSION
    213     };
    214 
    215     REQUEST_SIZE_MATCH(xShapeQueryVersionReq);
    216 
    217     if (client->swapped) {
    218         swaps(&rep.sequenceNumber);
    219         swapl(&rep.length);
    220         swaps(&rep.majorVersion);
    221         swaps(&rep.minorVersion);
    222     }
    223     WriteToClient(client, sizeof(xShapeQueryVersionReply), &rep);
    224     return Success;
    225 }
    226 
    227 /*****************
    228  * ProcShapeRectangles
    229  *
    230  *****************/
    231 
    232 static int
    233 ProcShapeRectangles(ClientPtr client)
    234 {
    235     WindowPtr pWin;
    236 
    237     REQUEST(xShapeRectanglesReq);
    238     xRectangle *prects;
    239     int nrects, ctype, rc;
    240     RegionPtr srcRgn;
    241     RegionPtr *destRgn;
    242     CreateDftPtr createDefault;
    243 
    244     REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq);
    245     UpdateCurrentTime();
    246     rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
    247     if (rc != Success)
    248         return rc;
    249     switch (stuff->destKind) {
    250     case ShapeBounding:
    251         createDefault = CreateBoundingShape;
    252         break;
    253     case ShapeClip:
    254         createDefault = CreateClipShape;
    255         break;
    256     case ShapeInput:
    257         createDefault = CreateBoundingShape;
    258         break;
    259     default:
    260         client->errorValue = stuff->destKind;
    261         return BadValue;
    262     }
    263     if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
    264         (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
    265         client->errorValue = stuff->ordering;
    266         return BadValue;
    267     }
    268     nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq));
    269     if (nrects & 4)
    270         return BadLength;
    271     nrects >>= 3;
    272     prects = (xRectangle *) &stuff[1];
    273     ctype = VerifyRectOrder(nrects, prects, (int) stuff->ordering);
    274     if (ctype < 0)
    275         return BadMatch;
    276     srcRgn = RegionFromRects(nrects, prects, ctype);
    277 
    278     if (!pWin->optional)
    279         MakeWindowOptional(pWin);
    280     switch (stuff->destKind) {
    281     case ShapeBounding:
    282         destRgn = &pWin->optional->boundingShape;
    283         break;
    284     case ShapeClip:
    285         destRgn = &pWin->optional->clipShape;
    286         break;
    287     case ShapeInput:
    288         destRgn = &pWin->optional->inputShape;
    289         break;
    290     default:
    291         return BadValue;
    292     }
    293 
    294     return RegionOperate(client, pWin, (int) stuff->destKind,
    295                          destRgn, srcRgn, (int) stuff->op,
    296                          stuff->xOff, stuff->yOff, createDefault);
    297 }
    298 
    299 #ifdef PANORAMIX
    300 static int
    301 ProcPanoramiXShapeRectangles(ClientPtr client)
    302 {
    303     REQUEST(xShapeRectanglesReq);
    304     PanoramiXRes *win;
    305     int j, result;
    306 
    307     REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq);
    308 
    309     result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW,
    310                                      client, DixWriteAccess);
    311     if (result != Success)
    312         return result;
    313 
    314     FOR_NSCREENS(j) {
    315         stuff->dest = win->info[j].id;
    316         result = ProcShapeRectangles(client);
    317         if (result != Success)
    318             break;
    319     }
    320     return result;
    321 }
    322 #endif
    323 
    324 /**************
    325  * ProcShapeMask
    326  **************/
    327 
    328 static int
    329 ProcShapeMask(ClientPtr client)
    330 {
    331     WindowPtr pWin;
    332     ScreenPtr pScreen;
    333 
    334     REQUEST(xShapeMaskReq);
    335     RegionPtr srcRgn;
    336     RegionPtr *destRgn;
    337     PixmapPtr pPixmap;
    338     CreateDftPtr createDefault;
    339     int rc;
    340 
    341     REQUEST_SIZE_MATCH(xShapeMaskReq);
    342     UpdateCurrentTime();
    343     rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
    344     if (rc != Success)
    345         return rc;
    346     switch (stuff->destKind) {
    347     case ShapeBounding:
    348         createDefault = CreateBoundingShape;
    349         break;
    350     case ShapeClip:
    351         createDefault = CreateClipShape;
    352         break;
    353     case ShapeInput:
    354         createDefault = CreateBoundingShape;
    355         break;
    356     default:
    357         client->errorValue = stuff->destKind;
    358         return BadValue;
    359     }
    360     pScreen = pWin->drawable.pScreen;
    361     if (stuff->src == None)
    362         srcRgn = 0;
    363     else {
    364         rc = dixLookupResourceByType((void **) &pPixmap, stuff->src,
    365                                      RT_PIXMAP, client, DixReadAccess);
    366         if (rc != Success)
    367             return rc;
    368         if (pPixmap->drawable.pScreen != pScreen ||
    369             pPixmap->drawable.depth != 1)
    370             return BadMatch;
    371         srcRgn = BitmapToRegion(pScreen, pPixmap);
    372         if (!srcRgn)
    373             return BadAlloc;
    374     }
    375 
    376     if (!pWin->optional)
    377         MakeWindowOptional(pWin);
    378     switch (stuff->destKind) {
    379     case ShapeBounding:
    380         destRgn = &pWin->optional->boundingShape;
    381         break;
    382     case ShapeClip:
    383         destRgn = &pWin->optional->clipShape;
    384         break;
    385     case ShapeInput:
    386         destRgn = &pWin->optional->inputShape;
    387         break;
    388     default:
    389         return BadValue;
    390     }
    391 
    392     return RegionOperate(client, pWin, (int) stuff->destKind,
    393                          destRgn, srcRgn, (int) stuff->op,
    394                          stuff->xOff, stuff->yOff, createDefault);
    395 }
    396 
    397 #ifdef PANORAMIX
    398 static int
    399 ProcPanoramiXShapeMask(ClientPtr client)
    400 {
    401     REQUEST(xShapeMaskReq);
    402     PanoramiXRes *win, *pmap;
    403     int j, result;
    404 
    405     REQUEST_SIZE_MATCH(xShapeMaskReq);
    406 
    407     result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW,
    408                                      client, DixWriteAccess);
    409     if (result != Success)
    410         return result;
    411 
    412     if (stuff->src != None) {
    413         result = dixLookupResourceByType((void **) &pmap, stuff->src,
    414                                          XRT_PIXMAP, client, DixReadAccess);
    415         if (result != Success)
    416             return result;
    417     }
    418     else
    419         pmap = NULL;
    420 
    421     FOR_NSCREENS(j) {
    422         stuff->dest = win->info[j].id;
    423         if (pmap)
    424             stuff->src = pmap->info[j].id;
    425         result = ProcShapeMask(client);
    426         if (result != Success)
    427             break;
    428     }
    429     return result;
    430 }
    431 #endif
    432 
    433 /************
    434  * ProcShapeCombine
    435  ************/
    436 
    437 static int
    438 ProcShapeCombine(ClientPtr client)
    439 {
    440     WindowPtr pSrcWin, pDestWin;
    441 
    442     REQUEST(xShapeCombineReq);
    443     RegionPtr srcRgn;
    444     RegionPtr *destRgn;
    445     CreateDftPtr createDefault;
    446     CreateDftPtr createSrc;
    447     RegionPtr tmp;
    448     int rc;
    449 
    450     REQUEST_SIZE_MATCH(xShapeCombineReq);
    451     UpdateCurrentTime();
    452     rc = dixLookupWindow(&pDestWin, stuff->dest, client, DixSetAttrAccess);
    453     if (rc != Success)
    454         return rc;
    455     if (!pDestWin->optional)
    456         MakeWindowOptional(pDestWin);
    457     switch (stuff->destKind) {
    458     case ShapeBounding:
    459         createDefault = CreateBoundingShape;
    460         break;
    461     case ShapeClip:
    462         createDefault = CreateClipShape;
    463         break;
    464     case ShapeInput:
    465         createDefault = CreateBoundingShape;
    466         break;
    467     default:
    468         client->errorValue = stuff->destKind;
    469         return BadValue;
    470     }
    471 
    472     rc = dixLookupWindow(&pSrcWin, stuff->src, client, DixGetAttrAccess);
    473     if (rc != Success)
    474         return rc;
    475     switch (stuff->srcKind) {
    476     case ShapeBounding:
    477         srcRgn = wBoundingShape(pSrcWin);
    478         createSrc = CreateBoundingShape;
    479         break;
    480     case ShapeClip:
    481         srcRgn = wClipShape(pSrcWin);
    482         createSrc = CreateClipShape;
    483         break;
    484     case ShapeInput:
    485         srcRgn = wInputShape(pSrcWin);
    486         createSrc = CreateBoundingShape;
    487         break;
    488     default:
    489         client->errorValue = stuff->srcKind;
    490         return BadValue;
    491     }
    492     if (pSrcWin->drawable.pScreen != pDestWin->drawable.pScreen) {
    493         return BadMatch;
    494     }
    495 
    496     if (srcRgn) {
    497         tmp = RegionCreate((BoxPtr) 0, 0);
    498         RegionCopy(tmp, srcRgn);
    499         srcRgn = tmp;
    500     }
    501     else
    502         srcRgn = (*createSrc) (pSrcWin);
    503 
    504     if (!pDestWin->optional)
    505         MakeWindowOptional(pDestWin);
    506     switch (stuff->destKind) {
    507     case ShapeBounding:
    508         destRgn = &pDestWin->optional->boundingShape;
    509         break;
    510     case ShapeClip:
    511         destRgn = &pDestWin->optional->clipShape;
    512         break;
    513     case ShapeInput:
    514         destRgn = &pDestWin->optional->inputShape;
    515         break;
    516     default:
    517         return BadValue;
    518     }
    519 
    520     return RegionOperate(client, pDestWin, (int) stuff->destKind,
    521                          destRgn, srcRgn, (int) stuff->op,
    522                          stuff->xOff, stuff->yOff, createDefault);
    523 }
    524 
    525 #ifdef PANORAMIX
    526 static int
    527 ProcPanoramiXShapeCombine(ClientPtr client)
    528 {
    529     REQUEST(xShapeCombineReq);
    530     PanoramiXRes *win, *win2;
    531     int j, result;
    532 
    533     REQUEST_AT_LEAST_SIZE(xShapeCombineReq);
    534 
    535     result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW,
    536                                      client, DixWriteAccess);
    537     if (result != Success)
    538         return result;
    539 
    540     result = dixLookupResourceByType((void **) &win2, stuff->src, XRT_WINDOW,
    541                                      client, DixReadAccess);
    542     if (result != Success)
    543         return result;
    544 
    545     FOR_NSCREENS(j) {
    546         stuff->dest = win->info[j].id;
    547         stuff->src = win2->info[j].id;
    548         result = ProcShapeCombine(client);
    549         if (result != Success)
    550             break;
    551     }
    552     return result;
    553 }
    554 #endif
    555 
    556 /*************
    557  * ProcShapeOffset
    558  *************/
    559 
    560 static int
    561 ProcShapeOffset(ClientPtr client)
    562 {
    563     WindowPtr pWin;
    564 
    565     REQUEST(xShapeOffsetReq);
    566     RegionPtr srcRgn;
    567     int rc;
    568 
    569     REQUEST_SIZE_MATCH(xShapeOffsetReq);
    570     UpdateCurrentTime();
    571     rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
    572     if (rc != Success)
    573         return rc;
    574     switch (stuff->destKind) {
    575     case ShapeBounding:
    576         srcRgn = wBoundingShape(pWin);
    577         break;
    578     case ShapeClip:
    579         srcRgn = wClipShape(pWin);
    580         break;
    581     case ShapeInput:
    582         srcRgn = wInputShape(pWin);
    583         break;
    584     default:
    585         client->errorValue = stuff->destKind;
    586         return BadValue;
    587     }
    588     if (srcRgn) {
    589         RegionTranslate(srcRgn, stuff->xOff, stuff->yOff);
    590         (*pWin->drawable.pScreen->SetShape) (pWin, stuff->destKind);
    591     }
    592     SendShapeNotify(pWin, (int) stuff->destKind);
    593     return Success;
    594 }
    595 
    596 #ifdef PANORAMIX
    597 static int
    598 ProcPanoramiXShapeOffset(ClientPtr client)
    599 {
    600     REQUEST(xShapeOffsetReq);
    601     PanoramiXRes *win;
    602     int j, result;
    603 
    604     REQUEST_AT_LEAST_SIZE(xShapeOffsetReq);
    605 
    606     result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW,
    607                                      client, DixWriteAccess);
    608     if (result != Success)
    609         return result;
    610 
    611     FOR_NSCREENS(j) {
    612         stuff->dest = win->info[j].id;
    613         result = ProcShapeOffset(client);
    614         if (result != Success)
    615             break;
    616     }
    617     return result;
    618 }
    619 #endif
    620 
    621 static int
    622 ProcShapeQueryExtents(ClientPtr client)
    623 {
    624     REQUEST(xShapeQueryExtentsReq);
    625     WindowPtr pWin;
    626     xShapeQueryExtentsReply rep;
    627     BoxRec extents, *pExtents;
    628     int rc;
    629     RegionPtr region;
    630 
    631     REQUEST_SIZE_MATCH(xShapeQueryExtentsReq);
    632     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    633     if (rc != Success)
    634         return rc;
    635     rep = (xShapeQueryExtentsReply) {
    636         .type = X_Reply,
    637         .sequenceNumber = client->sequence,
    638         .length = 0,
    639         .boundingShaped = (wBoundingShape(pWin) != 0),
    640         .clipShaped = (wClipShape(pWin) != 0)
    641     };
    642     if ((region = wBoundingShape(pWin))) {
    643         /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
    644         pExtents = RegionExtents(region);
    645         extents = *pExtents;
    646     }
    647     else {
    648         extents.x1 = -wBorderWidth(pWin);
    649         extents.y1 = -wBorderWidth(pWin);
    650         extents.x2 = pWin->drawable.width + wBorderWidth(pWin);
    651         extents.y2 = pWin->drawable.height + wBorderWidth(pWin);
    652     }
    653     rep.xBoundingShape = extents.x1;
    654     rep.yBoundingShape = extents.y1;
    655     rep.widthBoundingShape = extents.x2 - extents.x1;
    656     rep.heightBoundingShape = extents.y2 - extents.y1;
    657     if ((region = wClipShape(pWin))) {
    658         /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
    659         pExtents = RegionExtents(region);
    660         extents = *pExtents;
    661     }
    662     else {
    663         extents.x1 = 0;
    664         extents.y1 = 0;
    665         extents.x2 = pWin->drawable.width;
    666         extents.y2 = pWin->drawable.height;
    667     }
    668     rep.xClipShape = extents.x1;
    669     rep.yClipShape = extents.y1;
    670     rep.widthClipShape = extents.x2 - extents.x1;
    671     rep.heightClipShape = extents.y2 - extents.y1;
    672     if (client->swapped) {
    673         swaps(&rep.sequenceNumber);
    674         swapl(&rep.length);
    675         swaps(&rep.xBoundingShape);
    676         swaps(&rep.yBoundingShape);
    677         swaps(&rep.widthBoundingShape);
    678         swaps(&rep.heightBoundingShape);
    679         swaps(&rep.xClipShape);
    680         swaps(&rep.yClipShape);
    681         swaps(&rep.widthClipShape);
    682         swaps(&rep.heightClipShape);
    683     }
    684     WriteToClient(client, sizeof(xShapeQueryExtentsReply), &rep);
    685     return Success;
    686 }
    687 
    688  /*ARGSUSED*/ static int
    689 ShapeFreeClient(void *data, XID id)
    690 {
    691     ShapeEventPtr pShapeEvent;
    692     WindowPtr pWin;
    693     ShapeEventPtr *pHead, pCur, pPrev;
    694     int rc;
    695 
    696     pShapeEvent = (ShapeEventPtr) data;
    697     pWin = pShapeEvent->window;
    698     rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
    699                                  ShapeEventType, serverClient, DixReadAccess);
    700     if (rc == Success) {
    701         pPrev = 0;
    702         for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur = pCur->next)
    703             pPrev = pCur;
    704         if (pCur) {
    705             if (pPrev)
    706                 pPrev->next = pShapeEvent->next;
    707             else
    708                 *pHead = pShapeEvent->next;
    709         }
    710     }
    711     free((void *) pShapeEvent);
    712     return 1;
    713 }
    714 
    715  /*ARGSUSED*/ static int
    716 ShapeFreeEvents(void *data, XID id)
    717 {
    718     ShapeEventPtr *pHead, pCur, pNext;
    719 
    720     pHead = (ShapeEventPtr *) data;
    721     for (pCur = *pHead; pCur; pCur = pNext) {
    722         pNext = pCur->next;
    723         FreeResource(pCur->clientResource, ClientType);
    724         free((void *) pCur);
    725     }
    726     free((void *) pHead);
    727     return 1;
    728 }
    729 
    730 static int
    731 ProcShapeSelectInput(ClientPtr client)
    732 {
    733     REQUEST(xShapeSelectInputReq);
    734     WindowPtr pWin;
    735     ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead;
    736     XID clientResource;
    737     int rc;
    738 
    739     REQUEST_SIZE_MATCH(xShapeSelectInputReq);
    740     rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
    741     if (rc != Success)
    742         return rc;
    743     rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
    744                                  ShapeEventType, client, DixWriteAccess);
    745     if (rc != Success && rc != BadValue)
    746         return rc;
    747 
    748     switch (stuff->enable) {
    749     case xTrue:
    750         if (pHead) {
    751 
    752             /* check for existing entry. */
    753             for (pShapeEvent = *pHead;
    754                  pShapeEvent; pShapeEvent = pShapeEvent->next) {
    755                 if (pShapeEvent->client == client)
    756                     return Success;
    757             }
    758         }
    759 
    760         /* build the entry */
    761         pNewShapeEvent = malloc(sizeof(ShapeEventRec));
    762         if (!pNewShapeEvent)
    763             return BadAlloc;
    764         pNewShapeEvent->next = 0;
    765         pNewShapeEvent->client = client;
    766         pNewShapeEvent->window = pWin;
    767         /*
    768          * add a resource that will be deleted when
    769          * the client goes away
    770          */
    771         clientResource = FakeClientID(client->index);
    772         pNewShapeEvent->clientResource = clientResource;
    773         if (!AddResource(clientResource, ClientType, (void *) pNewShapeEvent))
    774             return BadAlloc;
    775         /*
    776          * create a resource to contain a void *to the list
    777          * of clients selecting input.  This must be indirect as
    778          * the list may be arbitrarily rearranged which cannot be
    779          * done through the resource database.
    780          */
    781         if (!pHead) {
    782             pHead = malloc(sizeof(ShapeEventPtr));
    783             if (!pHead ||
    784                 !AddResource(pWin->drawable.id, ShapeEventType,
    785                              (void *) pHead)) {
    786                 FreeResource(clientResource, RT_NONE);
    787                 return BadAlloc;
    788             }
    789             *pHead = 0;
    790         }
    791         pNewShapeEvent->next = *pHead;
    792         *pHead = pNewShapeEvent;
    793         break;
    794     case xFalse:
    795         /* delete the interest */
    796         if (pHead) {
    797             pNewShapeEvent = 0;
    798             for (pShapeEvent = *pHead; pShapeEvent;
    799                  pShapeEvent = pShapeEvent->next) {
    800                 if (pShapeEvent->client == client)
    801                     break;
    802                 pNewShapeEvent = pShapeEvent;
    803             }
    804             if (pShapeEvent) {
    805                 FreeResource(pShapeEvent->clientResource, ClientType);
    806                 if (pNewShapeEvent)
    807                     pNewShapeEvent->next = pShapeEvent->next;
    808                 else
    809                     *pHead = pShapeEvent->next;
    810                 free(pShapeEvent);
    811             }
    812         }
    813         break;
    814     default:
    815         client->errorValue = stuff->enable;
    816         return BadValue;
    817     }
    818     return Success;
    819 }
    820 
    821 /*
    822  * deliver the event
    823  */
    824 
    825 void
    826 SendShapeNotify(WindowPtr pWin, int which)
    827 {
    828     ShapeEventPtr *pHead, pShapeEvent;
    829     BoxRec extents;
    830     RegionPtr region;
    831     BYTE shaped;
    832     int rc;
    833 
    834     rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
    835                                  ShapeEventType, serverClient, DixReadAccess);
    836     if (rc != Success)
    837         return;
    838     switch (which) {
    839     case ShapeBounding:
    840         region = wBoundingShape(pWin);
    841         if (region) {
    842             extents = *RegionExtents(region);
    843             shaped = xTrue;
    844         }
    845         else {
    846             extents.x1 = -wBorderWidth(pWin);
    847             extents.y1 = -wBorderWidth(pWin);
    848             extents.x2 = pWin->drawable.width + wBorderWidth(pWin);
    849             extents.y2 = pWin->drawable.height + wBorderWidth(pWin);
    850             shaped = xFalse;
    851         }
    852         break;
    853     case ShapeClip:
    854         region = wClipShape(pWin);
    855         if (region) {
    856             extents = *RegionExtents(region);
    857             shaped = xTrue;
    858         }
    859         else {
    860             extents.x1 = 0;
    861             extents.y1 = 0;
    862             extents.x2 = pWin->drawable.width;
    863             extents.y2 = pWin->drawable.height;
    864             shaped = xFalse;
    865         }
    866         break;
    867     case ShapeInput:
    868         region = wInputShape(pWin);
    869         if (region) {
    870             extents = *RegionExtents(region);
    871             shaped = xTrue;
    872         }
    873         else {
    874             extents.x1 = -wBorderWidth(pWin);
    875             extents.y1 = -wBorderWidth(pWin);
    876             extents.x2 = pWin->drawable.width + wBorderWidth(pWin);
    877             extents.y2 = pWin->drawable.height + wBorderWidth(pWin);
    878             shaped = xFalse;
    879         }
    880         break;
    881     default:
    882         return;
    883     }
    884     UpdateCurrentTimeIf();
    885     for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
    886         xShapeNotifyEvent se = {
    887             .type = ShapeNotify + ShapeEventBase,
    888             .kind = which,
    889             .window = pWin->drawable.id,
    890             .x = extents.x1,
    891             .y = extents.y1,
    892             .width = extents.x2 - extents.x1,
    893             .height = extents.y2 - extents.y1,
    894             .time = currentTime.milliseconds,
    895             .shaped = shaped
    896         };
    897         WriteEventsToClient(pShapeEvent->client, 1, (xEvent *) &se);
    898     }
    899 }
    900 
    901 static int
    902 ProcShapeInputSelected(ClientPtr client)
    903 {
    904     REQUEST(xShapeInputSelectedReq);
    905     WindowPtr pWin;
    906     ShapeEventPtr pShapeEvent, *pHead;
    907     int enabled, rc;
    908     xShapeInputSelectedReply rep;
    909 
    910     REQUEST_SIZE_MATCH(xShapeInputSelectedReq);
    911     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    912     if (rc != Success)
    913         return rc;
    914     rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
    915                                  ShapeEventType, client, DixReadAccess);
    916     if (rc != Success && rc != BadValue)
    917         return rc;
    918     enabled = xFalse;
    919     if (pHead) {
    920         for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
    921             if (pShapeEvent->client == client) {
    922                 enabled = xTrue;
    923                 break;
    924             }
    925         }
    926     }
    927     rep = (xShapeInputSelectedReply) {
    928         .type = X_Reply,
    929         .enabled = enabled,
    930         .sequenceNumber = client->sequence,
    931         .length = 0
    932     };
    933     if (client->swapped) {
    934         swaps(&rep.sequenceNumber);
    935         swapl(&rep.length);
    936     }
    937     WriteToClient(client, sizeof(xShapeInputSelectedReply), &rep);
    938     return Success;
    939 }
    940 
    941 static int
    942 ProcShapeGetRectangles(ClientPtr client)
    943 {
    944     REQUEST(xShapeGetRectanglesReq);
    945     WindowPtr pWin;
    946     xShapeGetRectanglesReply rep;
    947     xRectangle *rects;
    948     int nrects, i, rc;
    949     RegionPtr region;
    950 
    951     REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
    952     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    953     if (rc != Success)
    954         return rc;
    955     switch (stuff->kind) {
    956     case ShapeBounding:
    957         region = wBoundingShape(pWin);
    958         break;
    959     case ShapeClip:
    960         region = wClipShape(pWin);
    961         break;
    962     case ShapeInput:
    963         region = wInputShape(pWin);
    964         break;
    965     default:
    966         client->errorValue = stuff->kind;
    967         return BadValue;
    968     }
    969     if (!region) {
    970         nrects = 1;
    971         rects = malloc(sizeof(xRectangle));
    972         if (!rects)
    973             return BadAlloc;
    974         switch (stuff->kind) {
    975         case ShapeBounding:
    976             rects->x = -(int) wBorderWidth(pWin);
    977             rects->y = -(int) wBorderWidth(pWin);
    978             rects->width = pWin->drawable.width + wBorderWidth(pWin);
    979             rects->height = pWin->drawable.height + wBorderWidth(pWin);
    980             break;
    981         case ShapeClip:
    982             rects->x = 0;
    983             rects->y = 0;
    984             rects->width = pWin->drawable.width;
    985             rects->height = pWin->drawable.height;
    986             break;
    987         case ShapeInput:
    988             rects->x = -(int) wBorderWidth(pWin);
    989             rects->y = -(int) wBorderWidth(pWin);
    990             rects->width = pWin->drawable.width + wBorderWidth(pWin);
    991             rects->height = pWin->drawable.height + wBorderWidth(pWin);
    992             break;
    993         }
    994     }
    995     else {
    996         BoxPtr box;
    997 
    998         nrects = RegionNumRects(region);
    999         box = RegionRects(region);
   1000         rects = xallocarray(nrects, sizeof(xRectangle));
   1001         if (!rects && nrects)
   1002             return BadAlloc;
   1003         for (i = 0; i < nrects; i++, box++) {
   1004             rects[i].x = box->x1;
   1005             rects[i].y = box->y1;
   1006             rects[i].width = box->x2 - box->x1;
   1007             rects[i].height = box->y2 - box->y1;
   1008         }
   1009     }
   1010     rep = (xShapeGetRectanglesReply) {
   1011         .type = X_Reply,
   1012         .ordering = YXBanded,
   1013         .sequenceNumber = client->sequence,
   1014         .length = bytes_to_int32(nrects * sizeof(xRectangle)),
   1015         .nrects = nrects
   1016     };
   1017     if (client->swapped) {
   1018         swaps(&rep.sequenceNumber);
   1019         swapl(&rep.length);
   1020         swapl(&rep.nrects);
   1021         SwapShorts((short *) rects, (unsigned long) nrects * 4);
   1022     }
   1023     WriteToClient(client, sizeof(rep), &rep);
   1024     WriteToClient(client, nrects * sizeof(xRectangle), rects);
   1025     free(rects);
   1026     return Success;
   1027 }
   1028 
   1029 static int
   1030 ProcShapeDispatch(ClientPtr client)
   1031 {
   1032     REQUEST(xReq);
   1033     switch (stuff->data) {
   1034     case X_ShapeQueryVersion:
   1035         return ProcShapeQueryVersion(client);
   1036     case X_ShapeRectangles:
   1037 #ifdef PANORAMIX
   1038         if (!noPanoramiXExtension)
   1039             return ProcPanoramiXShapeRectangles(client);
   1040         else
   1041 #endif
   1042             return ProcShapeRectangles(client);
   1043     case X_ShapeMask:
   1044 #ifdef PANORAMIX
   1045         if (!noPanoramiXExtension)
   1046             return ProcPanoramiXShapeMask(client);
   1047         else
   1048 #endif
   1049             return ProcShapeMask(client);
   1050     case X_ShapeCombine:
   1051 #ifdef PANORAMIX
   1052         if (!noPanoramiXExtension)
   1053             return ProcPanoramiXShapeCombine(client);
   1054         else
   1055 #endif
   1056             return ProcShapeCombine(client);
   1057     case X_ShapeOffset:
   1058 #ifdef PANORAMIX
   1059         if (!noPanoramiXExtension)
   1060             return ProcPanoramiXShapeOffset(client);
   1061         else
   1062 #endif
   1063             return ProcShapeOffset(client);
   1064     case X_ShapeQueryExtents:
   1065         return ProcShapeQueryExtents(client);
   1066     case X_ShapeSelectInput:
   1067         return ProcShapeSelectInput(client);
   1068     case X_ShapeInputSelected:
   1069         return ProcShapeInputSelected(client);
   1070     case X_ShapeGetRectangles:
   1071         return ProcShapeGetRectangles(client);
   1072     default:
   1073         return BadRequest;
   1074     }
   1075 }
   1076 
   1077 static void _X_COLD
   1078 SShapeNotifyEvent(xShapeNotifyEvent * from, xShapeNotifyEvent * to)
   1079 {
   1080     to->type = from->type;
   1081     to->kind = from->kind;
   1082     cpswapl(from->window, to->window);
   1083     cpswaps(from->sequenceNumber, to->sequenceNumber);
   1084     cpswaps(from->x, to->x);
   1085     cpswaps(from->y, to->y);
   1086     cpswaps(from->width, to->width);
   1087     cpswaps(from->height, to->height);
   1088     cpswapl(from->time, to->time);
   1089     to->shaped = from->shaped;
   1090 }
   1091 
   1092 static int _X_COLD
   1093 SProcShapeQueryVersion(ClientPtr client)
   1094 {
   1095     REQUEST(xShapeQueryVersionReq);
   1096 
   1097     swaps(&stuff->length);
   1098     return ProcShapeQueryVersion(client);
   1099 }
   1100 
   1101 static int _X_COLD
   1102 SProcShapeRectangles(ClientPtr client)
   1103 {
   1104     REQUEST(xShapeRectanglesReq);
   1105 
   1106     swaps(&stuff->length);
   1107     REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq);
   1108     swapl(&stuff->dest);
   1109     swaps(&stuff->xOff);
   1110     swaps(&stuff->yOff);
   1111     SwapRestS(stuff);
   1112     return ProcShapeRectangles(client);
   1113 }
   1114 
   1115 static int _X_COLD
   1116 SProcShapeMask(ClientPtr client)
   1117 {
   1118     REQUEST(xShapeMaskReq);
   1119 
   1120     swaps(&stuff->length);
   1121     REQUEST_SIZE_MATCH(xShapeMaskReq);
   1122     swapl(&stuff->dest);
   1123     swaps(&stuff->xOff);
   1124     swaps(&stuff->yOff);
   1125     swapl(&stuff->src);
   1126     return ProcShapeMask(client);
   1127 }
   1128 
   1129 static int _X_COLD
   1130 SProcShapeCombine(ClientPtr client)
   1131 {
   1132     REQUEST(xShapeCombineReq);
   1133 
   1134     swaps(&stuff->length);
   1135     REQUEST_SIZE_MATCH(xShapeCombineReq);
   1136     swapl(&stuff->dest);
   1137     swaps(&stuff->xOff);
   1138     swaps(&stuff->yOff);
   1139     swapl(&stuff->src);
   1140     return ProcShapeCombine(client);
   1141 }
   1142 
   1143 static int _X_COLD
   1144 SProcShapeOffset(ClientPtr client)
   1145 {
   1146     REQUEST(xShapeOffsetReq);
   1147 
   1148     swaps(&stuff->length);
   1149     REQUEST_SIZE_MATCH(xShapeOffsetReq);
   1150     swapl(&stuff->dest);
   1151     swaps(&stuff->xOff);
   1152     swaps(&stuff->yOff);
   1153     return ProcShapeOffset(client);
   1154 }
   1155 
   1156 static int _X_COLD
   1157 SProcShapeQueryExtents(ClientPtr client)
   1158 {
   1159     REQUEST(xShapeQueryExtentsReq);
   1160 
   1161     swaps(&stuff->length);
   1162     REQUEST_SIZE_MATCH(xShapeQueryExtentsReq);
   1163     swapl(&stuff->window);
   1164     return ProcShapeQueryExtents(client);
   1165 }
   1166 
   1167 static int _X_COLD
   1168 SProcShapeSelectInput(ClientPtr client)
   1169 {
   1170     REQUEST(xShapeSelectInputReq);
   1171 
   1172     swaps(&stuff->length);
   1173     REQUEST_SIZE_MATCH(xShapeSelectInputReq);
   1174     swapl(&stuff->window);
   1175     return ProcShapeSelectInput(client);
   1176 }
   1177 
   1178 static int _X_COLD
   1179 SProcShapeInputSelected(ClientPtr client)
   1180 {
   1181     REQUEST(xShapeInputSelectedReq);
   1182 
   1183     swaps(&stuff->length);
   1184     REQUEST_SIZE_MATCH(xShapeInputSelectedReq);
   1185     swapl(&stuff->window);
   1186     return ProcShapeInputSelected(client);
   1187 }
   1188 
   1189 static int _X_COLD
   1190 SProcShapeGetRectangles(ClientPtr client)
   1191 {
   1192     REQUEST(xShapeGetRectanglesReq);
   1193     swaps(&stuff->length);
   1194     REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
   1195     swapl(&stuff->window);
   1196     return ProcShapeGetRectangles(client);
   1197 }
   1198 
   1199 static int _X_COLD
   1200 SProcShapeDispatch(ClientPtr client)
   1201 {
   1202     REQUEST(xReq);
   1203     switch (stuff->data) {
   1204     case X_ShapeQueryVersion:
   1205         return SProcShapeQueryVersion(client);
   1206     case X_ShapeRectangles:
   1207         return SProcShapeRectangles(client);
   1208     case X_ShapeMask:
   1209         return SProcShapeMask(client);
   1210     case X_ShapeCombine:
   1211         return SProcShapeCombine(client);
   1212     case X_ShapeOffset:
   1213         return SProcShapeOffset(client);
   1214     case X_ShapeQueryExtents:
   1215         return SProcShapeQueryExtents(client);
   1216     case X_ShapeSelectInput:
   1217         return SProcShapeSelectInput(client);
   1218     case X_ShapeInputSelected:
   1219         return SProcShapeInputSelected(client);
   1220     case X_ShapeGetRectangles:
   1221         return SProcShapeGetRectangles(client);
   1222     default:
   1223         return BadRequest;
   1224     }
   1225 }
   1226 
   1227 void
   1228 ShapeExtensionInit(void)
   1229 {
   1230     ExtensionEntry *extEntry;
   1231 
   1232     ClientType = CreateNewResourceType(ShapeFreeClient, "ShapeClient");
   1233     ShapeEventType = CreateNewResourceType(ShapeFreeEvents, "ShapeEvent");
   1234     if (ClientType && ShapeEventType &&
   1235         (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0,
   1236                                  ProcShapeDispatch, SProcShapeDispatch,
   1237                                  NULL, StandardMinorOpcode))) {
   1238         ShapeEventBase = extEntry->eventBase;
   1239         EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent;
   1240     }
   1241 }