1706f2543Smrg/************************************************************
2706f2543Smrg
3706f2543SmrgCopyright 1989, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included in
12706f2543Smrgall copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20706f2543Smrg
21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
23706f2543Smrgin this Software without prior written authorization from The Open Group.
24706f2543Smrg
25706f2543Smrg********************************************************/
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
28706f2543Smrg#include <dix-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include <stdlib.h>
32706f2543Smrg
33706f2543Smrg#include <X11/X.h>
34706f2543Smrg#include <X11/Xproto.h>
35706f2543Smrg#include "misc.h"
36706f2543Smrg#include "os.h"
37706f2543Smrg#include "windowstr.h"
38706f2543Smrg#include "scrnintstr.h"
39706f2543Smrg#include "pixmapstr.h"
40706f2543Smrg#include "extnsionst.h"
41706f2543Smrg#include "dixstruct.h"
42706f2543Smrg#include "resource.h"
43706f2543Smrg#include "opaque.h"
44706f2543Smrg#include <X11/extensions/shapeproto.h>
45706f2543Smrg#include "regionstr.h"
46706f2543Smrg#include "gcstruct.h"
47706f2543Smrg#include "modinit.h"
48706f2543Smrg#include "protocol-versions.h"
49706f2543Smrg
50706f2543Smrgtypedef	RegionPtr (*CreateDftPtr)(
51706f2543Smrg	WindowPtr /* pWin */
52706f2543Smrg	);
53706f2543Smrg
54706f2543Smrgstatic int ShapeFreeClient(
55706f2543Smrg	pointer /* data */,
56706f2543Smrg	XID /* id */
57706f2543Smrg	);
58706f2543Smrgstatic int ShapeFreeEvents(
59706f2543Smrg	pointer /* data */,
60706f2543Smrg	XID /* id */
61706f2543Smrg	);
62706f2543Smrgstatic void SShapeNotifyEvent(
63706f2543Smrg	xShapeNotifyEvent * /* from */,
64706f2543Smrg	xShapeNotifyEvent * /* to */
65706f2543Smrg	);
66706f2543Smrg
67706f2543Smrg/* SendShapeNotify, CreateBoundingShape and CreateClipShape are used
68706f2543Smrg * externally by the Xfixes extension and are now defined in window.h
69706f2543Smrg */
70706f2543Smrg
71706f2543Smrg
72706f2543Smrg#ifdef PANORAMIX
73706f2543Smrg#include "panoramiX.h"
74706f2543Smrg#include "panoramiXsrv.h"
75706f2543Smrg#endif
76706f2543Smrg
77706f2543Smrgstatic int ShapeEventBase = 0;
78706f2543Smrgstatic RESTYPE ClientType, ShapeEventType; /* resource types for event masks */
79706f2543Smrg
80706f2543Smrg/*
81706f2543Smrg * each window has a list of clients requesting
82706f2543Smrg * ShapeNotify events.  Each client has a resource
83706f2543Smrg * for each window it selects ShapeNotify input for,
84706f2543Smrg * this resource is used to delete the ShapeNotifyRec
85706f2543Smrg * entry from the per-window queue.
86706f2543Smrg */
87706f2543Smrg
88706f2543Smrgtypedef struct _ShapeEvent *ShapeEventPtr;
89706f2543Smrg
90706f2543Smrgtypedef struct _ShapeEvent {
91706f2543Smrg    ShapeEventPtr   next;
92706f2543Smrg    ClientPtr	    client;
93706f2543Smrg    WindowPtr	    window;
94706f2543Smrg    XID		    clientResource;
95706f2543Smrg} ShapeEventRec;
96706f2543Smrg
97706f2543Smrg/****************
98706f2543Smrg * ShapeExtensionInit
99706f2543Smrg *
100706f2543Smrg * Called from InitExtensions in main() or from QueryExtension() if the
101706f2543Smrg * extension is dynamically loaded.
102706f2543Smrg *
103706f2543Smrg ****************/
104706f2543Smrg
105706f2543Smrgstatic int
106706f2543SmrgRegionOperate (
107706f2543Smrg	ClientPtr client,
108706f2543Smrg	WindowPtr pWin,
109706f2543Smrg	int kind,
110706f2543Smrg	RegionPtr *destRgnp,
111706f2543Smrg	RegionPtr srcRgn,
112706f2543Smrg	int op,
113706f2543Smrg	int xoff, int yoff,
114706f2543Smrg	CreateDftPtr create)
115706f2543Smrg{
116706f2543Smrg    if (srcRgn && (xoff || yoff))
117706f2543Smrg	RegionTranslate(srcRgn, xoff, yoff);
118706f2543Smrg    if (!pWin->parent)
119706f2543Smrg    {
120706f2543Smrg	if (srcRgn)
121706f2543Smrg	    RegionDestroy(srcRgn);
122706f2543Smrg	return Success;
123706f2543Smrg    }
124706f2543Smrg
125706f2543Smrg    /* May/30/2001:
126706f2543Smrg     * The shape.PS specs say if src is None, existing shape is to be
127706f2543Smrg     * removed (and so the op-code has no meaning in such removal);
128706f2543Smrg     * see shape.PS, page 3, ShapeMask.
129706f2543Smrg     */
130706f2543Smrg    if (srcRgn == NULL) {
131706f2543Smrg      if (*destRgnp != NULL) {
132706f2543Smrg	RegionDestroy(*destRgnp);
133706f2543Smrg	*destRgnp = 0;
134706f2543Smrg	/* go on to remove shape and generate ShapeNotify */
135706f2543Smrg      }
136706f2543Smrg      else {
137706f2543Smrg	/* May/30/2001:
138706f2543Smrg	 * The target currently has no shape in effect, so nothing to
139706f2543Smrg	 * do here.  The specs say that ShapeNotify is generated whenever
140706f2543Smrg	 * the client region is "modified"; since no modification is done
141706f2543Smrg	 * here, we do not generate that event.  The specs does not say
142706f2543Smrg	 * "it is an error to request removal when there is no shape in
143706f2543Smrg	 * effect", so we return good status.
144706f2543Smrg	 */
145706f2543Smrg	return Success;
146706f2543Smrg      }
147706f2543Smrg    }
148706f2543Smrg    else switch (op) {
149706f2543Smrg    case ShapeSet:
150706f2543Smrg	if (*destRgnp)
151706f2543Smrg	    RegionDestroy(*destRgnp);
152706f2543Smrg	*destRgnp = srcRgn;
153706f2543Smrg	srcRgn = 0;
154706f2543Smrg	break;
155706f2543Smrg    case ShapeUnion:
156706f2543Smrg	if (*destRgnp)
157706f2543Smrg	    RegionUnion(*destRgnp, *destRgnp, srcRgn);
158706f2543Smrg	break;
159706f2543Smrg    case ShapeIntersect:
160706f2543Smrg	if (*destRgnp)
161706f2543Smrg	    RegionIntersect(*destRgnp, *destRgnp, srcRgn);
162706f2543Smrg	else {
163706f2543Smrg	    *destRgnp = srcRgn;
164706f2543Smrg	    srcRgn = 0;
165706f2543Smrg	}
166706f2543Smrg	break;
167706f2543Smrg    case ShapeSubtract:
168706f2543Smrg	if (!*destRgnp)
169706f2543Smrg	    *destRgnp = (*create)(pWin);
170706f2543Smrg	RegionSubtract(*destRgnp, *destRgnp, srcRgn);
171706f2543Smrg	break;
172706f2543Smrg    case ShapeInvert:
173706f2543Smrg	if (!*destRgnp)
174706f2543Smrg	    *destRgnp = RegionCreate((BoxPtr) 0, 0);
175706f2543Smrg	else
176706f2543Smrg	    RegionSubtract(*destRgnp, srcRgn, *destRgnp);
177706f2543Smrg	break;
178706f2543Smrg    default:
179706f2543Smrg	client->errorValue = op;
180706f2543Smrg	return BadValue;
181706f2543Smrg    }
182706f2543Smrg    if (srcRgn)
183706f2543Smrg	RegionDestroy(srcRgn);
184706f2543Smrg    (*pWin->drawable.pScreen->SetShape) (pWin, kind);
185706f2543Smrg    SendShapeNotify (pWin, kind);
186706f2543Smrg    return Success;
187706f2543Smrg}
188706f2543Smrg
189706f2543SmrgRegionPtr
190706f2543SmrgCreateBoundingShape (WindowPtr pWin)
191706f2543Smrg{
192706f2543Smrg    BoxRec	extents;
193706f2543Smrg
194706f2543Smrg    extents.x1 = -wBorderWidth (pWin);
195706f2543Smrg    extents.y1 = -wBorderWidth (pWin);
196706f2543Smrg    extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
197706f2543Smrg    extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
198706f2543Smrg    return RegionCreate(&extents, 1);
199706f2543Smrg}
200706f2543Smrg
201706f2543SmrgRegionPtr
202706f2543SmrgCreateClipShape (WindowPtr pWin)
203706f2543Smrg{
204706f2543Smrg    BoxRec	extents;
205706f2543Smrg
206706f2543Smrg    extents.x1 = 0;
207706f2543Smrg    extents.y1 = 0;
208706f2543Smrg    extents.x2 = pWin->drawable.width;
209706f2543Smrg    extents.y2 = pWin->drawable.height;
210706f2543Smrg    return RegionCreate(&extents, 1);
211706f2543Smrg}
212706f2543Smrg
213706f2543Smrgstatic int
214706f2543SmrgProcShapeQueryVersion (ClientPtr client)
215706f2543Smrg{
216706f2543Smrg    xShapeQueryVersionReply	rep;
217706f2543Smrg    int		n;
218706f2543Smrg
219706f2543Smrg    REQUEST_SIZE_MATCH (xShapeQueryVersionReq);
220706f2543Smrg    memset(&rep, 0, sizeof(xShapeQueryVersionReply));
221706f2543Smrg    rep.type = X_Reply;
222706f2543Smrg    rep.length = 0;
223706f2543Smrg    rep.sequenceNumber = client->sequence;
224706f2543Smrg    rep.majorVersion = SERVER_SHAPE_MAJOR_VERSION;
225706f2543Smrg    rep.minorVersion = SERVER_SHAPE_MINOR_VERSION;
226706f2543Smrg    if (client->swapped) {
227706f2543Smrg    	swaps(&rep.sequenceNumber, n);
228706f2543Smrg    	swapl(&rep.length, n);
229706f2543Smrg	swaps(&rep.majorVersion, n);
230706f2543Smrg	swaps(&rep.minorVersion, n);
231706f2543Smrg    }
232706f2543Smrg    WriteToClient(client, sizeof (xShapeQueryVersionReply), (char *)&rep);
233706f2543Smrg    return Success;
234706f2543Smrg}
235706f2543Smrg
236706f2543Smrg/*****************
237706f2543Smrg * ProcShapeRectangles
238706f2543Smrg *
239706f2543Smrg *****************/
240706f2543Smrg
241706f2543Smrgstatic int
242706f2543SmrgProcShapeRectangles (ClientPtr client)
243706f2543Smrg{
244706f2543Smrg    WindowPtr		pWin;
245706f2543Smrg    REQUEST(xShapeRectanglesReq);
246706f2543Smrg    xRectangle		*prects;
247706f2543Smrg    int		        nrects, ctype, rc;
248706f2543Smrg    RegionPtr		srcRgn;
249706f2543Smrg    RegionPtr		*destRgn;
250706f2543Smrg    CreateDftPtr	createDefault;
251706f2543Smrg
252706f2543Smrg    REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
253706f2543Smrg    UpdateCurrentTime();
254706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
255706f2543Smrg    if (rc != Success)
256706f2543Smrg	return rc;
257706f2543Smrg    switch (stuff->destKind) {
258706f2543Smrg    case ShapeBounding:
259706f2543Smrg	createDefault = CreateBoundingShape;
260706f2543Smrg	break;
261706f2543Smrg    case ShapeClip:
262706f2543Smrg	createDefault = CreateClipShape;
263706f2543Smrg	break;
264706f2543Smrg    case ShapeInput:
265706f2543Smrg	createDefault = CreateBoundingShape;
266706f2543Smrg	break;
267706f2543Smrg    default:
268706f2543Smrg	client->errorValue = stuff->destKind;
269706f2543Smrg	return BadValue;
270706f2543Smrg    }
271706f2543Smrg    if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
272706f2543Smrg	(stuff->ordering != YXSorted) && (stuff->ordering != YXBanded))
273706f2543Smrg    {
274706f2543Smrg	client->errorValue = stuff->ordering;
275706f2543Smrg        return BadValue;
276706f2543Smrg    }
277706f2543Smrg    nrects = ((stuff->length  << 2) - sizeof(xShapeRectanglesReq));
278706f2543Smrg    if (nrects & 4)
279706f2543Smrg	return BadLength;
280706f2543Smrg    nrects >>= 3;
281706f2543Smrg    prects = (xRectangle *) &stuff[1];
282706f2543Smrg    ctype = VerifyRectOrder(nrects, prects, (int)stuff->ordering);
283706f2543Smrg    if (ctype < 0)
284706f2543Smrg	return BadMatch;
285706f2543Smrg    srcRgn = RegionFromRects(nrects, prects, ctype);
286706f2543Smrg
287706f2543Smrg    if (!pWin->optional)
288706f2543Smrg	MakeWindowOptional (pWin);
289706f2543Smrg    switch (stuff->destKind) {
290706f2543Smrg    case ShapeBounding:
291706f2543Smrg	destRgn = &pWin->optional->boundingShape;
292706f2543Smrg	break;
293706f2543Smrg    case ShapeClip:
294706f2543Smrg	destRgn = &pWin->optional->clipShape;
295706f2543Smrg	break;
296706f2543Smrg    case ShapeInput:
297706f2543Smrg	destRgn = &pWin->optional->inputShape;
298706f2543Smrg	break;
299706f2543Smrg    default:
300706f2543Smrg	return BadValue;
301706f2543Smrg    }
302706f2543Smrg
303706f2543Smrg    return RegionOperate (client, pWin, (int)stuff->destKind,
304706f2543Smrg			  destRgn, srcRgn, (int)stuff->op,
305706f2543Smrg			  stuff->xOff, stuff->yOff, createDefault);
306706f2543Smrg}
307706f2543Smrg
308706f2543Smrg#ifdef PANORAMIX
309706f2543Smrgstatic int
310706f2543SmrgProcPanoramiXShapeRectangles(
311706f2543Smrg    ClientPtr client)
312706f2543Smrg{
313706f2543Smrg    REQUEST(xShapeRectanglesReq);
314706f2543Smrg    PanoramiXRes	*win;
315706f2543Smrg    int        		j, result;
316706f2543Smrg
317706f2543Smrg    REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
318706f2543Smrg
319706f2543Smrg    result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
320706f2543Smrg				     client, DixWriteAccess);
321706f2543Smrg    if (result != Success)
322706f2543Smrg	return result;
323706f2543Smrg
324706f2543Smrg    FOR_NSCREENS(j) {
325706f2543Smrg	stuff->dest = win->info[j].id;
326706f2543Smrg	result = ProcShapeRectangles (client);
327706f2543Smrg	if (result != Success) break;
328706f2543Smrg    }
329706f2543Smrg    return result;
330706f2543Smrg}
331706f2543Smrg#endif
332706f2543Smrg
333706f2543Smrg
334706f2543Smrg/**************
335706f2543Smrg * ProcShapeMask
336706f2543Smrg **************/
337706f2543Smrg
338706f2543Smrg
339706f2543Smrgstatic int
340706f2543SmrgProcShapeMask (ClientPtr client)
341706f2543Smrg{
342706f2543Smrg    WindowPtr		pWin;
343706f2543Smrg    ScreenPtr		pScreen;
344706f2543Smrg    REQUEST(xShapeMaskReq);
345706f2543Smrg    RegionPtr		srcRgn;
346706f2543Smrg    RegionPtr		*destRgn;
347706f2543Smrg    PixmapPtr		pPixmap;
348706f2543Smrg    CreateDftPtr	createDefault;
349706f2543Smrg    int			rc;
350706f2543Smrg
351706f2543Smrg    REQUEST_SIZE_MATCH (xShapeMaskReq);
352706f2543Smrg    UpdateCurrentTime();
353706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
354706f2543Smrg    if (rc != Success)
355706f2543Smrg	return rc;
356706f2543Smrg    switch (stuff->destKind) {
357706f2543Smrg    case ShapeBounding:
358706f2543Smrg	createDefault = CreateBoundingShape;
359706f2543Smrg	break;
360706f2543Smrg    case ShapeClip:
361706f2543Smrg	createDefault = CreateClipShape;
362706f2543Smrg	break;
363706f2543Smrg    case ShapeInput:
364706f2543Smrg	createDefault = CreateBoundingShape;
365706f2543Smrg	break;
366706f2543Smrg    default:
367706f2543Smrg	client->errorValue = stuff->destKind;
368706f2543Smrg	return BadValue;
369706f2543Smrg    }
370706f2543Smrg    pScreen = pWin->drawable.pScreen;
371706f2543Smrg    if (stuff->src == None)
372706f2543Smrg	srcRgn = 0;
373706f2543Smrg    else {
374706f2543Smrg	rc = dixLookupResourceByType((pointer *)&pPixmap, stuff->src, RT_PIXMAP,
375706f2543Smrg			       client, DixReadAccess);
376706f2543Smrg        if (rc != Success)
377706f2543Smrg	    return rc;
378706f2543Smrg	if (pPixmap->drawable.pScreen != pScreen ||
379706f2543Smrg	    pPixmap->drawable.depth != 1)
380706f2543Smrg	    return BadMatch;
381706f2543Smrg	srcRgn = BitmapToRegion(pScreen, pPixmap);
382706f2543Smrg	if (!srcRgn)
383706f2543Smrg	    return BadAlloc;
384706f2543Smrg    }
385706f2543Smrg
386706f2543Smrg    if (!pWin->optional)
387706f2543Smrg	MakeWindowOptional (pWin);
388706f2543Smrg    switch (stuff->destKind) {
389706f2543Smrg    case ShapeBounding:
390706f2543Smrg	destRgn = &pWin->optional->boundingShape;
391706f2543Smrg	break;
392706f2543Smrg    case ShapeClip:
393706f2543Smrg	destRgn = &pWin->optional->clipShape;
394706f2543Smrg	break;
395706f2543Smrg    case ShapeInput:
396706f2543Smrg	destRgn = &pWin->optional->inputShape;
397706f2543Smrg	break;
398706f2543Smrg    default:
399706f2543Smrg	return BadValue;
400706f2543Smrg    }
401706f2543Smrg
402706f2543Smrg    return RegionOperate (client, pWin, (int)stuff->destKind,
403706f2543Smrg			  destRgn, srcRgn, (int)stuff->op,
404706f2543Smrg			  stuff->xOff, stuff->yOff, createDefault);
405706f2543Smrg}
406706f2543Smrg
407706f2543Smrg#ifdef PANORAMIX
408706f2543Smrgstatic int
409706f2543SmrgProcPanoramiXShapeMask(
410706f2543Smrg    ClientPtr client)
411706f2543Smrg{
412706f2543Smrg    REQUEST(xShapeMaskReq);
413706f2543Smrg    PanoramiXRes	*win, *pmap;
414706f2543Smrg    int 		j, result;
415706f2543Smrg
416706f2543Smrg    REQUEST_SIZE_MATCH (xShapeMaskReq);
417706f2543Smrg
418706f2543Smrg    result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
419706f2543Smrg				     client, DixWriteAccess);
420706f2543Smrg    if (result != Success)
421706f2543Smrg	return result;
422706f2543Smrg
423706f2543Smrg    if(stuff->src != None) {
424706f2543Smrg	result = dixLookupResourceByType((pointer *)&pmap, stuff->src,
425706f2543Smrg					 XRT_PIXMAP, client, DixReadAccess);
426706f2543Smrg	if (result != Success)
427706f2543Smrg	    return result;
428706f2543Smrg    } else
429706f2543Smrg	pmap = NULL;
430706f2543Smrg
431706f2543Smrg    FOR_NSCREENS(j) {
432706f2543Smrg	stuff->dest = win->info[j].id;
433706f2543Smrg	if(pmap)
434706f2543Smrg	    stuff->src  = pmap->info[j].id;
435706f2543Smrg	result = ProcShapeMask (client);
436706f2543Smrg	if (result != Success) break;
437706f2543Smrg    }
438706f2543Smrg    return result;
439706f2543Smrg}
440706f2543Smrg#endif
441706f2543Smrg
442706f2543Smrg
443706f2543Smrg/************
444706f2543Smrg * ProcShapeCombine
445706f2543Smrg ************/
446706f2543Smrg
447706f2543Smrgstatic int
448706f2543SmrgProcShapeCombine (ClientPtr client)
449706f2543Smrg{
450706f2543Smrg    WindowPtr		pSrcWin, pDestWin;
451706f2543Smrg    REQUEST(xShapeCombineReq);
452706f2543Smrg    RegionPtr		srcRgn;
453706f2543Smrg    RegionPtr		*destRgn;
454706f2543Smrg    CreateDftPtr	createDefault;
455706f2543Smrg    CreateDftPtr	createSrc;
456706f2543Smrg    RegionPtr		tmp;
457706f2543Smrg    int			rc;
458706f2543Smrg
459706f2543Smrg    REQUEST_SIZE_MATCH (xShapeCombineReq);
460706f2543Smrg    UpdateCurrentTime();
461706f2543Smrg    rc = dixLookupWindow(&pDestWin, stuff->dest, client, DixSetAttrAccess);
462706f2543Smrg    if (rc != Success)
463706f2543Smrg	return rc;
464706f2543Smrg    if (!pDestWin->optional)
465706f2543Smrg	MakeWindowOptional (pDestWin);
466706f2543Smrg    switch (stuff->destKind) {
467706f2543Smrg    case ShapeBounding:
468706f2543Smrg	createDefault = CreateBoundingShape;
469706f2543Smrg	break;
470706f2543Smrg    case ShapeClip:
471706f2543Smrg	createDefault = CreateClipShape;
472706f2543Smrg	break;
473706f2543Smrg    case ShapeInput:
474706f2543Smrg	createDefault = CreateBoundingShape;
475706f2543Smrg	break;
476706f2543Smrg    default:
477706f2543Smrg	client->errorValue = stuff->destKind;
478706f2543Smrg	return BadValue;
479706f2543Smrg    }
480706f2543Smrg
481706f2543Smrg    rc = dixLookupWindow(&pSrcWin, stuff->src, client, DixGetAttrAccess);
482706f2543Smrg    if (rc != Success)
483706f2543Smrg	return rc;
484706f2543Smrg    switch (stuff->srcKind) {
485706f2543Smrg    case ShapeBounding:
486706f2543Smrg	srcRgn = wBoundingShape (pSrcWin);
487706f2543Smrg	createSrc = CreateBoundingShape;
488706f2543Smrg	break;
489706f2543Smrg    case ShapeClip:
490706f2543Smrg	srcRgn = wClipShape (pSrcWin);
491706f2543Smrg	createSrc = CreateClipShape;
492706f2543Smrg	break;
493706f2543Smrg    case ShapeInput:
494706f2543Smrg	srcRgn = wInputShape (pSrcWin);
495706f2543Smrg	createSrc = CreateBoundingShape;
496706f2543Smrg	break;
497706f2543Smrg    default:
498706f2543Smrg	client->errorValue = stuff->srcKind;
499706f2543Smrg	return BadValue;
500706f2543Smrg    }
501706f2543Smrg    if (pSrcWin->drawable.pScreen != pDestWin->drawable.pScreen)
502706f2543Smrg    {
503706f2543Smrg	return BadMatch;
504706f2543Smrg    }
505706f2543Smrg
506706f2543Smrg    if (srcRgn) {
507706f2543Smrg        tmp = RegionCreate((BoxPtr) 0, 0);
508706f2543Smrg        RegionCopy(tmp, srcRgn);
509706f2543Smrg        srcRgn = tmp;
510706f2543Smrg    } else
511706f2543Smrg	srcRgn = (*createSrc) (pSrcWin);
512706f2543Smrg
513706f2543Smrg    if (!pDestWin->optional)
514706f2543Smrg	MakeWindowOptional (pDestWin);
515706f2543Smrg    switch (stuff->destKind) {
516706f2543Smrg    case ShapeBounding:
517706f2543Smrg	destRgn = &pDestWin->optional->boundingShape;
518706f2543Smrg	break;
519706f2543Smrg    case ShapeClip:
520706f2543Smrg	destRgn = &pDestWin->optional->clipShape;
521706f2543Smrg	break;
522706f2543Smrg    case ShapeInput:
523706f2543Smrg	destRgn = &pDestWin->optional->inputShape;
524706f2543Smrg	break;
525706f2543Smrg    default:
526706f2543Smrg	return BadValue;
527706f2543Smrg    }
528706f2543Smrg
529706f2543Smrg    return RegionOperate (client, pDestWin, (int)stuff->destKind,
530706f2543Smrg			  destRgn, srcRgn, (int)stuff->op,
531706f2543Smrg			  stuff->xOff, stuff->yOff, createDefault);
532706f2543Smrg}
533706f2543Smrg
534706f2543Smrg
535706f2543Smrg#ifdef PANORAMIX
536706f2543Smrgstatic int
537706f2543SmrgProcPanoramiXShapeCombine(
538706f2543Smrg    ClientPtr client)
539706f2543Smrg{
540706f2543Smrg    REQUEST(xShapeCombineReq);
541706f2543Smrg    PanoramiXRes	*win, *win2;
542706f2543Smrg    int 		j, result;
543706f2543Smrg
544706f2543Smrg    REQUEST_AT_LEAST_SIZE (xShapeCombineReq);
545706f2543Smrg
546706f2543Smrg    result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
547706f2543Smrg				     client, DixWriteAccess);
548706f2543Smrg    if (result != Success)
549706f2543Smrg	return result;
550706f2543Smrg
551706f2543Smrg    result = dixLookupResourceByType((pointer *)&win2, stuff->src, XRT_WINDOW,
552706f2543Smrg				     client, DixReadAccess);
553706f2543Smrg    if (result != Success)
554706f2543Smrg	return result;
555706f2543Smrg
556706f2543Smrg    FOR_NSCREENS(j) {
557706f2543Smrg	stuff->dest = win->info[j].id;
558706f2543Smrg	stuff->src =  win2->info[j].id;
559706f2543Smrg	result = ProcShapeCombine (client);
560706f2543Smrg	if (result != Success) break;
561706f2543Smrg    }
562706f2543Smrg    return result;
563706f2543Smrg}
564706f2543Smrg#endif
565706f2543Smrg
566706f2543Smrg/*************
567706f2543Smrg * ProcShapeOffset
568706f2543Smrg *************/
569706f2543Smrg
570706f2543Smrgstatic int
571706f2543SmrgProcShapeOffset (ClientPtr client)
572706f2543Smrg{
573706f2543Smrg    WindowPtr		pWin;
574706f2543Smrg    REQUEST(xShapeOffsetReq);
575706f2543Smrg    RegionPtr		srcRgn;
576706f2543Smrg    int			rc;
577706f2543Smrg
578706f2543Smrg    REQUEST_SIZE_MATCH (xShapeOffsetReq);
579706f2543Smrg    UpdateCurrentTime();
580706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
581706f2543Smrg    if (rc != Success)
582706f2543Smrg	return rc;
583706f2543Smrg    switch (stuff->destKind) {
584706f2543Smrg    case ShapeBounding:
585706f2543Smrg	srcRgn = wBoundingShape (pWin);
586706f2543Smrg	break;
587706f2543Smrg    case ShapeClip:
588706f2543Smrg	srcRgn = wClipShape(pWin);
589706f2543Smrg	break;
590706f2543Smrg    case ShapeInput:
591706f2543Smrg	srcRgn = wInputShape (pWin);
592706f2543Smrg	break;
593706f2543Smrg    default:
594706f2543Smrg	client->errorValue = stuff->destKind;
595706f2543Smrg	return BadValue;
596706f2543Smrg    }
597706f2543Smrg    if (srcRgn)
598706f2543Smrg    {
599706f2543Smrg        RegionTranslate(srcRgn, stuff->xOff, stuff->yOff);
600706f2543Smrg        (*pWin->drawable.pScreen->SetShape) (pWin, stuff->destKind);
601706f2543Smrg    }
602706f2543Smrg    SendShapeNotify (pWin, (int)stuff->destKind);
603706f2543Smrg    return Success;
604706f2543Smrg}
605706f2543Smrg
606706f2543Smrg
607706f2543Smrg#ifdef PANORAMIX
608706f2543Smrgstatic int
609706f2543SmrgProcPanoramiXShapeOffset(
610706f2543Smrg    ClientPtr client)
611706f2543Smrg{
612706f2543Smrg    REQUEST(xShapeOffsetReq);
613706f2543Smrg    PanoramiXRes *win;
614706f2543Smrg    int j, result;
615706f2543Smrg
616706f2543Smrg    REQUEST_AT_LEAST_SIZE (xShapeOffsetReq);
617706f2543Smrg
618706f2543Smrg    result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
619706f2543Smrg				     client, DixWriteAccess);
620706f2543Smrg    if (result != Success)
621706f2543Smrg	return result;
622706f2543Smrg
623706f2543Smrg    FOR_NSCREENS(j) {
624706f2543Smrg	stuff->dest = win->info[j].id;
625706f2543Smrg	result = ProcShapeOffset (client);
626706f2543Smrg	if(result != Success) break;
627706f2543Smrg    }
628706f2543Smrg    return result;
629706f2543Smrg}
630706f2543Smrg#endif
631706f2543Smrg
632706f2543Smrg
633706f2543Smrgstatic int
634706f2543SmrgProcShapeQueryExtents (ClientPtr client)
635706f2543Smrg{
636706f2543Smrg    REQUEST(xShapeQueryExtentsReq);
637706f2543Smrg    WindowPtr		pWin;
638706f2543Smrg    xShapeQueryExtentsReply	rep;
639706f2543Smrg    BoxRec		extents, *pExtents;
640706f2543Smrg    int	n, rc;
641706f2543Smrg    RegionPtr		region;
642706f2543Smrg
643706f2543Smrg    REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
644706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
645706f2543Smrg    if (rc != Success)
646706f2543Smrg	return rc;
647706f2543Smrg    memset(&rep, 0, sizeof(xShapeQueryExtentsReply));
648706f2543Smrg    rep.type = X_Reply;
649706f2543Smrg    rep.length = 0;
650706f2543Smrg    rep.sequenceNumber = client->sequence;
651706f2543Smrg    rep.boundingShaped = (wBoundingShape(pWin) != 0);
652706f2543Smrg    rep.clipShaped = (wClipShape(pWin) != 0);
653706f2543Smrg    if ((region = wBoundingShape(pWin))) {
654706f2543Smrg     /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
655706f2543Smrg	pExtents = RegionExtents(region);
656706f2543Smrg	extents = *pExtents;
657706f2543Smrg    } else {
658706f2543Smrg	extents.x1 = -wBorderWidth (pWin);
659706f2543Smrg	extents.y1 = -wBorderWidth (pWin);
660706f2543Smrg	extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
661706f2543Smrg	extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
662706f2543Smrg    }
663706f2543Smrg    rep.xBoundingShape = extents.x1;
664706f2543Smrg    rep.yBoundingShape = extents.y1;
665706f2543Smrg    rep.widthBoundingShape = extents.x2 - extents.x1;
666706f2543Smrg    rep.heightBoundingShape = extents.y2 - extents.y1;
667706f2543Smrg    if ((region = wClipShape(pWin))) {
668706f2543Smrg     /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
669706f2543Smrg	pExtents = RegionExtents(region);
670706f2543Smrg	extents = *pExtents;
671706f2543Smrg    } else {
672706f2543Smrg	extents.x1 = 0;
673706f2543Smrg	extents.y1 = 0;
674706f2543Smrg	extents.x2 = pWin->drawable.width;
675706f2543Smrg	extents.y2 = pWin->drawable.height;
676706f2543Smrg    }
677706f2543Smrg    rep.xClipShape = extents.x1;
678706f2543Smrg    rep.yClipShape = extents.y1;
679706f2543Smrg    rep.widthClipShape = extents.x2 - extents.x1;
680706f2543Smrg    rep.heightClipShape = extents.y2 - extents.y1;
681706f2543Smrg    if (client->swapped) {
682706f2543Smrg    	swaps(&rep.sequenceNumber, n);
683706f2543Smrg    	swapl(&rep.length, n);
684706f2543Smrg	swaps(&rep.xBoundingShape, n);
685706f2543Smrg	swaps(&rep.yBoundingShape, n);
686706f2543Smrg	swaps(&rep.widthBoundingShape, n);
687706f2543Smrg	swaps(&rep.heightBoundingShape, n);
688706f2543Smrg	swaps(&rep.xClipShape, n);
689706f2543Smrg	swaps(&rep.yClipShape, n);
690706f2543Smrg	swaps(&rep.widthClipShape, n);
691706f2543Smrg	swaps(&rep.heightClipShape, n);
692706f2543Smrg    }
693706f2543Smrg    WriteToClient(client, sizeof (xShapeQueryExtentsReply), (char *)&rep);
694706f2543Smrg    return Success;
695706f2543Smrg}
696706f2543Smrg
697706f2543Smrg/*ARGSUSED*/
698706f2543Smrgstatic int
699706f2543SmrgShapeFreeClient (pointer data, XID id)
700706f2543Smrg{
701706f2543Smrg    ShapeEventPtr   pShapeEvent;
702706f2543Smrg    WindowPtr	    pWin;
703706f2543Smrg    ShapeEventPtr   *pHead, pCur, pPrev;
704706f2543Smrg    int rc;
705706f2543Smrg
706706f2543Smrg    pShapeEvent = (ShapeEventPtr) data;
707706f2543Smrg    pWin = pShapeEvent->window;
708706f2543Smrg    rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
709706f2543Smrg				 ShapeEventType, serverClient, DixReadAccess);
710706f2543Smrg    if (rc == Success) {
711706f2543Smrg	pPrev = 0;
712706f2543Smrg	for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur=pCur->next)
713706f2543Smrg	    pPrev = pCur;
714706f2543Smrg	if (pCur)
715706f2543Smrg	{
716706f2543Smrg	    if (pPrev)
717706f2543Smrg	    	pPrev->next = pShapeEvent->next;
718706f2543Smrg	    else
719706f2543Smrg	    	*pHead = pShapeEvent->next;
720706f2543Smrg	}
721706f2543Smrg    }
722706f2543Smrg    free((pointer) pShapeEvent);
723706f2543Smrg    return 1;
724706f2543Smrg}
725706f2543Smrg
726706f2543Smrg/*ARGSUSED*/
727706f2543Smrgstatic int
728706f2543SmrgShapeFreeEvents (pointer data, XID id)
729706f2543Smrg{
730706f2543Smrg    ShapeEventPtr   *pHead, pCur, pNext;
731706f2543Smrg
732706f2543Smrg    pHead = (ShapeEventPtr *) data;
733706f2543Smrg    for (pCur = *pHead; pCur; pCur = pNext) {
734706f2543Smrg	pNext = pCur->next;
735706f2543Smrg	FreeResource (pCur->clientResource, ClientType);
736706f2543Smrg	free((pointer) pCur);
737706f2543Smrg    }
738706f2543Smrg    free((pointer) pHead);
739706f2543Smrg    return 1;
740706f2543Smrg}
741706f2543Smrg
742706f2543Smrgstatic int
743706f2543SmrgProcShapeSelectInput (ClientPtr client)
744706f2543Smrg{
745706f2543Smrg    REQUEST(xShapeSelectInputReq);
746706f2543Smrg    WindowPtr		pWin;
747706f2543Smrg    ShapeEventPtr	pShapeEvent, pNewShapeEvent, *pHead;
748706f2543Smrg    XID			clientResource;
749706f2543Smrg    int			rc;
750706f2543Smrg
751706f2543Smrg    REQUEST_SIZE_MATCH (xShapeSelectInputReq);
752706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
753706f2543Smrg    if (rc != Success)
754706f2543Smrg	return rc;
755706f2543Smrg    rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
756706f2543Smrg				 ShapeEventType, client, DixWriteAccess);
757706f2543Smrg    if (rc != Success && rc != BadValue)
758706f2543Smrg	return rc;
759706f2543Smrg
760706f2543Smrg    switch (stuff->enable) {
761706f2543Smrg    case xTrue:
762706f2543Smrg	if (pHead) {
763706f2543Smrg
764706f2543Smrg	    /* check for existing entry. */
765706f2543Smrg	    for (pShapeEvent = *pHead;
766706f2543Smrg		 pShapeEvent;
767706f2543Smrg 		 pShapeEvent = pShapeEvent->next)
768706f2543Smrg	    {
769706f2543Smrg		if (pShapeEvent->client == client)
770706f2543Smrg		    return Success;
771706f2543Smrg	    }
772706f2543Smrg	}
773706f2543Smrg
774706f2543Smrg	/* build the entry */
775706f2543Smrg	pNewShapeEvent = malloc(sizeof (ShapeEventRec));
776706f2543Smrg    	if (!pNewShapeEvent)
777706f2543Smrg	    return BadAlloc;
778706f2543Smrg    	pNewShapeEvent->next = 0;
779706f2543Smrg    	pNewShapeEvent->client = client;
780706f2543Smrg    	pNewShapeEvent->window = pWin;
781706f2543Smrg    	/*
782706f2543Smrg 	 * add a resource that will be deleted when
783706f2543Smrg     	 * the client goes away
784706f2543Smrg     	 */
785706f2543Smrg   	clientResource = FakeClientID (client->index);
786706f2543Smrg    	pNewShapeEvent->clientResource = clientResource;
787706f2543Smrg    	if (!AddResource (clientResource, ClientType, (pointer)pNewShapeEvent))
788706f2543Smrg	    return BadAlloc;
789706f2543Smrg    	/*
790706f2543Smrg     	 * create a resource to contain a pointer to the list
791706f2543Smrg     	 * of clients selecting input.  This must be indirect as
792706f2543Smrg     	 * the list may be arbitrarily rearranged which cannot be
793706f2543Smrg     	 * done through the resource database.
794706f2543Smrg     	 */
795706f2543Smrg    	if (!pHead)
796706f2543Smrg    	{
797706f2543Smrg	    pHead = malloc(sizeof (ShapeEventPtr));
798706f2543Smrg	    if (!pHead ||
799706f2543Smrg		!AddResource (pWin->drawable.id, ShapeEventType, (pointer)pHead))
800706f2543Smrg	    {
801706f2543Smrg	    	FreeResource (clientResource, RT_NONE);
802706f2543Smrg	    	return BadAlloc;
803706f2543Smrg	    }
804706f2543Smrg	    *pHead = 0;
805706f2543Smrg    	}
806706f2543Smrg    	pNewShapeEvent->next = *pHead;
807706f2543Smrg    	*pHead = pNewShapeEvent;
808706f2543Smrg	break;
809706f2543Smrg    case xFalse:
810706f2543Smrg	/* delete the interest */
811706f2543Smrg	if (pHead) {
812706f2543Smrg	    pNewShapeEvent = 0;
813706f2543Smrg	    for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
814706f2543Smrg		if (pShapeEvent->client == client)
815706f2543Smrg		    break;
816706f2543Smrg		pNewShapeEvent = pShapeEvent;
817706f2543Smrg	    }
818706f2543Smrg	    if (pShapeEvent) {
819706f2543Smrg		FreeResource (pShapeEvent->clientResource, ClientType);
820706f2543Smrg		if (pNewShapeEvent)
821706f2543Smrg		    pNewShapeEvent->next = pShapeEvent->next;
822706f2543Smrg		else
823706f2543Smrg		    *pHead = pShapeEvent->next;
824706f2543Smrg		free(pShapeEvent);
825706f2543Smrg	    }
826706f2543Smrg	}
827706f2543Smrg	break;
828706f2543Smrg    default:
829706f2543Smrg	client->errorValue = stuff->enable;
830706f2543Smrg	return BadValue;
831706f2543Smrg    }
832706f2543Smrg    return Success;
833706f2543Smrg}
834706f2543Smrg
835706f2543Smrg/*
836706f2543Smrg * deliver the event
837706f2543Smrg */
838706f2543Smrg
839706f2543Smrgvoid
840706f2543SmrgSendShapeNotify (WindowPtr pWin, int which)
841706f2543Smrg{
842706f2543Smrg    ShapeEventPtr	*pHead, pShapeEvent;
843706f2543Smrg    xShapeNotifyEvent	se;
844706f2543Smrg    BoxRec		extents;
845706f2543Smrg    RegionPtr		region;
846706f2543Smrg    BYTE		shaped;
847706f2543Smrg    int rc;
848706f2543Smrg
849706f2543Smrg    rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
850706f2543Smrg				 ShapeEventType, serverClient, DixReadAccess);
851706f2543Smrg    if (rc != Success)
852706f2543Smrg	return;
853706f2543Smrg    switch (which) {
854706f2543Smrg    case ShapeBounding:
855706f2543Smrg	region = wBoundingShape(pWin);
856706f2543Smrg	if (region) {
857706f2543Smrg	    extents = *RegionExtents(region);
858706f2543Smrg	    shaped = xTrue;
859706f2543Smrg	} else {
860706f2543Smrg	    extents.x1 = -wBorderWidth (pWin);
861706f2543Smrg	    extents.y1 = -wBorderWidth (pWin);
862706f2543Smrg	    extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
863706f2543Smrg	    extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
864706f2543Smrg	    shaped = xFalse;
865706f2543Smrg	}
866706f2543Smrg	break;
867706f2543Smrg    case ShapeClip:
868706f2543Smrg	region = wClipShape(pWin);
869706f2543Smrg	if (region) {
870706f2543Smrg	    extents = *RegionExtents(region);
871706f2543Smrg	    shaped = xTrue;
872706f2543Smrg	} else {
873706f2543Smrg	    extents.x1 = 0;
874706f2543Smrg	    extents.y1 = 0;
875706f2543Smrg	    extents.x2 = pWin->drawable.width;
876706f2543Smrg	    extents.y2 = pWin->drawable.height;
877706f2543Smrg	    shaped = xFalse;
878706f2543Smrg	}
879706f2543Smrg	break;
880706f2543Smrg    case ShapeInput:
881706f2543Smrg	region = wInputShape(pWin);
882706f2543Smrg	if (region) {
883706f2543Smrg	    extents = *RegionExtents(region);
884706f2543Smrg	    shaped = xTrue;
885706f2543Smrg	} else {
886706f2543Smrg	    extents.x1 = -wBorderWidth (pWin);
887706f2543Smrg	    extents.y1 = -wBorderWidth (pWin);
888706f2543Smrg	    extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
889706f2543Smrg	    extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
890706f2543Smrg	    shaped = xFalse;
891706f2543Smrg	}
892706f2543Smrg	break;
893706f2543Smrg    default:
894706f2543Smrg	return;
895706f2543Smrg    }
896706f2543Smrg    for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
897706f2543Smrg	se.type = ShapeNotify + ShapeEventBase;
898706f2543Smrg	se.kind = which;
899706f2543Smrg	se.window = pWin->drawable.id;
900706f2543Smrg	se.x = extents.x1;
901706f2543Smrg	se.y = extents.y1;
902706f2543Smrg	se.width = extents.x2 - extents.x1;
903706f2543Smrg	se.height = extents.y2 - extents.y1;
904706f2543Smrg	se.time = currentTime.milliseconds;
905706f2543Smrg	se.shaped = shaped;
906706f2543Smrg	WriteEventsToClient (pShapeEvent->client, 1, (xEvent *) &se);
907706f2543Smrg    }
908706f2543Smrg}
909706f2543Smrg
910706f2543Smrgstatic int
911706f2543SmrgProcShapeInputSelected (ClientPtr client)
912706f2543Smrg{
913706f2543Smrg    REQUEST(xShapeInputSelectedReq);
914706f2543Smrg    WindowPtr		pWin;
915706f2543Smrg    ShapeEventPtr	pShapeEvent, *pHead;
916706f2543Smrg    int			enabled, rc;
917706f2543Smrg    xShapeInputSelectedReply	rep;
918706f2543Smrg    int		n;
919706f2543Smrg
920706f2543Smrg    REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
921706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
922706f2543Smrg    if (rc != Success)
923706f2543Smrg	return rc;
924706f2543Smrg    rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
925706f2543Smrg				 ShapeEventType, client, DixReadAccess);
926706f2543Smrg    if (rc != Success && rc != BadValue)
927706f2543Smrg	return rc;
928706f2543Smrg    enabled = xFalse;
929706f2543Smrg    if (pHead) {
930706f2543Smrg    	for (pShapeEvent = *pHead;
931706f2543Smrg	     pShapeEvent;
932706f2543Smrg	     pShapeEvent = pShapeEvent->next)
933706f2543Smrg    	{
934706f2543Smrg	    if (pShapeEvent->client == client) {
935706f2543Smrg	    	enabled = xTrue;
936706f2543Smrg		break;
937706f2543Smrg	    }
938706f2543Smrg    	}
939706f2543Smrg    }
940706f2543Smrg    rep.type = X_Reply;
941706f2543Smrg    rep.length = 0;
942706f2543Smrg    rep.sequenceNumber = client->sequence;
943706f2543Smrg    rep.enabled = enabled;
944706f2543Smrg    if (client->swapped) {
945706f2543Smrg	swaps (&rep.sequenceNumber, n);
946706f2543Smrg	swapl (&rep.length, n);
947706f2543Smrg    }
948706f2543Smrg    WriteToClient (client, sizeof (xShapeInputSelectedReply), (char *) &rep);
949706f2543Smrg    return Success;
950706f2543Smrg}
951706f2543Smrg
952706f2543Smrgstatic int
953706f2543SmrgProcShapeGetRectangles (ClientPtr client)
954706f2543Smrg{
955706f2543Smrg    REQUEST(xShapeGetRectanglesReq);
956706f2543Smrg    WindowPtr			pWin;
957706f2543Smrg    xShapeGetRectanglesReply	rep;
958706f2543Smrg    xRectangle			*rects;
959706f2543Smrg    int				nrects, i, rc;
960706f2543Smrg    RegionPtr			region;
961706f2543Smrg    int		n;
962706f2543Smrg
963706f2543Smrg    REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
964706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
965706f2543Smrg    if (rc != Success)
966706f2543Smrg	return rc;
967706f2543Smrg    switch (stuff->kind) {
968706f2543Smrg    case ShapeBounding:
969706f2543Smrg	region = wBoundingShape(pWin);
970706f2543Smrg	break;
971706f2543Smrg    case ShapeClip:
972706f2543Smrg	region = wClipShape(pWin);
973706f2543Smrg	break;
974706f2543Smrg    case ShapeInput:
975706f2543Smrg	region = wInputShape (pWin);
976706f2543Smrg	break;
977706f2543Smrg    default:
978706f2543Smrg	client->errorValue = stuff->kind;
979706f2543Smrg	return BadValue;
980706f2543Smrg    }
981706f2543Smrg    if (!region) {
982706f2543Smrg	nrects = 1;
983706f2543Smrg	rects = malloc(sizeof (xRectangle));
984706f2543Smrg	if (!rects)
985706f2543Smrg	    return BadAlloc;
986706f2543Smrg	switch (stuff->kind) {
987706f2543Smrg	case ShapeBounding:
988706f2543Smrg	    rects->x = - (int) wBorderWidth (pWin);
989706f2543Smrg	    rects->y = - (int) wBorderWidth (pWin);
990706f2543Smrg	    rects->width = pWin->drawable.width + wBorderWidth (pWin);
991706f2543Smrg	    rects->height = pWin->drawable.height + wBorderWidth (pWin);
992706f2543Smrg	    break;
993706f2543Smrg	case ShapeClip:
994706f2543Smrg	    rects->x = 0;
995706f2543Smrg	    rects->y = 0;
996706f2543Smrg	    rects->width = pWin->drawable.width;
997706f2543Smrg	    rects->height = pWin->drawable.height;
998706f2543Smrg	    break;
999706f2543Smrg	case ShapeInput:
1000706f2543Smrg	    rects->x = - (int) wBorderWidth (pWin);
1001706f2543Smrg	    rects->y = - (int) wBorderWidth (pWin);
1002706f2543Smrg	    rects->width = pWin->drawable.width + wBorderWidth (pWin);
1003706f2543Smrg	    rects->height = pWin->drawable.height + wBorderWidth (pWin);
1004706f2543Smrg	    break;
1005706f2543Smrg	}
1006706f2543Smrg    } else {
1007706f2543Smrg	BoxPtr box;
1008706f2543Smrg	nrects = RegionNumRects(region);
1009706f2543Smrg	box = RegionRects(region);
1010706f2543Smrg	rects = malloc(nrects * sizeof (xRectangle));
1011706f2543Smrg	if (!rects && nrects)
1012706f2543Smrg	    return BadAlloc;
1013706f2543Smrg	for (i = 0; i < nrects; i++, box++) {
1014706f2543Smrg	    rects[i].x = box->x1;
1015706f2543Smrg	    rects[i].y = box->y1;
1016706f2543Smrg	    rects[i].width = box->x2 - box->x1;
1017706f2543Smrg	    rects[i].height = box->y2 - box->y1;
1018706f2543Smrg	}
1019706f2543Smrg    }
1020706f2543Smrg    rep.type = X_Reply;
1021706f2543Smrg    rep.sequenceNumber = client->sequence;
1022706f2543Smrg    rep.length = bytes_to_int32(nrects * sizeof (xRectangle));
1023706f2543Smrg    rep.ordering = YXBanded;
1024706f2543Smrg    rep.nrects = nrects;
1025706f2543Smrg    if (client->swapped) {
1026706f2543Smrg	swaps (&rep.sequenceNumber, n);
1027706f2543Smrg	swapl (&rep.length, n);
1028706f2543Smrg	swapl (&rep.nrects, n);
1029706f2543Smrg	SwapShorts ((short *)rects, (unsigned long)nrects * 4);
1030706f2543Smrg    }
1031706f2543Smrg    WriteToClient (client, sizeof (rep), (char *) &rep);
1032706f2543Smrg    WriteToClient (client, nrects * sizeof (xRectangle), (char *) rects);
1033706f2543Smrg    free(rects);
1034706f2543Smrg    return Success;
1035706f2543Smrg}
1036706f2543Smrg
1037706f2543Smrgstatic int
1038706f2543SmrgProcShapeDispatch (ClientPtr client)
1039706f2543Smrg{
1040706f2543Smrg    REQUEST(xReq);
1041706f2543Smrg    switch (stuff->data) {
1042706f2543Smrg    case X_ShapeQueryVersion:
1043706f2543Smrg	return ProcShapeQueryVersion (client);
1044706f2543Smrg    case X_ShapeRectangles:
1045706f2543Smrg#ifdef PANORAMIX
1046706f2543Smrg        if ( !noPanoramiXExtension )
1047706f2543Smrg	    return ProcPanoramiXShapeRectangles (client);
1048706f2543Smrg        else
1049706f2543Smrg#endif
1050706f2543Smrg	return ProcShapeRectangles (client);
1051706f2543Smrg    case X_ShapeMask:
1052706f2543Smrg#ifdef PANORAMIX
1053706f2543Smrg        if ( !noPanoramiXExtension )
1054706f2543Smrg           return ProcPanoramiXShapeMask (client);
1055706f2543Smrg	else
1056706f2543Smrg#endif
1057706f2543Smrg	return ProcShapeMask (client);
1058706f2543Smrg    case X_ShapeCombine:
1059706f2543Smrg#ifdef PANORAMIX
1060706f2543Smrg        if ( !noPanoramiXExtension )
1061706f2543Smrg           return ProcPanoramiXShapeCombine (client);
1062706f2543Smrg	else
1063706f2543Smrg#endif
1064706f2543Smrg	return ProcShapeCombine (client);
1065706f2543Smrg    case X_ShapeOffset:
1066706f2543Smrg#ifdef PANORAMIX
1067706f2543Smrg        if ( !noPanoramiXExtension )
1068706f2543Smrg           return ProcPanoramiXShapeOffset (client);
1069706f2543Smrg	else
1070706f2543Smrg#endif
1071706f2543Smrg	return ProcShapeOffset (client);
1072706f2543Smrg    case X_ShapeQueryExtents:
1073706f2543Smrg	return ProcShapeQueryExtents (client);
1074706f2543Smrg    case X_ShapeSelectInput:
1075706f2543Smrg	return ProcShapeSelectInput (client);
1076706f2543Smrg    case X_ShapeInputSelected:
1077706f2543Smrg	return ProcShapeInputSelected (client);
1078706f2543Smrg    case X_ShapeGetRectangles:
1079706f2543Smrg	return ProcShapeGetRectangles (client);
1080706f2543Smrg    default:
1081706f2543Smrg	return BadRequest;
1082706f2543Smrg    }
1083706f2543Smrg}
1084706f2543Smrg
1085706f2543Smrgstatic void
1086706f2543SmrgSShapeNotifyEvent(xShapeNotifyEvent *from, xShapeNotifyEvent *to)
1087706f2543Smrg{
1088706f2543Smrg    to->type = from->type;
1089706f2543Smrg    to->kind = from->kind;
1090706f2543Smrg    cpswapl (from->window, to->window);
1091706f2543Smrg    cpswaps (from->sequenceNumber, to->sequenceNumber);
1092706f2543Smrg    cpswaps (from->x, to->x);
1093706f2543Smrg    cpswaps (from->y, to->y);
1094706f2543Smrg    cpswaps (from->width, to->width);
1095706f2543Smrg    cpswaps (from->height, to->height);
1096706f2543Smrg    cpswapl (from->time, to->time);
1097706f2543Smrg    to->shaped = from->shaped;
1098706f2543Smrg}
1099706f2543Smrg
1100706f2543Smrgstatic int
1101706f2543SmrgSProcShapeQueryVersion (ClientPtr client)
1102706f2543Smrg{
1103706f2543Smrg    int    n;
1104706f2543Smrg    REQUEST (xShapeQueryVersionReq);
1105706f2543Smrg
1106706f2543Smrg    swaps (&stuff->length, n);
1107706f2543Smrg    return ProcShapeQueryVersion (client);
1108706f2543Smrg}
1109706f2543Smrg
1110706f2543Smrgstatic int
1111706f2543SmrgSProcShapeRectangles (ClientPtr client)
1112706f2543Smrg{
1113706f2543Smrg    char   n;
1114706f2543Smrg    REQUEST (xShapeRectanglesReq);
1115706f2543Smrg
1116706f2543Smrg    swaps (&stuff->length, n);
1117706f2543Smrg    REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
1118706f2543Smrg    swapl (&stuff->dest, n);
1119706f2543Smrg    swaps (&stuff->xOff, n);
1120706f2543Smrg    swaps (&stuff->yOff, n);
1121706f2543Smrg    SwapRestS(stuff);
1122706f2543Smrg    return ProcShapeRectangles (client);
1123706f2543Smrg}
1124706f2543Smrg
1125706f2543Smrgstatic int
1126706f2543SmrgSProcShapeMask (ClientPtr client)
1127706f2543Smrg{
1128706f2543Smrg    char   n;
1129706f2543Smrg    REQUEST (xShapeMaskReq);
1130706f2543Smrg
1131706f2543Smrg    swaps (&stuff->length, n);
1132706f2543Smrg    REQUEST_SIZE_MATCH (xShapeMaskReq);
1133706f2543Smrg    swapl (&stuff->dest, n);
1134706f2543Smrg    swaps (&stuff->xOff, n);
1135706f2543Smrg    swaps (&stuff->yOff, n);
1136706f2543Smrg    swapl (&stuff->src, n);
1137706f2543Smrg    return ProcShapeMask (client);
1138706f2543Smrg}
1139706f2543Smrg
1140706f2543Smrgstatic int
1141706f2543SmrgSProcShapeCombine (ClientPtr client)
1142706f2543Smrg{
1143706f2543Smrg    char   n;
1144706f2543Smrg    REQUEST (xShapeCombineReq);
1145706f2543Smrg
1146706f2543Smrg    swaps (&stuff->length, n);
1147706f2543Smrg    REQUEST_SIZE_MATCH (xShapeCombineReq);
1148706f2543Smrg    swapl (&stuff->dest, n);
1149706f2543Smrg    swaps (&stuff->xOff, n);
1150706f2543Smrg    swaps (&stuff->yOff, n);
1151706f2543Smrg    swapl (&stuff->src, n);
1152706f2543Smrg    return ProcShapeCombine (client);
1153706f2543Smrg}
1154706f2543Smrg
1155706f2543Smrgstatic int
1156706f2543SmrgSProcShapeOffset (ClientPtr client)
1157706f2543Smrg{
1158706f2543Smrg    char   n;
1159706f2543Smrg    REQUEST (xShapeOffsetReq);
1160706f2543Smrg
1161706f2543Smrg    swaps (&stuff->length, n);
1162706f2543Smrg    REQUEST_SIZE_MATCH (xShapeOffsetReq);
1163706f2543Smrg    swapl (&stuff->dest, n);
1164706f2543Smrg    swaps (&stuff->xOff, n);
1165706f2543Smrg    swaps (&stuff->yOff, n);
1166706f2543Smrg    return ProcShapeOffset (client);
1167706f2543Smrg}
1168706f2543Smrg
1169706f2543Smrgstatic int
1170706f2543SmrgSProcShapeQueryExtents (ClientPtr client)
1171706f2543Smrg{
1172706f2543Smrg    char   n;
1173706f2543Smrg    REQUEST (xShapeQueryExtentsReq);
1174706f2543Smrg
1175706f2543Smrg    swaps (&stuff->length, n);
1176706f2543Smrg    REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
1177706f2543Smrg    swapl (&stuff->window, n);
1178706f2543Smrg    return ProcShapeQueryExtents (client);
1179706f2543Smrg}
1180706f2543Smrg
1181706f2543Smrgstatic int
1182706f2543SmrgSProcShapeSelectInput (ClientPtr client)
1183706f2543Smrg{
1184706f2543Smrg    char   n;
1185706f2543Smrg    REQUEST (xShapeSelectInputReq);
1186706f2543Smrg
1187706f2543Smrg    swaps (&stuff->length, n);
1188706f2543Smrg    REQUEST_SIZE_MATCH (xShapeSelectInputReq);
1189706f2543Smrg    swapl (&stuff->window, n);
1190706f2543Smrg    return ProcShapeSelectInput (client);
1191706f2543Smrg}
1192706f2543Smrg
1193706f2543Smrgstatic int
1194706f2543SmrgSProcShapeInputSelected (ClientPtr client)
1195706f2543Smrg{
1196706f2543Smrg    int    n;
1197706f2543Smrg    REQUEST (xShapeInputSelectedReq);
1198706f2543Smrg
1199706f2543Smrg    swaps (&stuff->length, n);
1200706f2543Smrg    REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
1201706f2543Smrg    swapl (&stuff->window, n);
1202706f2543Smrg    return ProcShapeInputSelected (client);
1203706f2543Smrg}
1204706f2543Smrg
1205706f2543Smrgstatic int
1206706f2543SmrgSProcShapeGetRectangles (ClientPtr client)
1207706f2543Smrg{
1208706f2543Smrg    REQUEST(xShapeGetRectanglesReq);
1209706f2543Smrg    char   n;
1210706f2543Smrg
1211706f2543Smrg    swaps (&stuff->length, n);
1212706f2543Smrg    REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
1213706f2543Smrg    swapl (&stuff->window, n);
1214706f2543Smrg    return ProcShapeGetRectangles (client);
1215706f2543Smrg}
1216706f2543Smrg
1217706f2543Smrgstatic int
1218706f2543SmrgSProcShapeDispatch (ClientPtr client)
1219706f2543Smrg{
1220706f2543Smrg    REQUEST(xReq);
1221706f2543Smrg    switch (stuff->data) {
1222706f2543Smrg    case X_ShapeQueryVersion:
1223706f2543Smrg	return SProcShapeQueryVersion (client);
1224706f2543Smrg    case X_ShapeRectangles:
1225706f2543Smrg	return SProcShapeRectangles (client);
1226706f2543Smrg    case X_ShapeMask:
1227706f2543Smrg	return SProcShapeMask (client);
1228706f2543Smrg    case X_ShapeCombine:
1229706f2543Smrg	return SProcShapeCombine (client);
1230706f2543Smrg    case X_ShapeOffset:
1231706f2543Smrg	return SProcShapeOffset (client);
1232706f2543Smrg    case X_ShapeQueryExtents:
1233706f2543Smrg	return SProcShapeQueryExtents (client);
1234706f2543Smrg    case X_ShapeSelectInput:
1235706f2543Smrg	return SProcShapeSelectInput (client);
1236706f2543Smrg    case X_ShapeInputSelected:
1237706f2543Smrg	return SProcShapeInputSelected (client);
1238706f2543Smrg    case X_ShapeGetRectangles:
1239706f2543Smrg	return SProcShapeGetRectangles (client);
1240706f2543Smrg    default:
1241706f2543Smrg	return BadRequest;
1242706f2543Smrg    }
1243706f2543Smrg}
1244706f2543Smrg
1245706f2543Smrgvoid
1246706f2543SmrgShapeExtensionInit(void)
1247706f2543Smrg{
1248706f2543Smrg    ExtensionEntry *extEntry;
1249706f2543Smrg
1250706f2543Smrg    ClientType = CreateNewResourceType(ShapeFreeClient, "ShapeClient");
1251706f2543Smrg    ShapeEventType = CreateNewResourceType(ShapeFreeEvents, "ShapeEvent");
1252706f2543Smrg    if (ClientType && ShapeEventType &&
1253706f2543Smrg	(extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0,
1254706f2543Smrg				 ProcShapeDispatch, SProcShapeDispatch,
1255706f2543Smrg				 NULL, StandardMinorOpcode)))
1256706f2543Smrg    {
1257706f2543Smrg	ShapeEventBase = extEntry->eventBase;
1258706f2543Smrg	EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent;
1259706f2543Smrg    }
1260706f2543Smrg}
1261