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