XShape.c revision e8a5466a
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
39static XExtensionInfo _shape_info_data;
40static XExtensionInfo *shape_info = &_shape_info_data;
41static /* const */ char *shape_extension_name = SHAPENAME;
42
43#define ShapeCheckExtension(dpy,i,val) \
44  XextCheckExtension (dpy, i, shape_extension_name, val)
45#define ShapeSimpleCheckExtension(dpy,i) \
46  XextSimpleCheckExtension (dpy, i, shape_extension_name)
47
48
49/*****************************************************************************
50 *                                                                           *
51 *			   private utility routines                          *
52 *                                                                           *
53 *****************************************************************************/
54
55static int close_display(Display *dpy, XExtCodes *codes);
56static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
57static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
58static /* const */ XExtensionHooks shape_extension_hooks = {
59    NULL,				/* create_gc */
60    NULL,				/* copy_gc */
61    NULL,				/* flush_gc */
62    NULL,				/* free_gc */
63    NULL,				/* create_font */
64    NULL,				/* free_font */
65    close_display,			/* close_display */
66    wire_to_event,			/* wire_to_event */
67    event_to_wire,			/* event_to_wire */
68    NULL,				/* error */
69    NULL,				/* error_string */
70};
71
72static XEXT_GENERATE_FIND_DISPLAY (find_display, shape_info,
73				   shape_extension_name,
74				   &shape_extension_hooks,
75				   ShapeNumberEvents, NULL)
76
77static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shape_info)
78
79
80static Bool
81wire_to_event (Display *dpy, XEvent *re, xEvent *event)
82{
83    XExtDisplayInfo *info = find_display (dpy);
84    XShapeEvent		*se;
85    xShapeNotifyEvent	*sevent;
86
87    ShapeCheckExtension (dpy, info, False);
88
89    switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
90    case ShapeNotify:
91    	se = (XShapeEvent *) re;
92	sevent = (xShapeNotifyEvent *) event;
93    	se->type = sevent->type & 0x7f;
94    	se->serial = _XSetLastRequestRead(dpy,(xGenericReply *) event);
95    	se->send_event = (sevent->type & 0x80) != 0;
96    	se->display = dpy;
97    	se->window = sevent->window;
98    	se->kind = sevent->kind;
99    	se->x = cvtINT16toInt (sevent->x);
100    	se->y = cvtINT16toInt (sevent->y);
101    	se->width = sevent->width;
102    	se->height = sevent->height;
103	se->time = sevent->time;
104	se->shaped = True;
105	if (sevent->shaped == xFalse)
106	    se->shaped = False;
107    	return True;
108    }
109    return False;
110}
111
112static Status
113event_to_wire (Display *dpy, XEvent *re, xEvent *event)
114{
115    XExtDisplayInfo *info = find_display (dpy);
116    XShapeEvent		*se;
117    xShapeNotifyEvent	*sevent;
118
119    ShapeCheckExtension (dpy, info, 0);
120
121    switch ((re->type & 0x7f) - info->codes->first_event) {
122    case ShapeNotify:
123    	se = (XShapeEvent *) re;
124	sevent = (xShapeNotifyEvent *) event;
125    	sevent->type = se->type | (se->send_event ? 0x80 : 0);
126    	sevent->sequenceNumber = se->serial & 0xffff;
127    	sevent->window = se->window;
128    	sevent->kind = se->kind;
129    	sevent->x = se->x;
130    	sevent->y = se->y;
131    	sevent->width = se->width;
132    	sevent->height = se->height;
133	sevent->time = se->time;
134    	return 1;
135    }
136    return 0;
137}
138
139
140/****************************************************************************
141 *                                                                          *
142 *			    Shape public interfaces                         *
143 *                                                                          *
144 ****************************************************************************/
145
146Bool XShapeQueryExtension (Display *dpy, int *event_basep, int *error_basep)
147{
148    XExtDisplayInfo *info = find_display (dpy);
149
150    if (XextHasExtension(info)) {
151	*event_basep = info->codes->first_event;
152	*error_basep = info->codes->first_error;
153	return True;
154    } else {
155	return False;
156    }
157}
158
159
160Status XShapeQueryVersion(
161    Display *dpy,
162    int *major_versionp,
163    int *minor_versionp)
164{
165    XExtDisplayInfo *info = find_display (dpy);
166    xShapeQueryVersionReply	    rep;
167    register xShapeQueryVersionReq  *req;
168
169    ShapeCheckExtension (dpy, info, 0);
170
171    LockDisplay (dpy);
172    GetReq (ShapeQueryVersion, req);
173    req->reqType = info->codes->major_opcode;
174    req->shapeReqType = X_ShapeQueryVersion;
175    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
176	UnlockDisplay (dpy);
177	SyncHandle ();
178	return 0;
179    }
180    *major_versionp = rep.majorVersion;
181    *minor_versionp = rep.minorVersion;
182    UnlockDisplay (dpy);
183    SyncHandle ();
184    return 1;
185}
186
187void XShapeCombineRegion(
188    register Display *dpy,
189    Window dest,
190    int destKind, int xOff, int yOff,
191    register REGION *r,
192    int op)
193{
194    XExtDisplayInfo *info = find_display (dpy);
195    register xShapeRectanglesReq *req;
196    register long nbytes;
197    register int i;
198    register XRectangle *xr, *pr;
199    register BOX *pb;
200
201    ShapeSimpleCheckExtension (dpy, info);
202
203    LockDisplay(dpy);
204    GetReq(ShapeRectangles, req);
205    xr = (XRectangle *)
206    	_XAllocScratch(dpy, (unsigned long)(r->numRects * sizeof (XRectangle)));
207    for (pr = xr, pb = r->rects, i = r->numRects; --i >= 0; pr++, pb++) {
208        pr->x = pb->x1;
209	pr->y = pb->y1;
210	pr->width = pb->x2 - pb->x1;
211	pr->height = pb->y2 - pb->y1;
212     }
213    req->reqType = info->codes->major_opcode;
214    req->shapeReqType = X_ShapeRectangles;
215    req->op = op;
216    req->ordering = YXBanded;
217    req->destKind = destKind;
218    req->dest = dest;
219    req->xOff = xOff;
220    req->yOff = yOff;
221
222    /* SIZEOF(xRectangle) will be a multiple of 4 */
223    req->length += r->numRects * (SIZEOF(xRectangle) / 4);
224
225    nbytes = r->numRects * sizeof(xRectangle);
226
227    Data16 (dpy, (short *) xr, nbytes);
228    UnlockDisplay(dpy);
229    SyncHandle();
230}
231
232
233void XShapeCombineRectangles (
234    register Display *dpy,
235    XID dest,
236    int destKind, int xOff, int yOff,
237    XRectangle *rects,
238    int n_rects,
239    int op, int ordering)
240{
241    XExtDisplayInfo *info = find_display (dpy);
242    register xShapeRectanglesReq *req;
243    register long nbytes;
244
245    ShapeSimpleCheckExtension (dpy, info);
246
247    LockDisplay(dpy);
248    GetReq(ShapeRectangles, req);
249    req->reqType = info->codes->major_opcode;
250    req->shapeReqType = X_ShapeRectangles;
251    req->op = op;
252    req->ordering = ordering;
253    req->destKind = destKind;
254    req->dest = dest;
255    req->xOff = xOff;
256    req->yOff = yOff;
257
258    /* SIZEOF(xRectangle) will be a multiple of 4 */
259    req->length += n_rects * (SIZEOF(xRectangle) / 4);
260
261    nbytes = n_rects * sizeof(xRectangle);
262
263    Data16 (dpy, (short *) rects, nbytes);
264    UnlockDisplay(dpy);
265    SyncHandle();
266}
267
268
269void XShapeCombineMask (
270    register Display *dpy,
271    XID dest,
272    int destKind,
273    int xOff, int yOff,
274    Pixmap src,
275    int op)
276{
277    XExtDisplayInfo *info = find_display (dpy);
278    register xShapeMaskReq *req;
279
280    ShapeSimpleCheckExtension (dpy, info);
281
282    LockDisplay(dpy);
283    GetReq(ShapeMask, req);
284    req->reqType = info->codes->major_opcode;
285    req->shapeReqType = X_ShapeMask;
286    req->op = op;
287    req->destKind = destKind;
288    req->dest = dest;
289    req->xOff = xOff;
290    req->yOff = yOff;
291    req->src = src;
292    UnlockDisplay(dpy);
293    SyncHandle();
294}
295
296void XShapeCombineShape (
297    register Display *dpy,
298    XID dest,
299    int destKind,
300    int xOff, int yOff,
301    XID src,
302    int srcKind,
303    int op)
304{
305    XExtDisplayInfo *info = find_display (dpy);
306    register xShapeCombineReq *req;
307
308    ShapeSimpleCheckExtension (dpy, info);
309
310    LockDisplay(dpy);
311    GetReq(ShapeCombine, req);
312    req->reqType = info->codes->major_opcode;
313    req->shapeReqType = X_ShapeCombine;
314    req->op = op;
315    req->destKind = destKind;
316    req->srcKind = srcKind;
317    req->dest = dest;
318    req->xOff = xOff;
319    req->yOff = yOff;
320    req->src = src;
321    UnlockDisplay(dpy);
322    SyncHandle();
323}
324
325void XShapeOffsetShape (
326    register Display *dpy,
327    XID dest,
328    int destKind,
329    int xOff, int yOff)
330{
331    XExtDisplayInfo *info = find_display (dpy);
332    register xShapeOffsetReq *req;
333
334    ShapeSimpleCheckExtension (dpy, info);
335
336    LockDisplay(dpy);
337    GetReq(ShapeOffset, req);
338    req->reqType = info->codes->major_opcode;
339    req->shapeReqType = X_ShapeOffset;
340    req->destKind = destKind;
341    req->dest = dest;
342    req->xOff = xOff;
343    req->yOff = yOff;
344    UnlockDisplay(dpy);
345    SyncHandle();
346}
347
348Status XShapeQueryExtents (
349    register Display *dpy,
350    Window window,
351    int *bShaped, int *xbs, int *ybs, unsigned int *wbs, unsigned int *hbs, /* RETURN */
352    int *cShaped, int *xcs, int *ycs, unsigned int *wcs, unsigned int *hcs /* RETURN */)
353{
354    XExtDisplayInfo *info = find_display (dpy);
355    xShapeQueryExtentsReply	    rep;
356    register xShapeQueryExtentsReq *req;
357
358    ShapeCheckExtension (dpy, info, 0);
359
360    LockDisplay (dpy);
361    GetReq (ShapeQueryExtents, req);
362    req->reqType = info->codes->major_opcode;
363    req->shapeReqType = X_ShapeQueryExtents;
364    req->window = window;
365    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
366	UnlockDisplay (dpy);
367	SyncHandle ();
368	return 0;
369    }
370    *bShaped = rep.boundingShaped;
371    *cShaped = rep.clipShaped;
372    *xbs = cvtINT16toInt (rep.xBoundingShape);
373    *ybs = cvtINT16toInt (rep.yBoundingShape);
374    *wbs = rep.widthBoundingShape;
375    *hbs = rep.heightBoundingShape;
376    *xcs = cvtINT16toInt (rep.xClipShape);
377    *ycs = cvtINT16toInt (rep.yClipShape);
378    *wcs = rep.widthClipShape;
379    *hcs = rep.heightClipShape;
380    UnlockDisplay (dpy);
381    SyncHandle ();
382    return 1;
383}
384
385
386void XShapeSelectInput (
387    register Display *dpy,
388    Window window,
389    unsigned long mask)
390{
391    XExtDisplayInfo *info = find_display (dpy);
392    register xShapeSelectInputReq   *req;
393
394    ShapeSimpleCheckExtension (dpy, info);
395
396    LockDisplay (dpy);
397    GetReq (ShapeSelectInput, req);
398    req->reqType = info->codes->major_opcode;
399    req->shapeReqType = X_ShapeSelectInput;
400    req->window = window;
401    if (mask & ShapeNotifyMask)
402	req->enable = xTrue;
403    else
404	req->enable = xFalse;
405    UnlockDisplay (dpy);
406    SyncHandle ();
407}
408
409unsigned long XShapeInputSelected (register Display *dpy, Window window)
410{
411    XExtDisplayInfo *info = find_display (dpy);
412    register xShapeInputSelectedReq *req;
413    xShapeInputSelectedReply	    rep;
414
415    ShapeCheckExtension (dpy, info, False);
416
417    LockDisplay (dpy);
418    GetReq (ShapeInputSelected, req);
419    req->reqType = info->codes->major_opcode;
420    req->shapeReqType = X_ShapeInputSelected;
421    req->window = window;
422    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
423	UnlockDisplay (dpy);
424	SyncHandle ();
425	return False;
426    }
427    UnlockDisplay (dpy);
428    SyncHandle ();
429    return rep.enabled ? ShapeNotifyMask : 0L;
430}
431
432
433XRectangle *XShapeGetRectangles (
434    register Display *dpy,
435    Window window,
436    int kind,
437    int *count, /* RETURN */
438    int *ordering /* RETURN */)
439{
440    XExtDisplayInfo *info = find_display (dpy);
441    register xShapeGetRectanglesReq   *req;
442    xShapeGetRectanglesReply	    rep;
443    XRectangle			    *rects;
444    xRectangle			    *xrects;
445    int				    i;
446
447    ShapeCheckExtension (dpy, info, (XRectangle *)NULL);
448
449    LockDisplay (dpy);
450    GetReq (ShapeGetRectangles, req);
451    req->reqType = info->codes->major_opcode;
452    req->shapeReqType = X_ShapeGetRectangles;
453    req->window = window;
454    req->kind = kind;
455    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
456	UnlockDisplay (dpy);
457	SyncHandle ();
458	return (XRectangle *)NULL;
459    }
460    *count = rep.nrects;
461    *ordering = rep.ordering;
462    rects = NULL;
463    if (*count) {
464	xrects = (xRectangle *) Xmalloc (*count * sizeof (xRectangle));
465	rects = (XRectangle *) Xmalloc (*count * sizeof (XRectangle));
466	if (!xrects || !rects) {
467	    if (xrects)
468		Xfree (xrects);
469	    if (rects)
470		Xfree (rects);
471	    _XEatData (dpy, *count * sizeof (xRectangle));
472	    rects = NULL;
473	    *count = 0;
474	} else {
475	    _XRead (dpy, (char *) xrects, *count * sizeof (xRectangle));
476	    for (i = 0; i < *count; i++) {
477	    	rects[i].x = (short) cvtINT16toInt (xrects[i].x);
478	    	rects[i].y = (short) cvtINT16toInt (xrects[i].y);
479	    	rects[i].width = xrects[i].width;
480	    	rects[i].height = xrects[i].height;
481	    }
482	    Xfree (xrects);
483	}
484    }
485    UnlockDisplay (dpy);
486    SyncHandle ();
487    return rects;
488}
489