region.c revision 05b261ec
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#ifdef RENDER
30#include <picturestr.h>
31extern int RenderErrBase;
32#endif
33#include <regionstr.h>
34#include <gcstruct.h>
35#include <window.h>
36
37RESTYPE	    RegionResType;
38
39static int
40RegionResFree (pointer data, XID id)
41{
42    RegionPtr    pRegion = (RegionPtr) data;
43
44    REGION_DESTROY (0, pRegion);
45    return Success;
46}
47
48RegionPtr
49XFixesRegionCopy (RegionPtr pRegion)
50{
51    RegionPtr   pNew = REGION_CREATE (0, REGION_EXTENTS(0, pRegion),
52				      REGION_NUM_RECTS(pRegion));
53    if (!pNew)
54	return 0;
55    if (!REGION_COPY (0, pNew, pRegion))
56    {
57	REGION_DESTROY (0, pNew);
58	return 0;
59    }
60    return pNew;
61}
62
63Bool
64XFixesRegionInit (void)
65{
66    RegionResType = CreateNewResourceType(RegionResFree);
67    return TRUE;
68}
69
70int
71ProcXFixesCreateRegion (ClientPtr client)
72{
73    int		things;
74    RegionPtr	pRegion;
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 = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
86    if (!pRegion)
87	return BadAlloc;
88    if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
89	return BadAlloc;
90
91    return(client->noClientException);
92}
93
94int
95SProcXFixesCreateRegion (ClientPtr client)
96{
97    register int n;
98    REQUEST(xXFixesCreateRegionReq);
99
100    swaps(&stuff->length, n);
101    REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
102    swapl(&stuff->region, n);
103    SwapRestS(stuff);
104    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
105}
106
107int
108ProcXFixesCreateRegionFromBitmap (ClientPtr client)
109{
110    RegionPtr	pRegion;
111    PixmapPtr	pPixmap;
112    REQUEST (xXFixesCreateRegionFromBitmapReq);
113
114    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
115    LEGAL_NEW_RESOURCE (stuff->region, client);
116
117    pPixmap = (PixmapPtr) SecurityLookupIDByType (client, stuff->bitmap,
118						  RT_PIXMAP,
119						  DixReadAccess);
120    if (!pPixmap)
121    {
122	client->errorValue = stuff->bitmap;
123	return BadPixmap;
124    }
125    if (pPixmap->drawable.depth != 1)
126	return BadMatch;
127
128    pRegion = BITMAP_TO_REGION(pPixmap->drawable.pScreen, pPixmap);
129
130    if (!pRegion)
131	return BadAlloc;
132
133    if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
134	return BadAlloc;
135
136    return(client->noClientException);
137}
138
139int
140SProcXFixesCreateRegionFromBitmap (ClientPtr client)
141{
142    int n;
143    REQUEST (xXFixesCreateRegionFromBitmapReq);
144
145    swaps(&stuff->length, n);
146    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
147    swapl(&stuff->region, n);
148    swapl(&stuff->bitmap, n);
149    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
150}
151
152int
153ProcXFixesCreateRegionFromWindow (ClientPtr client)
154{
155    RegionPtr	pRegion;
156    Bool	copy = TRUE;
157    WindowPtr	pWin;
158    REQUEST (xXFixesCreateRegionFromWindowReq);
159
160    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
161    LEGAL_NEW_RESOURCE (stuff->region, client);
162    pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
163    if (!pWin)
164    {
165	client->errorValue = stuff->window;
166	return BadWindow;
167    }
168    switch (stuff->kind) {
169    case WindowRegionBounding:
170#ifdef SHAPE
171	pRegion = wBoundingShape(pWin);
172	if (!pRegion)
173#endif
174	{
175	    pRegion = CreateBoundingShape (pWin);
176	    copy = FALSE;
177	}
178	break;
179    case WindowRegionClip:
180#ifdef SHAPE
181	pRegion = wClipShape(pWin);
182	if (!pRegion)
183#endif
184	{
185	    pRegion = CreateClipShape (pWin);
186	    copy = FALSE;
187	}
188	break;
189    default:
190	client->errorValue = stuff->kind;
191	return BadValue;
192    }
193    if (copy && pRegion)
194	pRegion = XFixesRegionCopy (pRegion);
195    if (!pRegion)
196	return BadAlloc;
197    if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
198	return BadAlloc;
199
200    return(client->noClientException);
201}
202
203int
204SProcXFixesCreateRegionFromWindow (ClientPtr client)
205{
206    int n;
207    REQUEST (xXFixesCreateRegionFromWindowReq);
208
209    swaps(&stuff->length, n);
210    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
211    swapl(&stuff->region, n);
212    swapl(&stuff->window, n);
213    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
214}
215
216int
217ProcXFixesCreateRegionFromGC (ClientPtr client)
218{
219    RegionPtr	pRegion, pClip;
220    GCPtr	pGC;
221    int 	rc;
222    REQUEST (xXFixesCreateRegionFromGCReq);
223
224    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
225    LEGAL_NEW_RESOURCE (stuff->region, client);
226
227    rc = dixLookupGC(&pGC, stuff->gc, client, DixReadAccess);
228    if (rc != Success)
229	return rc;
230
231    switch (pGC->clientClipType) {
232    case CT_PIXMAP:
233	pRegion = BITMAP_TO_REGION(pGC->pScreen, (PixmapPtr) pGC->clientClip);
234	if (!pRegion)
235	    return BadAlloc;
236	break;
237    case CT_REGION:
238	pClip = (RegionPtr) pGC->clientClip;
239	pRegion = XFixesRegionCopy (pClip);
240	if (!pRegion)
241	    return BadAlloc;
242	break;
243    default:
244	return BadImplementation;   /* assume sane server bits */
245    }
246
247    if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
248	return BadAlloc;
249
250    return(client->noClientException);
251}
252
253int
254SProcXFixesCreateRegionFromGC (ClientPtr client)
255{
256    int n;
257    REQUEST (xXFixesCreateRegionFromGCReq);
258
259    swaps(&stuff->length, n);
260    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
261    swapl(&stuff->region, n);
262    swapl(&stuff->gc, n);
263    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
264}
265
266int
267ProcXFixesCreateRegionFromPicture (ClientPtr client)
268{
269#ifdef RENDER
270    RegionPtr	pRegion;
271    PicturePtr	pPicture;
272    REQUEST (xXFixesCreateRegionFromPictureReq);
273
274    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
275    LEGAL_NEW_RESOURCE (stuff->region, client);
276
277    VERIFY_PICTURE(pPicture, stuff->picture, client, DixReadAccess,
278		   RenderErrBase + BadPicture);
279
280    switch (pPicture->clientClipType) {
281    case CT_PIXMAP:
282	pRegion = BITMAP_TO_REGION(pPicture->pDrawable->pScreen,
283				   (PixmapPtr) pPicture->clientClip);
284	if (!pRegion)
285	    return BadAlloc;
286	break;
287    case CT_REGION:
288	pRegion = XFixesRegionCopy ((RegionPtr) pPicture->clientClip);
289	if (!pRegion)
290	    return BadAlloc;
291	break;
292    default:
293	return BadImplementation;   /* assume sane server bits */
294    }
295
296    if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
297	return BadAlloc;
298
299    return(client->noClientException);
300#else
301    return BadRequest;
302#endif
303}
304
305int
306SProcXFixesCreateRegionFromPicture (ClientPtr client)
307{
308    int n;
309    REQUEST (xXFixesCreateRegionFromPictureReq);
310
311    swaps(&stuff->length, n);
312    REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
313    swapl(&stuff->region, n);
314    swapl(&stuff->picture, n);
315    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
316}
317
318int
319ProcXFixesDestroyRegion (ClientPtr client)
320{
321    REQUEST (xXFixesDestroyRegionReq);
322    RegionPtr	pRegion;
323
324    REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
325    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
326    FreeResource (stuff->region, RT_NONE);
327    return(client->noClientException);
328}
329
330int
331SProcXFixesDestroyRegion (ClientPtr client)
332{
333    int n;
334    REQUEST (xXFixesDestroyRegionReq);
335
336    swaps (&stuff->length, n);
337    REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
338    swapl (&stuff->region, n);
339    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
340}
341
342int
343ProcXFixesSetRegion (ClientPtr client)
344{
345    int		things;
346    RegionPtr	pRegion, pNew;
347    REQUEST (xXFixesSetRegionReq);
348
349    REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
350    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
351
352    things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq);
353    if (things & 4)
354	return BadLength;
355    things >>= 3;
356
357    pNew = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
358    if (!pNew)
359	return BadAlloc;
360    if (!REGION_COPY (0, pRegion, pNew))
361    {
362	REGION_DESTROY (0, pNew);
363	return BadAlloc;
364    }
365    REGION_DESTROY (0, pNew);
366    return(client->noClientException);
367}
368
369int
370SProcXFixesSetRegion (ClientPtr client)
371{
372    int n;
373    REQUEST (xXFixesSetRegionReq);
374
375    swaps (&stuff->length, n);
376    REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
377    swapl (&stuff->region, n);
378    SwapRestS(stuff);
379    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
380}
381
382int
383ProcXFixesCopyRegion (ClientPtr client)
384{
385    RegionPtr	pSource, pDestination;
386    REQUEST (xXFixesCopyRegionReq);
387
388    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
389    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
390
391    if (!REGION_COPY(pScreen, pDestination, pSource))
392	return BadAlloc;
393
394    return(client->noClientException);
395}
396
397int
398SProcXFixesCopyRegion (ClientPtr client)
399{
400    int n;
401    REQUEST (xXFixesCopyRegionReq);
402
403    swaps (&stuff->length, n);
404    REQUEST_AT_LEAST_SIZE(xXFixesCopyRegionReq);
405    swapl (&stuff->source, n);
406    swapl (&stuff->destination, n);
407    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
408}
409
410int
411ProcXFixesCombineRegion (ClientPtr client)
412{
413    RegionPtr	pSource1, pSource2, pDestination;
414    int		ret = Success;
415    REQUEST (xXFixesCombineRegionReq);
416
417    REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
418    VERIFY_REGION(pSource1, stuff->source1, client, DixReadAccess);
419    VERIFY_REGION(pSource2, stuff->source2, client, DixReadAccess);
420    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
421
422    switch (stuff->xfixesReqType) {
423    case X_XFixesUnionRegion:
424	if (!REGION_UNION (0, pDestination, pSource1, pSource2))
425	    ret = BadAlloc;
426	break;
427    case X_XFixesIntersectRegion:
428	if (!REGION_INTERSECT (0, pDestination, pSource1, pSource2))
429	    ret = BadAlloc;
430	break;
431    case X_XFixesSubtractRegion:
432	if (!REGION_SUBTRACT (0, pDestination, pSource1, pSource2))
433	    ret = BadAlloc;
434	break;
435    }
436
437    if (ret == Success)
438	ret = client->noClientException;
439    return ret;
440}
441
442int
443SProcXFixesCombineRegion (ClientPtr client)
444{
445    int n;
446    REQUEST (xXFixesCombineRegionReq);
447
448    swaps (&stuff->length, n);
449    REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
450    swapl (&stuff->source1, n);
451    swapl (&stuff->source2, n);
452    swapl (&stuff->destination, n);
453    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
454}
455
456int
457ProcXFixesInvertRegion (ClientPtr client)
458{
459    RegionPtr	pSource, pDestination;
460    BoxRec	bounds;
461    int		ret = Success;
462    REQUEST(xXFixesInvertRegionReq);
463
464    REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
465    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
466    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
467
468    /* Compute bounds, limit to 16 bits */
469    bounds.x1 = stuff->x;
470    bounds.y1 = stuff->y;
471    if ((int) stuff->x + (int) stuff->width > MAXSHORT)
472	bounds.x2 = MAXSHORT;
473    else
474	bounds.x2 = stuff->x + stuff->width;
475
476    if ((int) stuff->y + (int) stuff->height > MAXSHORT)
477	bounds.y2 = MAXSHORT;
478    else
479	bounds.y2 = stuff->y + stuff->height;
480
481    if (!REGION_INVERSE(0, pDestination, pSource, &bounds))
482	ret = BadAlloc;
483
484    if (ret == Success)
485	ret = client->noClientException;
486    return ret;
487}
488
489int
490SProcXFixesInvertRegion (ClientPtr client)
491{
492    int n;
493    REQUEST(xXFixesInvertRegionReq);
494
495    swaps (&stuff->length, n);
496    REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
497    swapl (&stuff->source, n);
498    swaps (&stuff->x, n);
499    swaps (&stuff->y, n);
500    swaps (&stuff->width, n);
501    swaps (&stuff->height, n);
502    swapl (&stuff->destination, n);
503    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
504}
505
506int
507ProcXFixesTranslateRegion (ClientPtr client)
508{
509    RegionPtr	pRegion;
510    REQUEST(xXFixesTranslateRegionReq);
511
512    REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
513    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
514
515    REGION_TRANSLATE(pScreen, pRegion, stuff->dx, stuff->dy);
516    return (client->noClientException);
517}
518
519int
520SProcXFixesTranslateRegion (ClientPtr client)
521{
522    int n;
523    REQUEST(xXFixesTranslateRegionReq);
524
525    swaps (&stuff->length, n);
526    REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
527    swapl (&stuff->region, n);
528    swaps (&stuff->dx, n);
529    swaps (&stuff->dy, n);
530    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
531}
532
533int
534ProcXFixesRegionExtents (ClientPtr client)
535{
536    RegionPtr	pSource, pDestination;
537    REQUEST(xXFixesRegionExtentsReq);
538
539    REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
540    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
541    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
542
543    REGION_RESET (0, pDestination, REGION_EXTENTS (0, pSource));
544
545    return (client->noClientException);
546}
547
548int
549SProcXFixesRegionExtents (ClientPtr client)
550{
551    int n;
552    REQUEST(xXFixesRegionExtentsReq);
553
554    swaps (&stuff->length, n);
555    REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
556    swapl (&stuff->source, n);
557    swapl (&stuff->destination, n);
558    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
559}
560
561int
562ProcXFixesFetchRegion (ClientPtr client)
563{
564    RegionPtr		    pRegion;
565    xXFixesFetchRegionReply *reply;
566    xRectangle		    *pRect;
567    BoxPtr		    pExtent;
568    BoxPtr		    pBox;
569    int			    i, nBox;
570    REQUEST(xXFixesFetchRegionReq);
571
572    REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
573    VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
574
575    pExtent = REGION_EXTENTS (0, pRegion);
576    pBox = REGION_RECTS (pRegion);
577    nBox = REGION_NUM_RECTS (pRegion);
578
579    reply = xalloc (sizeof (xXFixesFetchRegionReply) +
580		    nBox * sizeof (xRectangle));
581    if (!reply)
582	return BadAlloc;
583    reply->type = X_Reply;
584    reply->sequenceNumber = client->sequence;
585    reply->length = nBox << 1;
586    reply->x = pExtent->x1;
587    reply->y = pExtent->y1;
588    reply->width = pExtent->x2 - pExtent->x1;
589    reply->height = pExtent->y2 - pExtent->y1;
590
591    pRect = (xRectangle *) (reply + 1);
592    for (i = 0; i < nBox; i++)
593    {
594	pRect[i].x = pBox[i].x1;
595	pRect[i].y = pBox[i].y1;
596	pRect[i].width = pBox[i].x2 - pBox[i].x1;
597	pRect[i].height = pBox[i].y2 - pBox[i].y1;
598    }
599    if (client->swapped)
600    {
601	int n;
602	swaps (&reply->sequenceNumber, n);
603	swapl (&reply->length, n);
604	swaps (&reply->x, n);
605	swaps (&reply->y, n);
606	swaps (&reply->width, n);
607	swaps (&reply->height, n);
608	SwapShorts ((INT16 *) pRect, nBox * 4);
609    }
610    (void) WriteToClient(client, sizeof (xXFixesFetchRegionReply) +
611			 nBox * sizeof (xRectangle), (char *) reply);
612    xfree (reply);
613    return (client->noClientException);
614}
615
616int
617SProcXFixesFetchRegion (ClientPtr client)
618{
619    int n;
620    REQUEST(xXFixesFetchRegionReq);
621
622    swaps (&stuff->length, n);
623    REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
624    swapl (&stuff->region, n);
625    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
626}
627
628int
629ProcXFixesSetGCClipRegion (ClientPtr client)
630{
631    GCPtr	pGC;
632    RegionPtr	pRegion;
633    XID		vals[2];
634    int		rc;
635    REQUEST(xXFixesSetGCClipRegionReq);
636    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
637
638    rc = dixLookupGC(&pGC, stuff->gc, client, DixWriteAccess);
639    if (rc != Success)
640	return rc;
641
642    VERIFY_REGION_OR_NONE (pRegion, stuff->region, client, DixReadAccess);
643
644    if (pRegion)
645    {
646	pRegion = XFixesRegionCopy (pRegion);
647	if (!pRegion)
648	    return BadAlloc;
649    }
650
651    vals[0] = stuff->xOrigin;
652    vals[1] = stuff->yOrigin;
653    DoChangeGC (pGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
654    (*pGC->funcs->ChangeClip)(pGC, pRegion ? CT_REGION : CT_NONE, (pointer)pRegion, 0);
655
656    return (client->noClientException);
657}
658
659int
660SProcXFixesSetGCClipRegion (ClientPtr client)
661{
662    int n;
663    REQUEST(xXFixesSetGCClipRegionReq);
664
665    swaps (&stuff->length, n);
666    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
667    swapl (&stuff->gc, n);
668    swapl (&stuff->region, n);
669    swaps (&stuff->xOrigin, n);
670    swaps (&stuff->yOrigin, n);
671    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
672}
673
674typedef	RegionPtr (*CreateDftPtr)(WindowPtr pWin);
675
676int
677ProcXFixesSetWindowShapeRegion (ClientPtr client)
678{
679#ifdef SHAPE
680    WindowPtr	    pWin;
681    ScreenPtr	    pScreen;
682    RegionPtr	    pRegion;
683    RegionPtr	    *pDestRegion;
684    REQUEST(xXFixesSetWindowShapeRegionReq);
685
686    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
687    pWin = (WindowPtr) LookupIDByType (stuff->dest, RT_WINDOW);
688    if (!pWin)
689    {
690	client->errorValue = stuff->dest;
691	return BadWindow;
692    }
693    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess);
694    pScreen = pWin->drawable.pScreen;
695    switch (stuff->destKind) {
696    case ShapeBounding:
697    case ShapeClip:
698    case ShapeInput:
699	break;
700    default:
701	client->errorValue = stuff->destKind;
702	return BadValue;
703    }
704    if (pRegion)
705    {
706	pRegion = XFixesRegionCopy (pRegion);
707	if (!pRegion)
708	    return BadAlloc;
709	if (!pWin->optional)
710	    MakeWindowOptional (pWin);
711	switch (stuff->destKind) {
712	default:
713	case ShapeBounding:
714	    pDestRegion = &pWin->optional->boundingShape;
715	    break;
716	case ShapeClip:
717	    pDestRegion = &pWin->optional->clipShape;
718	    break;
719	case ShapeInput:
720	    pDestRegion = &pWin->optional->inputShape;
721	    break;
722	}
723	if (stuff->xOff || stuff->yOff)
724	    REGION_TRANSLATE (0, pRegion, stuff->xOff, stuff->yOff);
725    }
726    else
727    {
728	if (pWin->optional)
729	{
730	    switch (stuff->destKind) {
731	    default:
732	    case ShapeBounding:
733		pDestRegion = &pWin->optional->boundingShape;
734		break;
735	    case ShapeClip:
736		pDestRegion = &pWin->optional->clipShape;
737		break;
738	    case ShapeInput:
739		pDestRegion = &pWin->optional->inputShape;
740		break;
741	    }
742	}
743	else
744	    pDestRegion = &pRegion; /* a NULL region pointer */
745    }
746    if (*pDestRegion)
747	REGION_DESTROY(pScreen, *pDestRegion);
748    *pDestRegion = pRegion;
749    (*pScreen->SetShape) (pWin);
750    SendShapeNotify (pWin, stuff->destKind);
751    return (client->noClientException);
752#else
753    return BadRequest;
754#endif
755}
756
757int
758SProcXFixesSetWindowShapeRegion (ClientPtr client)
759{
760    int n;
761    REQUEST(xXFixesSetWindowShapeRegionReq);
762
763    swaps (&stuff->length, n);
764    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
765    swapl (&stuff->dest, n);
766    swaps (&stuff->xOff, n);
767    swaps (&stuff->yOff, n);
768    swapl (&stuff->region, n);
769    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
770}
771
772int
773ProcXFixesSetPictureClipRegion (ClientPtr client)
774{
775#ifdef RENDER
776    PicturePtr		pPicture;
777    RegionPtr		pRegion;
778    ScreenPtr		pScreen;
779    PictureScreenPtr	ps;
780    REQUEST(xXFixesSetPictureClipRegionReq);
781
782    REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
783    VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess,
784		   RenderErrBase + BadPicture);
785    pScreen = pPicture->pDrawable->pScreen;
786    ps = GetPictureScreen (pScreen);
787    VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
788
789    return SetPictureClipRegion (pPicture, stuff->xOrigin, stuff->yOrigin,
790				 pRegion);
791#else
792    return BadRequest;
793#endif
794}
795
796int
797SProcXFixesSetPictureClipRegion (ClientPtr client)
798{
799    int n;
800    REQUEST(xXFixesSetPictureClipRegionReq);
801
802    swaps (&stuff->length, n);
803    REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
804    swapl (&stuff->picture, n);
805    swapl (&stuff->region, n);
806    swaps (&stuff->xOrigin, n);
807    swaps (&stuff->yOrigin, n);
808    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
809}
810
811int
812ProcXFixesExpandRegion (ClientPtr client)
813{
814    RegionPtr	pSource, pDestination;
815    int		ret = Success;
816    REQUEST (xXFixesExpandRegionReq);
817    BoxPtr	pTmp;
818    BoxPtr	pSrc;
819    int		nBoxes;
820    int		i;
821
822    REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
823    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
824    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
825
826    nBoxes = REGION_NUM_RECTS(pSource);
827    pSrc = REGION_RECTS(pSource);
828    if (nBoxes)
829    {
830	pTmp = xalloc (nBoxes * sizeof (BoxRec));
831	if (!pTmp)
832	    return BadAlloc;
833	for (i = 0; i < nBoxes; i++)
834	{
835	    pTmp[i].x1 = pSrc[i].x1 - stuff->left;
836	    pTmp[i].x2 = pSrc[i].x2 + stuff->right;
837	    pTmp[i].y1 = pSrc[i].y1 - stuff->top;
838	    pTmp[i].y2 = pSrc[i].y2 + stuff->bottom;
839	}
840	REGION_EMPTY (pScreen, pDestination);
841	for (i = 0; i < nBoxes; i++)
842	{
843	    RegionRec	r;
844	    REGION_INIT (pScreen, &r, &pTmp[i], 0);
845	    REGION_UNION (pScreen, pDestination, pDestination, &r);
846	}
847	xfree(pTmp);
848    }
849    if (ret == Success)
850	ret = client->noClientException;
851    return ret;
852}
853
854int
855SProcXFixesExpandRegion (ClientPtr client)
856{
857    int n;
858    REQUEST (xXFixesExpandRegionReq);
859
860    swaps (&stuff->length, n);
861    REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
862    swapl (&stuff->source, n);
863    swapl (&stuff->destination, n);
864    swaps (&stuff->left, n);
865    swaps (&stuff->right, n);
866    swaps (&stuff->top, n);
867    swaps (&stuff->bottom, n);
868    return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
869}
870
871