708c20f8f9ec08c1820ba3d25efceecd7d0b6f87
[framework/uifw/xorg/lib/libxext.git] / src / XShape.c
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
39 static XExtensionInfo _shape_info_data;
40 static XExtensionInfo *shape_info = &_shape_info_data;
41 static /* 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
55 static int close_display(Display *dpy, XExtCodes *codes);
56 static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
57 static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
58 static /* 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
72 static XEXT_GENERATE_FIND_DISPLAY (find_display, shape_info,
73                                    shape_extension_name, 
74                                    &shape_extension_hooks,
75                                    ShapeNumberEvents, NULL)
76
77 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shape_info)
78
79
80 static Bool
81 wire_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
112 static Status
113 event_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
146 Bool 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
160 Status 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
187 void 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
233 void 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
269 void 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
296 void 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
325 void 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
348 Status 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
386 void 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
409 unsigned 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
433 XRectangle *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 }