XShape.c revision e5383a99
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 40static XExtensionInfo _shape_info_data; 41static XExtensionInfo *shape_info = &_shape_info_data; 42static 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 56static int close_display(Display *dpy, XExtCodes *codes); 57static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event); 58static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event); 59static /* 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 73static XEXT_GENERATE_FIND_DISPLAY (find_display, shape_info, 74 shape_extension_name, 75 &shape_extension_hooks, 76 ShapeNumberEvents, NULL) 77 78static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shape_info) 79 80 81static Bool 82wire_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 113static Status 114event_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 147Bool 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 161Status 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 188void 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 234void 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 270void 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 297void 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 326void 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 349Status 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 387void 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 410unsigned 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 434XRectangle *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