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