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 #include <limits.h>
39
40 static XExtensionInfo _shape_info_data;
41 static XExtensionInfo *shape_info = &_shape_info_data;
42 static 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
56 static int close_display(Display *dpy, XExtCodes *codes);
57 static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
58 static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
59 static /* 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
73 static XEXT_GENERATE_FIND_DISPLAY (find_display, shape_info,
74 shape_extension_name,
75 &shape_extension_hooks,
76 ShapeNumberEvents, NULL)
77
XEXT_GENERATE_CLOSE_DISPLAY(close_display,shape_info)78 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shape_info)
79
80
81 static Bool
82 wire_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
113 static Status
event_to_wire(Display * dpy,XEvent * re,xEvent * event)114 event_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
XShapeQueryExtension(Display * dpy,int * event_basep,int * error_basep)147 Bool 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
XShapeQueryVersion(Display * dpy,int * major_versionp,int * minor_versionp)161 Status 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
XShapeCombineRegion(register Display * dpy,Window dest,int destKind,int xOff,int yOff,register REGION * r,int op)188 void 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
XShapeCombineRectangles(register Display * dpy,XID dest,int destKind,int xOff,int yOff,XRectangle * rects,int n_rects,int op,int ordering)234 void 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
XShapeCombineMask(register Display * dpy,XID dest,int destKind,int xOff,int yOff,Pixmap src,int op)270 void 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
XShapeCombineShape(register Display * dpy,XID dest,int destKind,int xOff,int yOff,XID src,int srcKind,int op)297 void 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
XShapeOffsetShape(register Display * dpy,XID dest,int destKind,int xOff,int yOff)326 void 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
XShapeQueryExtents(register Display * dpy,Window window,int * bShaped,int * xbs,int * ybs,unsigned int * wbs,unsigned int * hbs,int * cShaped,int * xcs,int * ycs,unsigned int * wcs,unsigned int * hcs)349 Status 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
XShapeSelectInput(register Display * dpy,Window window,unsigned long mask)387 void 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
XShapeInputSelected(register Display * dpy,Window window)410 unsigned 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
XShapeGetRectangles(register Display * dpy,Window window,int kind,int * count,int * ordering)434 XRectangle *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