region.c revision 7e31ba66
1/*
2 * Copyright © 2003 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26
27#include "xfixesint.h"
28#include "scrnintstr.h"
29#include <picturestr.h>
30
31#include <regionstr.h>
32#include <gcstruct.h>
33#include <window.h>
34
35RESTYPE RegionResType;
36
37static int
38RegionResFree(void *data, XID id)
39{
40    RegionPtr pRegion = (RegionPtr) data;
41
42    RegionDestroy(pRegion);
43    return Success;
44}
45
46RegionPtr
47XFixesRegionCopy(RegionPtr pRegion)
48{
49    RegionPtr pNew = RegionCreate(RegionExtents(pRegion),
50                                  RegionNumRects(pRegion));
51
52    if (!pNew)
53        return 0;
54    if (!RegionCopy(pNew, pRegion)) {
55        RegionDestroy(pNew);
56        return 0;
57    }
58    return pNew;
59}
60
61Bool
62XFixesRegionInit(void)
63{
64    RegionResType = CreateNewResourceType(RegionResFree, "XFixesRegion");
65
66    return RegionResType != 0;
67}
68
69int
70ProcXFixesCreateRegion(ClientPtr client)
71{
72    int things;
73    RegionPtr pRegion;
74
75    REQUEST(xXFixesCreateRegionReq);
76
77    REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
78    LEGAL_NEW_RESOURCE(stuff->region, client);
79
80    things = (client->req_len << 2) - sizeof(xXFixesCreateRegionReq);
81    if (things & 4)
82        return BadLength;
83    things >>= 3;
84
85    pRegion = RegionFromRects(things, (xRectangle *) (stuff + 1), CT_UNSORTED);
86    if (!pRegion)
87        return BadAlloc;
88    if (!AddResource(stuff->region, RegionResType, (void *) pRegion))
89        return BadAlloc;
90
91    return Success;
92}
93
94int _X_COLD
95SProcXFixesCreateRegion(ClientPtr client)
96{
97    REQUEST(xXFixesCreateRegionReq);
98
99    swaps(&stuff->length);
100    REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
101    swapl(&stuff->region);
102    SwapRestS(stuff);
103    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
104}
105
106int
107ProcXFixesCreateRegionFromBitmap(ClientPtr client)
108{
109    RegionPtr pRegion;
110    PixmapPtr pPixmap;
111    int rc;
112
113    REQUEST(xXFixesCreateRegionFromBitmapReq);
114
115    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromBitmapReq);
116    LEGAL_NEW_RESOURCE(stuff->region, client);
117
118    rc = dixLookupResourceByType((void **) &pPixmap, stuff->bitmap, RT_PIXMAP,
119                                 client, DixReadAccess);
120    if (rc != Success) {
121        client->errorValue = stuff->bitmap;
122        return rc;
123    }
124    if (pPixmap->drawable.depth != 1)
125        return BadMatch;
126
127    pRegion = BitmapToRegion(pPixmap->drawable.pScreen, pPixmap);
128
129    if (!pRegion)
130        return BadAlloc;
131
132    if (!AddResource(stuff->region, RegionResType, (void *) pRegion))
133        return BadAlloc;
134
135    return Success;
136}
137
138int _X_COLD
139SProcXFixesCreateRegionFromBitmap(ClientPtr client)
140{
141    REQUEST(xXFixesCreateRegionFromBitmapReq);
142
143    swaps(&stuff->length);
144    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromBitmapReq);
145    swapl(&stuff->region);
146    swapl(&stuff->bitmap);
147    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
148}
149
150int
151ProcXFixesCreateRegionFromWindow(ClientPtr client)
152{
153    RegionPtr pRegion;
154    Bool copy = TRUE;
155    WindowPtr pWin;
156    int rc;
157
158    REQUEST(xXFixesCreateRegionFromWindowReq);
159
160    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromWindowReq);
161    LEGAL_NEW_RESOURCE(stuff->region, client);
162    rc = dixLookupResourceByType((void **) &pWin, stuff->window, RT_WINDOW,
163                                 client, DixGetAttrAccess);
164    if (rc != Success) {
165        client->errorValue = stuff->window;
166        return rc;
167    }
168    switch (stuff->kind) {
169    case WindowRegionBounding:
170        pRegion = wBoundingShape(pWin);
171        if (!pRegion) {
172            pRegion = CreateBoundingShape(pWin);
173            copy = FALSE;
174        }
175        break;
176    case WindowRegionClip:
177        pRegion = wClipShape(pWin);
178        if (!pRegion) {
179            pRegion = CreateClipShape(pWin);
180            copy = FALSE;
181        }
182        break;
183    default:
184        client->errorValue = stuff->kind;
185        return BadValue;
186    }
187    if (copy && pRegion)
188        pRegion = XFixesRegionCopy(pRegion);
189    if (!pRegion)
190        return BadAlloc;
191    if (!AddResource(stuff->region, RegionResType, (void *) pRegion))
192        return BadAlloc;
193
194    return Success;
195}
196
197int _X_COLD
198SProcXFixesCreateRegionFromWindow(ClientPtr client)
199{
200    REQUEST(xXFixesCreateRegionFromWindowReq);
201
202    swaps(&stuff->length);
203    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromWindowReq);
204    swapl(&stuff->region);
205    swapl(&stuff->window);
206    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
207}
208
209int
210ProcXFixesCreateRegionFromGC(ClientPtr client)
211{
212    RegionPtr pRegion, pClip;
213    GCPtr pGC;
214    int rc;
215
216    REQUEST(xXFixesCreateRegionFromGCReq);
217
218    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromGCReq);
219    LEGAL_NEW_RESOURCE(stuff->region, client);
220
221    rc = dixLookupGC(&pGC, stuff->gc, client, DixGetAttrAccess);
222    if (rc != Success)
223        return rc;
224
225    if (pGC->clientClip) {
226        pClip = (RegionPtr) pGC->clientClip;
227        pRegion = XFixesRegionCopy(pClip);
228        if (!pRegion)
229            return BadAlloc;
230    } else {
231        return BadMatch;
232    }
233
234    if (!AddResource(stuff->region, RegionResType, (void *) pRegion))
235        return BadAlloc;
236
237    return Success;
238}
239
240int _X_COLD
241SProcXFixesCreateRegionFromGC(ClientPtr client)
242{
243    REQUEST(xXFixesCreateRegionFromGCReq);
244
245    swaps(&stuff->length);
246    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromGCReq);
247    swapl(&stuff->region);
248    swapl(&stuff->gc);
249    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
250}
251
252int
253ProcXFixesCreateRegionFromPicture(ClientPtr client)
254{
255    RegionPtr pRegion;
256    PicturePtr pPicture;
257
258    REQUEST(xXFixesCreateRegionFromPictureReq);
259
260    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromPictureReq);
261    LEGAL_NEW_RESOURCE(stuff->region, client);
262
263    VERIFY_PICTURE(pPicture, stuff->picture, client, DixGetAttrAccess);
264
265    if (!pPicture->pDrawable)
266        return RenderErrBase + BadPicture;
267
268    if (pPicture->clientClip) {
269        pRegion = XFixesRegionCopy((RegionPtr) pPicture->clientClip);
270        if (!pRegion)
271            return BadAlloc;
272    } else {
273        return BadMatch;
274    }
275
276    if (!AddResource(stuff->region, RegionResType, (void *) pRegion))
277        return BadAlloc;
278
279    return Success;
280}
281
282int _X_COLD
283SProcXFixesCreateRegionFromPicture(ClientPtr client)
284{
285    REQUEST(xXFixesCreateRegionFromPictureReq);
286
287    swaps(&stuff->length);
288    REQUEST_SIZE_MATCH(xXFixesCreateRegionFromPictureReq);
289    swapl(&stuff->region);
290    swapl(&stuff->picture);
291    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
292}
293
294int
295ProcXFixesDestroyRegion(ClientPtr client)
296{
297    REQUEST(xXFixesDestroyRegionReq);
298    RegionPtr pRegion;
299
300    REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
301    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
302    FreeResource(stuff->region, RT_NONE);
303    return Success;
304}
305
306int _X_COLD
307SProcXFixesDestroyRegion(ClientPtr client)
308{
309    REQUEST(xXFixesDestroyRegionReq);
310
311    swaps(&stuff->length);
312    REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
313    swapl(&stuff->region);
314    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
315}
316
317int
318ProcXFixesSetRegion(ClientPtr client)
319{
320    int things;
321    RegionPtr pRegion, pNew;
322
323    REQUEST(xXFixesSetRegionReq);
324
325    REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
326    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
327
328    things = (client->req_len << 2) - sizeof(xXFixesCreateRegionReq);
329    if (things & 4)
330        return BadLength;
331    things >>= 3;
332
333    pNew = RegionFromRects(things, (xRectangle *) (stuff + 1), CT_UNSORTED);
334    if (!pNew)
335        return BadAlloc;
336    if (!RegionCopy(pRegion, pNew)) {
337        RegionDestroy(pNew);
338        return BadAlloc;
339    }
340    RegionDestroy(pNew);
341    return Success;
342}
343
344int _X_COLD
345SProcXFixesSetRegion(ClientPtr client)
346{
347    REQUEST(xXFixesSetRegionReq);
348
349    swaps(&stuff->length);
350    REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
351    swapl(&stuff->region);
352    SwapRestS(stuff);
353    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
354}
355
356int
357ProcXFixesCopyRegion(ClientPtr client)
358{
359    RegionPtr pSource, pDestination;
360
361    REQUEST(xXFixesCopyRegionReq);
362    REQUEST_SIZE_MATCH(xXFixesCopyRegionReq);
363
364    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
365    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
366
367    if (!RegionCopy(pDestination, pSource))
368        return BadAlloc;
369
370    return Success;
371}
372
373int _X_COLD
374SProcXFixesCopyRegion(ClientPtr client)
375{
376    REQUEST(xXFixesCopyRegionReq);
377
378    swaps(&stuff->length);
379    REQUEST_SIZE_MATCH(xXFixesCopyRegionReq);
380    swapl(&stuff->source);
381    swapl(&stuff->destination);
382    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
383}
384
385int
386ProcXFixesCombineRegion(ClientPtr client)
387{
388    RegionPtr pSource1, pSource2, pDestination;
389
390    REQUEST(xXFixesCombineRegionReq);
391
392    REQUEST_SIZE_MATCH(xXFixesCombineRegionReq);
393    VERIFY_REGION(pSource1, stuff->source1, client, DixReadAccess);
394    VERIFY_REGION(pSource2, stuff->source2, client, DixReadAccess);
395    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
396
397    switch (stuff->xfixesReqType) {
398    case X_XFixesUnionRegion:
399        if (!RegionUnion(pDestination, pSource1, pSource2))
400            return BadAlloc;
401        break;
402    case X_XFixesIntersectRegion:
403        if (!RegionIntersect(pDestination, pSource1, pSource2))
404            return BadAlloc;
405        break;
406    case X_XFixesSubtractRegion:
407        if (!RegionSubtract(pDestination, pSource1, pSource2))
408            return BadAlloc;
409        break;
410    }
411
412    return Success;
413}
414
415int _X_COLD
416SProcXFixesCombineRegion(ClientPtr client)
417{
418    REQUEST(xXFixesCombineRegionReq);
419
420    swaps(&stuff->length);
421    REQUEST_SIZE_MATCH(xXFixesCombineRegionReq);
422    swapl(&stuff->source1);
423    swapl(&stuff->source2);
424    swapl(&stuff->destination);
425    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
426}
427
428int
429ProcXFixesInvertRegion(ClientPtr client)
430{
431    RegionPtr pSource, pDestination;
432    BoxRec bounds;
433
434    REQUEST(xXFixesInvertRegionReq);
435
436    REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
437    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
438    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
439
440    /* Compute bounds, limit to 16 bits */
441    bounds.x1 = stuff->x;
442    bounds.y1 = stuff->y;
443    if ((int) stuff->x + (int) stuff->width > MAXSHORT)
444        bounds.x2 = MAXSHORT;
445    else
446        bounds.x2 = stuff->x + stuff->width;
447
448    if ((int) stuff->y + (int) stuff->height > MAXSHORT)
449        bounds.y2 = MAXSHORT;
450    else
451        bounds.y2 = stuff->y + stuff->height;
452
453    if (!RegionInverse(pDestination, pSource, &bounds))
454        return BadAlloc;
455
456    return Success;
457}
458
459int _X_COLD
460SProcXFixesInvertRegion(ClientPtr client)
461{
462    REQUEST(xXFixesInvertRegionReq);
463
464    swaps(&stuff->length);
465    REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
466    swapl(&stuff->source);
467    swaps(&stuff->x);
468    swaps(&stuff->y);
469    swaps(&stuff->width);
470    swaps(&stuff->height);
471    swapl(&stuff->destination);
472    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
473}
474
475int
476ProcXFixesTranslateRegion(ClientPtr client)
477{
478    RegionPtr pRegion;
479
480    REQUEST(xXFixesTranslateRegionReq);
481
482    REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
483    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
484
485    RegionTranslate(pRegion, stuff->dx, stuff->dy);
486    return Success;
487}
488
489int _X_COLD
490SProcXFixesTranslateRegion(ClientPtr client)
491{
492    REQUEST(xXFixesTranslateRegionReq);
493
494    swaps(&stuff->length);
495    REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
496    swapl(&stuff->region);
497    swaps(&stuff->dx);
498    swaps(&stuff->dy);
499    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
500}
501
502int
503ProcXFixesRegionExtents(ClientPtr client)
504{
505    RegionPtr pSource, pDestination;
506
507    REQUEST(xXFixesRegionExtentsReq);
508
509    REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
510    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
511    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
512
513    RegionReset(pDestination, RegionExtents(pSource));
514
515    return Success;
516}
517
518int _X_COLD
519SProcXFixesRegionExtents(ClientPtr client)
520{
521    REQUEST(xXFixesRegionExtentsReq);
522
523    swaps(&stuff->length);
524    REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
525    swapl(&stuff->source);
526    swapl(&stuff->destination);
527    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
528}
529
530int
531ProcXFixesFetchRegion(ClientPtr client)
532{
533    RegionPtr pRegion;
534    xXFixesFetchRegionReply *reply;
535    xRectangle *pRect;
536    BoxPtr pExtent;
537    BoxPtr pBox;
538    int i, nBox;
539
540    REQUEST(xXFixesFetchRegionReq);
541
542    REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
543    VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
544
545    pExtent = RegionExtents(pRegion);
546    pBox = RegionRects(pRegion);
547    nBox = RegionNumRects(pRegion);
548
549    reply = calloc(sizeof(xXFixesFetchRegionReply) + nBox * sizeof(xRectangle),
550                   1);
551    if (!reply)
552        return BadAlloc;
553    reply->type = X_Reply;
554    reply->sequenceNumber = client->sequence;
555    reply->length = nBox << 1;
556    reply->x = pExtent->x1;
557    reply->y = pExtent->y1;
558    reply->width = pExtent->x2 - pExtent->x1;
559    reply->height = pExtent->y2 - pExtent->y1;
560
561    pRect = (xRectangle *) (reply + 1);
562    for (i = 0; i < nBox; i++) {
563        pRect[i].x = pBox[i].x1;
564        pRect[i].y = pBox[i].y1;
565        pRect[i].width = pBox[i].x2 - pBox[i].x1;
566        pRect[i].height = pBox[i].y2 - pBox[i].y1;
567    }
568    if (client->swapped) {
569        swaps(&reply->sequenceNumber);
570        swapl(&reply->length);
571        swaps(&reply->x);
572        swaps(&reply->y);
573        swaps(&reply->width);
574        swaps(&reply->height);
575        SwapShorts((INT16 *) pRect, nBox * 4);
576    }
577    WriteToClient(client, sizeof(xXFixesFetchRegionReply) +
578                         nBox * sizeof(xRectangle), (char *) reply);
579    free(reply);
580    return Success;
581}
582
583int _X_COLD
584SProcXFixesFetchRegion(ClientPtr client)
585{
586    REQUEST(xXFixesFetchRegionReq);
587
588    swaps(&stuff->length);
589    REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
590    swapl(&stuff->region);
591    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
592}
593
594int
595ProcXFixesSetGCClipRegion(ClientPtr client)
596{
597    GCPtr pGC;
598    RegionPtr pRegion;
599    ChangeGCVal vals[2];
600    int rc;
601
602    REQUEST(xXFixesSetGCClipRegionReq);
603    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
604
605    rc = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
606    if (rc != Success)
607        return rc;
608
609    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
610
611    if (pRegion) {
612        pRegion = XFixesRegionCopy(pRegion);
613        if (!pRegion)
614            return BadAlloc;
615    }
616
617    vals[0].val = stuff->xOrigin;
618    vals[1].val = stuff->yOrigin;
619    ChangeGC(NullClient, pGC, GCClipXOrigin | GCClipYOrigin, vals);
620    (*pGC->funcs->ChangeClip) (pGC, pRegion ? CT_REGION : CT_NONE,
621                               (void *) pRegion, 0);
622
623    return Success;
624}
625
626int _X_COLD
627SProcXFixesSetGCClipRegion(ClientPtr client)
628{
629    REQUEST(xXFixesSetGCClipRegionReq);
630
631    swaps(&stuff->length);
632    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
633    swapl(&stuff->gc);
634    swapl(&stuff->region);
635    swaps(&stuff->xOrigin);
636    swaps(&stuff->yOrigin);
637    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
638}
639
640typedef RegionPtr (*CreateDftPtr) (WindowPtr pWin);
641
642int
643ProcXFixesSetWindowShapeRegion(ClientPtr client)
644{
645    WindowPtr pWin;
646    RegionPtr pRegion;
647    RegionPtr *pDestRegion;
648    int rc;
649
650    REQUEST(xXFixesSetWindowShapeRegionReq);
651
652    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
653    rc = dixLookupResourceByType((void **) &pWin, stuff->dest, RT_WINDOW,
654                                 client, DixSetAttrAccess);
655    if (rc != Success) {
656        client->errorValue = stuff->dest;
657        return rc;
658    }
659    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess);
660    switch (stuff->destKind) {
661    case ShapeBounding:
662    case ShapeClip:
663    case ShapeInput:
664        break;
665    default:
666        client->errorValue = stuff->destKind;
667        return BadValue;
668    }
669    if (pRegion) {
670        pRegion = XFixesRegionCopy(pRegion);
671        if (!pRegion)
672            return BadAlloc;
673        if (!pWin->optional)
674            MakeWindowOptional(pWin);
675        switch (stuff->destKind) {
676        default:
677        case ShapeBounding:
678            pDestRegion = &pWin->optional->boundingShape;
679            break;
680        case ShapeClip:
681            pDestRegion = &pWin->optional->clipShape;
682            break;
683        case ShapeInput:
684            pDestRegion = &pWin->optional->inputShape;
685            break;
686        }
687        if (stuff->xOff || stuff->yOff)
688            RegionTranslate(pRegion, stuff->xOff, stuff->yOff);
689    }
690    else {
691        if (pWin->optional) {
692            switch (stuff->destKind) {
693            default:
694            case ShapeBounding:
695                pDestRegion = &pWin->optional->boundingShape;
696                break;
697            case ShapeClip:
698                pDestRegion = &pWin->optional->clipShape;
699                break;
700            case ShapeInput:
701                pDestRegion = &pWin->optional->inputShape;
702                break;
703            }
704        }
705        else
706            pDestRegion = &pRegion;     /* a NULL region pointer */
707    }
708    if (*pDestRegion)
709        RegionDestroy(*pDestRegion);
710    *pDestRegion = pRegion;
711    (*pWin->drawable.pScreen->SetShape) (pWin, stuff->destKind);
712    SendShapeNotify(pWin, stuff->destKind);
713    return Success;
714}
715
716int _X_COLD
717SProcXFixesSetWindowShapeRegion(ClientPtr client)
718{
719    REQUEST(xXFixesSetWindowShapeRegionReq);
720
721    swaps(&stuff->length);
722    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
723    swapl(&stuff->dest);
724    swaps(&stuff->xOff);
725    swaps(&stuff->yOff);
726    swapl(&stuff->region);
727    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
728}
729
730int
731ProcXFixesSetPictureClipRegion(ClientPtr client)
732{
733    PicturePtr pPicture;
734    RegionPtr pRegion;
735
736    REQUEST(xXFixesSetPictureClipRegionReq);
737
738    REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq);
739    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
740    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
741
742    if (!pPicture->pDrawable)
743        return RenderErrBase + BadPicture;
744
745    return SetPictureClipRegion(pPicture, stuff->xOrigin, stuff->yOrigin,
746                                pRegion);
747}
748
749int _X_COLD
750SProcXFixesSetPictureClipRegion(ClientPtr client)
751{
752    REQUEST(xXFixesSetPictureClipRegionReq);
753
754    swaps(&stuff->length);
755    REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq);
756    swapl(&stuff->picture);
757    swapl(&stuff->region);
758    swaps(&stuff->xOrigin);
759    swaps(&stuff->yOrigin);
760    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
761}
762
763int
764ProcXFixesExpandRegion(ClientPtr client)
765{
766    RegionPtr pSource, pDestination;
767
768    REQUEST(xXFixesExpandRegionReq);
769    BoxPtr pTmp;
770    BoxPtr pSrc;
771    int nBoxes;
772    int i;
773
774    REQUEST_SIZE_MATCH(xXFixesExpandRegionReq);
775    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
776    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
777
778    nBoxes = RegionNumRects(pSource);
779    pSrc = RegionRects(pSource);
780    if (nBoxes) {
781        pTmp = xallocarray(nBoxes, sizeof(BoxRec));
782        if (!pTmp)
783            return BadAlloc;
784        for (i = 0; i < nBoxes; i++) {
785            pTmp[i].x1 = pSrc[i].x1 - stuff->left;
786            pTmp[i].x2 = pSrc[i].x2 + stuff->right;
787            pTmp[i].y1 = pSrc[i].y1 - stuff->top;
788            pTmp[i].y2 = pSrc[i].y2 + stuff->bottom;
789        }
790        RegionEmpty(pDestination);
791        for (i = 0; i < nBoxes; i++) {
792            RegionRec r;
793
794            RegionInit(&r, &pTmp[i], 0);
795            RegionUnion(pDestination, pDestination, &r);
796        }
797        free(pTmp);
798    }
799    return Success;
800}
801
802int _X_COLD
803SProcXFixesExpandRegion(ClientPtr client)
804{
805    REQUEST(xXFixesExpandRegionReq);
806
807    swaps(&stuff->length);
808    REQUEST_SIZE_MATCH(xXFixesExpandRegionReq);
809    swapl(&stuff->source);
810    swapl(&stuff->destination);
811    swaps(&stuff->left);
812    swaps(&stuff->right);
813    swaps(&stuff->top);
814    swaps(&stuff->bottom);
815    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
816}
817
818#ifdef PANORAMIX
819#include "panoramiX.h"
820#include "panoramiXsrv.h"
821
822int
823PanoramiXFixesSetGCClipRegion(ClientPtr client)
824{
825    REQUEST(xXFixesSetGCClipRegionReq);
826    int result = Success, j;
827    PanoramiXRes *gc;
828
829    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
830
831    if ((result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
832                                          client, DixWriteAccess))) {
833        client->errorValue = stuff->gc;
834        return result;
835    }
836
837    FOR_NSCREENS_BACKWARD(j) {
838        stuff->gc = gc->info[j].id;
839        result = (*PanoramiXSaveXFixesVector[X_XFixesSetGCClipRegion]) (client);
840        if (result != Success)
841            break;
842    }
843
844    return result;
845}
846
847int
848PanoramiXFixesSetWindowShapeRegion(ClientPtr client)
849{
850    int result = Success, j;
851    PanoramiXRes *win;
852    RegionPtr reg = NULL;
853
854    REQUEST(xXFixesSetWindowShapeRegionReq);
855
856    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
857
858    if ((result = dixLookupResourceByType((void **) &win, stuff->dest,
859                                          XRT_WINDOW, client,
860                                          DixWriteAccess))) {
861        client->errorValue = stuff->dest;
862        return result;
863    }
864
865    if (win->u.win.root)
866        VERIFY_REGION_OR_NONE(reg, stuff->region, client, DixReadAccess);
867
868    FOR_NSCREENS_FORWARD(j) {
869        ScreenPtr screen = screenInfo.screens[j];
870        stuff->dest = win->info[j].id;
871
872        if (reg)
873            RegionTranslate(reg, -screen->x, -screen->y);
874
875        result =
876            (*PanoramiXSaveXFixesVector[X_XFixesSetWindowShapeRegion]) (client);
877
878        if (reg)
879            RegionTranslate(reg, screen->x, screen->y);
880
881        if (result != Success)
882            break;
883    }
884
885    return result;
886}
887
888int
889PanoramiXFixesSetPictureClipRegion(ClientPtr client)
890{
891    REQUEST(xXFixesSetPictureClipRegionReq);
892    int result = Success, j;
893    PanoramiXRes *pict;
894    RegionPtr reg = NULL;
895
896    REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq);
897
898    if ((result = dixLookupResourceByType((void **) &pict, stuff->picture,
899                                          XRT_PICTURE, client,
900                                          DixWriteAccess))) {
901        client->errorValue = stuff->picture;
902        return result;
903    }
904
905    if (pict->u.pict.root)
906        VERIFY_REGION_OR_NONE(reg, stuff->region, client, DixReadAccess);
907
908    FOR_NSCREENS_BACKWARD(j) {
909        ScreenPtr screen = screenInfo.screens[j];
910        stuff->picture = pict->info[j].id;
911
912        if (reg)
913            RegionTranslate(reg, -screen->x, -screen->y);
914
915        result =
916            (*PanoramiXSaveXFixesVector[X_XFixesSetPictureClipRegion]) (client);
917
918        if (reg)
919            RegionTranslate(reg, screen->x, screen->y);
920
921        if (result != Success)
922            break;
923    }
924
925    return result;
926}
927
928#endif
929