XShape.c revision e5383a99
1/*
2 *
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in 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
40static XExtensionInfo _shape_info_data;
41static XExtensionInfo *shape_info = &_shape_info_data;
42static 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
56static int close_display(Display *dpy, XExtCodes *codes);
57static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
58static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
59static /* 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
73static XEXT_GENERATE_FIND_DISPLAY (find_display, shape_info,
74				   shape_extension_name,
75				   &shape_extension_hooks,
76				   ShapeNumberEvents, NULL)
77
78static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shape_info)
79
80
81static Bool
82wire_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
113static Status
114event_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
147Bool 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
161Status 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
188void 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
234void 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
270void 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
297void 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
326void 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
349Status 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
387void 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
410unsigned 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
434XRectangle *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