1 /*
2  *
3 Copyright 1989, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24  *
25  * Author:  Keith Packard, MIT X Consortium
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <X11/Xlibint.h>
32 #include <X11/Xutil.h>
33 #include <X11/Xregion.h>
34 #include <X11/extensions/Xext.h>
35 #include <X11/extensions/extutil.h>
36 #include <X11/extensions/shape.h>
37 #include <X11/extensions/shapeproto.h>
38 #include <limits.h>
39 
40 static XExtensionInfo _shape_info_data;
41 static XExtensionInfo *shape_info = &_shape_info_data;
42 static const char *shape_extension_name = SHAPENAME;
43 
44 #define ShapeCheckExtension(dpy,i,val) \
45   XextCheckExtension (dpy, i, shape_extension_name, val)
46 #define ShapeSimpleCheckExtension(dpy,i) \
47   XextSimpleCheckExtension (dpy, i, shape_extension_name)
48 
49 
50 /*****************************************************************************
51  *                                                                           *
52  *			   private utility routines                          *
53  *                                                                           *
54  *****************************************************************************/
55 
56 static int close_display(Display *dpy, XExtCodes *codes);
57 static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
58 static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
59 static /* const */ XExtensionHooks shape_extension_hooks = {
60     NULL,				/* create_gc */
61     NULL,				/* copy_gc */
62     NULL,				/* flush_gc */
63     NULL,				/* free_gc */
64     NULL,				/* create_font */
65     NULL,				/* free_font */
66     close_display,			/* close_display */
67     wire_to_event,			/* wire_to_event */
68     event_to_wire,			/* event_to_wire */
69     NULL,				/* error */
70     NULL,				/* error_string */
71 };
72 
73 static XEXT_GENERATE_FIND_DISPLAY (find_display, shape_info,
74 				   shape_extension_name,
75 				   &shape_extension_hooks,
76 				   ShapeNumberEvents, NULL)
77 
XEXT_GENERATE_CLOSE_DISPLAY(close_display,shape_info)78 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shape_info)
79 
80 
81 static Bool
82 wire_to_event (Display *dpy, XEvent *re, xEvent *event)
83 {
84     XExtDisplayInfo *info = find_display (dpy);
85     XShapeEvent		*se;
86     xShapeNotifyEvent	*sevent;
87 
88     ShapeCheckExtension (dpy, info, False);
89 
90     switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
91     case ShapeNotify:
92     	se = (XShapeEvent *) re;
93 	sevent = (xShapeNotifyEvent *) event;
94     	se->type = sevent->type & 0x7f;
95     	se->serial = _XSetLastRequestRead(dpy,(xGenericReply *) event);
96     	se->send_event = (sevent->type & 0x80) != 0;
97     	se->display = dpy;
98     	se->window = sevent->window;
99     	se->kind = sevent->kind;
100     	se->x = cvtINT16toInt (sevent->x);
101     	se->y = cvtINT16toInt (sevent->y);
102     	se->width = sevent->width;
103     	se->height = sevent->height;
104 	se->time = sevent->time;
105 	se->shaped = True;
106 	if (sevent->shaped == xFalse)
107 	    se->shaped = False;
108     	return True;
109     }
110     return False;
111 }
112 
113 static Status
event_to_wire(Display * dpy,XEvent * re,xEvent * event)114 event_to_wire (Display *dpy, XEvent *re, xEvent *event)
115 {
116     XExtDisplayInfo *info = find_display (dpy);
117     XShapeEvent		*se;
118     xShapeNotifyEvent	*sevent;
119 
120     ShapeCheckExtension (dpy, info, 0);
121 
122     switch ((re->type & 0x7f) - info->codes->first_event) {
123     case ShapeNotify:
124     	se = (XShapeEvent *) re;
125 	sevent = (xShapeNotifyEvent *) event;
126     	sevent->type = se->type | (se->send_event ? 0x80 : 0);
127     	sevent->sequenceNumber = se->serial & 0xffff;
128     	sevent->window = se->window;
129     	sevent->kind = se->kind;
130     	sevent->x = se->x;
131     	sevent->y = se->y;
132     	sevent->width = se->width;
133     	sevent->height = se->height;
134 	sevent->time = se->time;
135     	return 1;
136     }
137     return 0;
138 }
139 
140 
141 /****************************************************************************
142  *                                                                          *
143  *			    Shape public interfaces                         *
144  *                                                                          *
145  ****************************************************************************/
146 
XShapeQueryExtension(Display * dpy,int * event_basep,int * error_basep)147 Bool XShapeQueryExtension (Display *dpy, int *event_basep, int *error_basep)
148 {
149     XExtDisplayInfo *info = find_display (dpy);
150 
151     if (XextHasExtension(info)) {
152 	*event_basep = info->codes->first_event;
153 	*error_basep = info->codes->first_error;
154 	return True;
155     } else {
156 	return False;
157     }
158 }
159 
160 
XShapeQueryVersion(Display * dpy,int * major_versionp,int * minor_versionp)161 Status XShapeQueryVersion(
162     Display *dpy,
163     int *major_versionp,
164     int *minor_versionp)
165 {
166     XExtDisplayInfo *info = find_display (dpy);
167     xShapeQueryVersionReply	    rep;
168     register xShapeQueryVersionReq  *req;
169 
170     ShapeCheckExtension (dpy, info, 0);
171 
172     LockDisplay (dpy);
173     GetReq (ShapeQueryVersion, req);
174     req->reqType = info->codes->major_opcode;
175     req->shapeReqType = X_ShapeQueryVersion;
176     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
177 	UnlockDisplay (dpy);
178 	SyncHandle ();
179 	return 0;
180     }
181     *major_versionp = rep.majorVersion;
182     *minor_versionp = rep.minorVersion;
183     UnlockDisplay (dpy);
184     SyncHandle ();
185     return 1;
186 }
187 
XShapeCombineRegion(register Display * dpy,Window dest,int destKind,int xOff,int yOff,register REGION * r,int op)188 void XShapeCombineRegion(
189     register Display *dpy,
190     Window dest,
191     int destKind, int xOff, int yOff,
192     register REGION *r,
193     int op)
194 {
195     XExtDisplayInfo *info = find_display (dpy);
196     register xShapeRectanglesReq *req;
197     register long nbytes;
198     register int i;
199     register XRectangle *xr, *pr;
200     register BOX *pb;
201 
202     ShapeSimpleCheckExtension (dpy, info);
203 
204     LockDisplay(dpy);
205     GetReq(ShapeRectangles, req);
206     xr = (XRectangle *)
207     	_XAllocScratch(dpy, (unsigned long)(r->numRects * sizeof (XRectangle)));
208     for (pr = xr, pb = r->rects, i = r->numRects; --i >= 0; pr++, pb++) {
209         pr->x = pb->x1;
210 	pr->y = pb->y1;
211 	pr->width = pb->x2 - pb->x1;
212 	pr->height = pb->y2 - pb->y1;
213      }
214     req->reqType = info->codes->major_opcode;
215     req->shapeReqType = X_ShapeRectangles;
216     req->op = op;
217     req->ordering = YXBanded;
218     req->destKind = destKind;
219     req->dest = dest;
220     req->xOff = xOff;
221     req->yOff = yOff;
222 
223     /* SIZEOF(xRectangle) will be a multiple of 4 */
224     req->length += r->numRects * (SIZEOF(xRectangle) / 4);
225 
226     nbytes = r->numRects * sizeof(xRectangle);
227 
228     Data16 (dpy, (short *) xr, nbytes);
229     UnlockDisplay(dpy);
230     SyncHandle();
231 }
232 
233 
XShapeCombineRectangles(register Display * dpy,XID dest,int destKind,int xOff,int yOff,XRectangle * rects,int n_rects,int op,int ordering)234 void XShapeCombineRectangles (
235     register Display *dpy,
236     XID dest,
237     int destKind, int xOff, int yOff,
238     XRectangle *rects,
239     int n_rects,
240     int op, int ordering)
241 {
242     XExtDisplayInfo *info = find_display (dpy);
243     register xShapeRectanglesReq *req;
244     register long nbytes;
245 
246     ShapeSimpleCheckExtension (dpy, info);
247 
248     LockDisplay(dpy);
249     GetReq(ShapeRectangles, req);
250     req->reqType = info->codes->major_opcode;
251     req->shapeReqType = X_ShapeRectangles;
252     req->op = op;
253     req->ordering = ordering;
254     req->destKind = destKind;
255     req->dest = dest;
256     req->xOff = xOff;
257     req->yOff = yOff;
258 
259     /* SIZEOF(xRectangle) will be a multiple of 4 */
260     req->length += n_rects * (SIZEOF(xRectangle) / 4);
261 
262     nbytes = n_rects * sizeof(xRectangle);
263 
264     Data16 (dpy, (short *) rects, nbytes);
265     UnlockDisplay(dpy);
266     SyncHandle();
267 }
268 
269 
XShapeCombineMask(register Display * dpy,XID dest,int destKind,int xOff,int yOff,Pixmap src,int op)270 void XShapeCombineMask (
271     register Display *dpy,
272     XID dest,
273     int destKind,
274     int xOff, int yOff,
275     Pixmap src,
276     int op)
277 {
278     XExtDisplayInfo *info = find_display (dpy);
279     register xShapeMaskReq *req;
280 
281     ShapeSimpleCheckExtension (dpy, info);
282 
283     LockDisplay(dpy);
284     GetReq(ShapeMask, req);
285     req->reqType = info->codes->major_opcode;
286     req->shapeReqType = X_ShapeMask;
287     req->op = op;
288     req->destKind = destKind;
289     req->dest = dest;
290     req->xOff = xOff;
291     req->yOff = yOff;
292     req->src = src;
293     UnlockDisplay(dpy);
294     SyncHandle();
295 }
296 
XShapeCombineShape(register Display * dpy,XID dest,int destKind,int xOff,int yOff,XID src,int srcKind,int op)297 void XShapeCombineShape (
298     register Display *dpy,
299     XID dest,
300     int destKind,
301     int xOff, int yOff,
302     XID src,
303     int srcKind,
304     int op)
305 {
306     XExtDisplayInfo *info = find_display (dpy);
307     register xShapeCombineReq *req;
308 
309     ShapeSimpleCheckExtension (dpy, info);
310 
311     LockDisplay(dpy);
312     GetReq(ShapeCombine, req);
313     req->reqType = info->codes->major_opcode;
314     req->shapeReqType = X_ShapeCombine;
315     req->op = op;
316     req->destKind = destKind;
317     req->srcKind = srcKind;
318     req->dest = dest;
319     req->xOff = xOff;
320     req->yOff = yOff;
321     req->src = src;
322     UnlockDisplay(dpy);
323     SyncHandle();
324 }
325 
XShapeOffsetShape(register Display * dpy,XID dest,int destKind,int xOff,int yOff)326 void XShapeOffsetShape (
327     register Display *dpy,
328     XID dest,
329     int destKind,
330     int xOff, int yOff)
331 {
332     XExtDisplayInfo *info = find_display (dpy);
333     register xShapeOffsetReq *req;
334 
335     ShapeSimpleCheckExtension (dpy, info);
336 
337     LockDisplay(dpy);
338     GetReq(ShapeOffset, req);
339     req->reqType = info->codes->major_opcode;
340     req->shapeReqType = X_ShapeOffset;
341     req->destKind = destKind;
342     req->dest = dest;
343     req->xOff = xOff;
344     req->yOff = yOff;
345     UnlockDisplay(dpy);
346     SyncHandle();
347 }
348 
XShapeQueryExtents(register Display * dpy,Window window,int * bShaped,int * xbs,int * ybs,unsigned int * wbs,unsigned int * hbs,int * cShaped,int * xcs,int * ycs,unsigned int * wcs,unsigned int * hcs)349 Status XShapeQueryExtents (
350     register Display *dpy,
351     Window window,
352     int *bShaped, int *xbs, int *ybs, unsigned int *wbs, unsigned int *hbs, /* RETURN */
353     int *cShaped, int *xcs, int *ycs, unsigned int *wcs, unsigned int *hcs /* RETURN */)
354 {
355     XExtDisplayInfo *info = find_display (dpy);
356     xShapeQueryExtentsReply	    rep;
357     register xShapeQueryExtentsReq *req;
358 
359     ShapeCheckExtension (dpy, info, 0);
360 
361     LockDisplay (dpy);
362     GetReq (ShapeQueryExtents, req);
363     req->reqType = info->codes->major_opcode;
364     req->shapeReqType = X_ShapeQueryExtents;
365     req->window = window;
366     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
367 	UnlockDisplay (dpy);
368 	SyncHandle ();
369 	return 0;
370     }
371     *bShaped = rep.boundingShaped;
372     *cShaped = rep.clipShaped;
373     *xbs = cvtINT16toInt (rep.xBoundingShape);
374     *ybs = cvtINT16toInt (rep.yBoundingShape);
375     *wbs = rep.widthBoundingShape;
376     *hbs = rep.heightBoundingShape;
377     *xcs = cvtINT16toInt (rep.xClipShape);
378     *ycs = cvtINT16toInt (rep.yClipShape);
379     *wcs = rep.widthClipShape;
380     *hcs = rep.heightClipShape;
381     UnlockDisplay (dpy);
382     SyncHandle ();
383     return 1;
384 }
385 
386 
XShapeSelectInput(register Display * dpy,Window window,unsigned long mask)387 void XShapeSelectInput (
388     register Display *dpy,
389     Window window,
390     unsigned long mask)
391 {
392     XExtDisplayInfo *info = find_display (dpy);
393     register xShapeSelectInputReq   *req;
394 
395     ShapeSimpleCheckExtension (dpy, info);
396 
397     LockDisplay (dpy);
398     GetReq (ShapeSelectInput, req);
399     req->reqType = info->codes->major_opcode;
400     req->shapeReqType = X_ShapeSelectInput;
401     req->window = window;
402     if (mask & ShapeNotifyMask)
403 	req->enable = xTrue;
404     else
405 	req->enable = xFalse;
406     UnlockDisplay (dpy);
407     SyncHandle ();
408 }
409 
XShapeInputSelected(register Display * dpy,Window window)410 unsigned long XShapeInputSelected (register Display *dpy, Window window)
411 {
412     XExtDisplayInfo *info = find_display (dpy);
413     register xShapeInputSelectedReq *req;
414     xShapeInputSelectedReply	    rep;
415 
416     ShapeCheckExtension (dpy, info, False);
417 
418     LockDisplay (dpy);
419     GetReq (ShapeInputSelected, req);
420     req->reqType = info->codes->major_opcode;
421     req->shapeReqType = X_ShapeInputSelected;
422     req->window = window;
423     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
424 	UnlockDisplay (dpy);
425 	SyncHandle ();
426 	return False;
427     }
428     UnlockDisplay (dpy);
429     SyncHandle ();
430     return rep.enabled ? ShapeNotifyMask : 0L;
431 }
432 
433 
XShapeGetRectangles(register Display * dpy,Window window,int kind,int * count,int * ordering)434 XRectangle *XShapeGetRectangles (
435     register Display *dpy,
436     Window window,
437     int kind,
438     int *count, /* RETURN */
439     int *ordering /* RETURN */)
440 {
441     XExtDisplayInfo *info = find_display (dpy);
442     register xShapeGetRectanglesReq   *req;
443     xShapeGetRectanglesReply	    rep;
444     XRectangle			    *rects;
445     xRectangle			    *xrects;
446     unsigned int		    i;
447 
448     ShapeCheckExtension (dpy, info, (XRectangle *)NULL);
449 
450     LockDisplay (dpy);
451     GetReq (ShapeGetRectangles, req);
452     req->reqType = info->codes->major_opcode;
453     req->shapeReqType = X_ShapeGetRectangles;
454     req->window = window;
455     req->kind = kind;
456     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
457 	UnlockDisplay (dpy);
458 	SyncHandle ();
459 	return (XRectangle *)NULL;
460     }
461     *count = rep.nrects;
462     *ordering = rep.ordering;
463     rects = NULL;
464     if (rep.nrects) {
465 	if (rep.nrects < (INT_MAX / sizeof (XRectangle))) {
466 	    xrects = Xmalloc (rep.nrects * sizeof (xRectangle));
467 	    rects = Xmalloc (rep.nrects * sizeof (XRectangle));
468 	} else {
469 	    xrects = NULL;
470 	    rects = NULL;
471 	}
472 	if (!xrects || !rects) {
473 	    Xfree (xrects);
474 	    Xfree (rects);
475 	    _XEatDataWords (dpy, rep.length);
476 	    rects = NULL;
477 	    *count = 0;
478 	} else {
479 	    _XRead (dpy, (char *) xrects, rep.nrects * sizeof (xRectangle));
480 	    for (i = 0; i < rep.nrects; i++) {
481 	    	rects[i].x = (short) cvtINT16toInt (xrects[i].x);
482 	    	rects[i].y = (short) cvtINT16toInt (xrects[i].y);
483 	    	rects[i].width = xrects[i].width;
484 	    	rects[i].height = xrects[i].height;
485 	    }
486 	    Xfree (xrects);
487 	}
488     }
489     UnlockDisplay (dpy);
490     SyncHandle ();
491     return rects;
492 }
493