region.c revision 35c4bbdf
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
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
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
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
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
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
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
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
363    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
364    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
365
366    if (!RegionCopy(pDestination, pSource))
367        return BadAlloc;
368
369    return Success;
370}
371
372int
373SProcXFixesCopyRegion(ClientPtr client)
374{
375    REQUEST(xXFixesCopyRegionReq);
376
377    swaps(&stuff->length);
378    REQUEST_AT_LEAST_SIZE(xXFixesCopyRegionReq);
379    swapl(&stuff->source);
380    swapl(&stuff->destination);
381    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
382}
383
384int
385ProcXFixesCombineRegion(ClientPtr client)
386{
387    RegionPtr pSource1, pSource2, pDestination;
388
389    REQUEST(xXFixesCombineRegionReq);
390
391    REQUEST_SIZE_MATCH(xXFixesCombineRegionReq);
392    VERIFY_REGION(pSource1, stuff->source1, client, DixReadAccess);
393    VERIFY_REGION(pSource2, stuff->source2, client, DixReadAccess);
394    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
395
396    switch (stuff->xfixesReqType) {
397    case X_XFixesUnionRegion:
398        if (!RegionUnion(pDestination, pSource1, pSource2))
399            return BadAlloc;
400        break;
401    case X_XFixesIntersectRegion:
402        if (!RegionIntersect(pDestination, pSource1, pSource2))
403            return BadAlloc;
404        break;
405    case X_XFixesSubtractRegion:
406        if (!RegionSubtract(pDestination, pSource1, pSource2))
407            return BadAlloc;
408        break;
409    }
410
411    return Success;
412}
413
414int
415SProcXFixesCombineRegion(ClientPtr client)
416{
417    REQUEST(xXFixesCombineRegionReq);
418
419    swaps(&stuff->length);
420    REQUEST_SIZE_MATCH(xXFixesCombineRegionReq);
421    swapl(&stuff->source1);
422    swapl(&stuff->source2);
423    swapl(&stuff->destination);
424    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
425}
426
427int
428ProcXFixesInvertRegion(ClientPtr client)
429{
430    RegionPtr pSource, pDestination;
431    BoxRec bounds;
432
433    REQUEST(xXFixesInvertRegionReq);
434
435    REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
436    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
437    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
438
439    /* Compute bounds, limit to 16 bits */
440    bounds.x1 = stuff->x;
441    bounds.y1 = stuff->y;
442    if ((int) stuff->x + (int) stuff->width > MAXSHORT)
443        bounds.x2 = MAXSHORT;
444    else
445        bounds.x2 = stuff->x + stuff->width;
446
447    if ((int) stuff->y + (int) stuff->height > MAXSHORT)
448        bounds.y2 = MAXSHORT;
449    else
450        bounds.y2 = stuff->y + stuff->height;
451
452    if (!RegionInverse(pDestination, pSource, &bounds))
453        return BadAlloc;
454
455    return Success;
456}
457
458int
459SProcXFixesInvertRegion(ClientPtr client)
460{
461    REQUEST(xXFixesInvertRegionReq);
462
463    swaps(&stuff->length);
464    REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
465    swapl(&stuff->source);
466    swaps(&stuff->x);
467    swaps(&stuff->y);
468    swaps(&stuff->width);
469    swaps(&stuff->height);
470    swapl(&stuff->destination);
471    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
472}
473
474int
475ProcXFixesTranslateRegion(ClientPtr client)
476{
477    RegionPtr pRegion;
478
479    REQUEST(xXFixesTranslateRegionReq);
480
481    REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
482    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
483
484    RegionTranslate(pRegion, stuff->dx, stuff->dy);
485    return Success;
486}
487
488int
489SProcXFixesTranslateRegion(ClientPtr client)
490{
491    REQUEST(xXFixesTranslateRegionReq);
492
493    swaps(&stuff->length);
494    REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
495    swapl(&stuff->region);
496    swaps(&stuff->dx);
497    swaps(&stuff->dy);
498    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
499}
500
501int
502ProcXFixesRegionExtents(ClientPtr client)
503{
504    RegionPtr pSource, pDestination;
505
506    REQUEST(xXFixesRegionExtentsReq);
507
508    REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
509    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
510    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
511
512    RegionReset(pDestination, RegionExtents(pSource));
513
514    return Success;
515}
516
517int
518SProcXFixesRegionExtents(ClientPtr client)
519{
520    REQUEST(xXFixesRegionExtentsReq);
521
522    swaps(&stuff->length);
523    REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
524    swapl(&stuff->source);
525    swapl(&stuff->destination);
526    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
527}
528
529int
530ProcXFixesFetchRegion(ClientPtr client)
531{
532    RegionPtr pRegion;
533    xXFixesFetchRegionReply *reply;
534    xRectangle *pRect;
535    BoxPtr pExtent;
536    BoxPtr pBox;
537    int i, nBox;
538
539    REQUEST(xXFixesFetchRegionReq);
540
541    REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
542    VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
543
544    pExtent = RegionExtents(pRegion);
545    pBox = RegionRects(pRegion);
546    nBox = RegionNumRects(pRegion);
547
548    reply = calloc(sizeof(xXFixesFetchRegionReply) + nBox * sizeof(xRectangle),
549                   1);
550    if (!reply)
551        return BadAlloc;
552    reply->type = X_Reply;
553    reply->sequenceNumber = client->sequence;
554    reply->length = nBox << 1;
555    reply->x = pExtent->x1;
556    reply->y = pExtent->y1;
557    reply->width = pExtent->x2 - pExtent->x1;
558    reply->height = pExtent->y2 - pExtent->y1;
559
560    pRect = (xRectangle *) (reply + 1);
561    for (i = 0; i < nBox; i++) {
562        pRect[i].x = pBox[i].x1;
563        pRect[i].y = pBox[i].y1;
564        pRect[i].width = pBox[i].x2 - pBox[i].x1;
565        pRect[i].height = pBox[i].y2 - pBox[i].y1;
566    }
567    if (client->swapped) {
568        swaps(&reply->sequenceNumber);
569        swapl(&reply->length);
570        swaps(&reply->x);
571        swaps(&reply->y);
572        swaps(&reply->width);
573        swaps(&reply->height);
574        SwapShorts((INT16 *) pRect, nBox * 4);
575    }
576    WriteToClient(client, sizeof(xXFixesFetchRegionReply) +
577                         nBox * sizeof(xRectangle), (char *) reply);
578    free(reply);
579    return Success;
580}
581
582int
583SProcXFixesFetchRegion(ClientPtr client)
584{
585    REQUEST(xXFixesFetchRegionReq);
586
587    swaps(&stuff->length);
588    REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
589    swapl(&stuff->region);
590    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
591}
592
593int
594ProcXFixesSetGCClipRegion(ClientPtr client)
595{
596    GCPtr pGC;
597    RegionPtr pRegion;
598    ChangeGCVal vals[2];
599    int rc;
600
601    REQUEST(xXFixesSetGCClipRegionReq);
602    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
603
604    rc = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
605    if (rc != Success)
606        return rc;
607
608    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
609
610    if (pRegion) {
611        pRegion = XFixesRegionCopy(pRegion);
612        if (!pRegion)
613            return BadAlloc;
614    }
615
616    vals[0].val = stuff->xOrigin;
617    vals[1].val = stuff->yOrigin;
618    ChangeGC(NullClient, pGC, GCClipXOrigin | GCClipYOrigin, vals);
619    (*pGC->funcs->ChangeClip) (pGC, pRegion ? CT_REGION : CT_NONE,
620                               (void *) pRegion, 0);
621
622    return Success;
623}
624
625int
626SProcXFixesSetGCClipRegion(ClientPtr client)
627{
628    REQUEST(xXFixesSetGCClipRegionReq);
629
630    swaps(&stuff->length);
631    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
632    swapl(&stuff->gc);
633    swapl(&stuff->region);
634    swaps(&stuff->xOrigin);
635    swaps(&stuff->yOrigin);
636    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
637}
638
639typedef RegionPtr (*CreateDftPtr) (WindowPtr pWin);
640
641int
642ProcXFixesSetWindowShapeRegion(ClientPtr client)
643{
644    WindowPtr pWin;
645    RegionPtr pRegion;
646    RegionPtr *pDestRegion;
647    int rc;
648
649    REQUEST(xXFixesSetWindowShapeRegionReq);
650
651    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
652    rc = dixLookupResourceByType((void **) &pWin, stuff->dest, RT_WINDOW,
653                                 client, DixSetAttrAccess);
654    if (rc != Success) {
655        client->errorValue = stuff->dest;
656        return rc;
657    }
658    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess);
659    switch (stuff->destKind) {
660    case ShapeBounding:
661    case ShapeClip:
662    case ShapeInput:
663        break;
664    default:
665        client->errorValue = stuff->destKind;
666        return BadValue;
667    }
668    if (pRegion) {
669        pRegion = XFixesRegionCopy(pRegion);
670        if (!pRegion)
671            return BadAlloc;
672        if (!pWin->optional)
673            MakeWindowOptional(pWin);
674        switch (stuff->destKind) {
675        default:
676        case ShapeBounding:
677            pDestRegion = &pWin->optional->boundingShape;
678            break;
679        case ShapeClip:
680            pDestRegion = &pWin->optional->clipShape;
681            break;
682        case ShapeInput:
683            pDestRegion = &pWin->optional->inputShape;
684            break;
685        }
686        if (stuff->xOff || stuff->yOff)
687            RegionTranslate(pRegion, stuff->xOff, stuff->yOff);
688    }
689    else {
690        if (pWin->optional) {
691            switch (stuff->destKind) {
692            default:
693            case ShapeBounding:
694                pDestRegion = &pWin->optional->boundingShape;
695                break;
696            case ShapeClip:
697                pDestRegion = &pWin->optional->clipShape;
698                break;
699            case ShapeInput:
700                pDestRegion = &pWin->optional->inputShape;
701                break;
702            }
703        }
704        else
705            pDestRegion = &pRegion;     /* a NULL region pointer */
706    }
707    if (*pDestRegion)
708        RegionDestroy(*pDestRegion);
709    *pDestRegion = pRegion;
710    (*pWin->drawable.pScreen->SetShape) (pWin, stuff->destKind);
711    SendShapeNotify(pWin, stuff->destKind);
712    return Success;
713}
714
715int
716SProcXFixesSetWindowShapeRegion(ClientPtr client)
717{
718    REQUEST(xXFixesSetWindowShapeRegionReq);
719
720    swaps(&stuff->length);
721    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
722    swapl(&stuff->dest);
723    swaps(&stuff->xOff);
724    swaps(&stuff->yOff);
725    swapl(&stuff->region);
726    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
727}
728
729int
730ProcXFixesSetPictureClipRegion(ClientPtr client)
731{
732    PicturePtr pPicture;
733    RegionPtr pRegion;
734
735    REQUEST(xXFixesSetPictureClipRegionReq);
736
737    REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq);
738    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
739    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
740
741    if (!pPicture->pDrawable)
742        return RenderErrBase + BadPicture;
743
744    return SetPictureClipRegion(pPicture, stuff->xOrigin, stuff->yOrigin,
745                                pRegion);
746}
747
748int
749SProcXFixesSetPictureClipRegion(ClientPtr client)
750{
751    REQUEST(xXFixesSetPictureClipRegionReq);
752
753    swaps(&stuff->length);
754    REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq);
755    swapl(&stuff->picture);
756    swapl(&stuff->region);
757    swaps(&stuff->xOrigin);
758    swaps(&stuff->yOrigin);
759    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
760}
761
762int
763ProcXFixesExpandRegion(ClientPtr client)
764{
765    RegionPtr pSource, pDestination;
766
767    REQUEST(xXFixesExpandRegionReq);
768    BoxPtr pTmp;
769    BoxPtr pSrc;
770    int nBoxes;
771    int i;
772
773    REQUEST_SIZE_MATCH(xXFixesExpandRegionReq);
774    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
775    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
776
777    nBoxes = RegionNumRects(pSource);
778    pSrc = RegionRects(pSource);
779    if (nBoxes) {
780        pTmp = xallocarray(nBoxes, sizeof(BoxRec));
781        if (!pTmp)
782            return BadAlloc;
783        for (i = 0; i < nBoxes; i++) {
784            pTmp[i].x1 = pSrc[i].x1 - stuff->left;
785            pTmp[i].x2 = pSrc[i].x2 + stuff->right;
786            pTmp[i].y1 = pSrc[i].y1 - stuff->top;
787            pTmp[i].y2 = pSrc[i].y2 + stuff->bottom;
788        }
789        RegionEmpty(pDestination);
790        for (i = 0; i < nBoxes; i++) {
791            RegionRec r;
792
793            RegionInit(&r, &pTmp[i], 0);
794            RegionUnion(pDestination, pDestination, &r);
795        }
796        free(pTmp);
797    }
798    return Success;
799}
800
801int
802SProcXFixesExpandRegion(ClientPtr client)
803{
804    REQUEST(xXFixesExpandRegionReq);
805
806    swaps(&stuff->length);
807    REQUEST_SIZE_MATCH(xXFixesExpandRegionReq);
808    swapl(&stuff->source);
809    swapl(&stuff->destination);
810    swaps(&stuff->left);
811    swaps(&stuff->right);
812    swaps(&stuff->top);
813    swaps(&stuff->bottom);
814    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
815}
816
817#ifdef PANORAMIX
818#include "panoramiX.h"
819#include "panoramiXsrv.h"
820
821int
822PanoramiXFixesSetGCClipRegion(ClientPtr client)
823{
824    REQUEST(xXFixesSetGCClipRegionReq);
825    int result = Success, j;
826    PanoramiXRes *gc;
827
828    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
829
830    if ((result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC,
831                                          client, DixWriteAccess))) {
832        client->errorValue = stuff->gc;
833        return result;
834    }
835
836    FOR_NSCREENS_BACKWARD(j) {
837        stuff->gc = gc->info[j].id;
838        result = (*PanoramiXSaveXFixesVector[X_XFixesSetGCClipRegion]) (client);
839        if (result != Success)
840            break;
841    }
842
843    return result;
844}
845
846int
847PanoramiXFixesSetWindowShapeRegion(ClientPtr client)
848{
849    int result = Success, j;
850    PanoramiXRes *win;
851    RegionPtr reg = NULL;
852
853    REQUEST(xXFixesSetWindowShapeRegionReq);
854
855    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
856
857    if ((result = dixLookupResourceByType((void **) &win, stuff->dest,
858                                          XRT_WINDOW, client,
859                                          DixWriteAccess))) {
860        client->errorValue = stuff->dest;
861        return result;
862    }
863
864    if (win->u.win.root)
865        VERIFY_REGION_OR_NONE(reg, stuff->region, client, DixReadAccess);
866
867    FOR_NSCREENS_FORWARD(j) {
868        ScreenPtr screen = screenInfo.screens[j];
869        stuff->dest = win->info[j].id;
870
871        if (reg)
872            RegionTranslate(reg, -screen->x, -screen->y);
873
874        result =
875            (*PanoramiXSaveXFixesVector[X_XFixesSetWindowShapeRegion]) (client);
876
877        if (reg)
878            RegionTranslate(reg, screen->x, screen->y);
879
880        if (result != Success)
881            break;
882    }
883
884    return result;
885}
886
887int
888PanoramiXFixesSetPictureClipRegion(ClientPtr client)
889{
890    REQUEST(xXFixesSetPictureClipRegionReq);
891    int result = Success, j;
892    PanoramiXRes *pict;
893    RegionPtr reg = NULL;
894
895    REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq);
896
897    if ((result = dixLookupResourceByType((void **) &pict, stuff->picture,
898                                          XRT_PICTURE, client,
899                                          DixWriteAccess))) {
900        client->errorValue = stuff->picture;
901        return result;
902    }
903
904    if (pict->u.pict.root)
905        VERIFY_REGION_OR_NONE(reg, stuff->region, client, DixReadAccess);
906
907    FOR_NSCREENS_BACKWARD(j) {
908        ScreenPtr screen = screenInfo.screens[j];
909        stuff->picture = pict->info[j].id;
910
911        if (reg)
912            RegionTranslate(reg, -screen->x, -screen->y);
913
914        result =
915            (*PanoramiXSaveXFixesVector[X_XFixesSetPictureClipRegion]) (client);
916
917        if (reg)
918            RegionTranslate(reg, screen->x, screen->y);
919
920        if (result != Success)
921            break;
922    }
923
924    return result;
925}
926
927#endif
928