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