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