shape.c revision 7e31ba66
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********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#include <stdlib.h> 32 33#include <X11/X.h> 34#include <X11/Xproto.h> 35#include "misc.h" 36#include "os.h" 37#include "windowstr.h" 38#include "scrnintstr.h" 39#include "pixmapstr.h" 40#include "extnsionst.h" 41#include "dixstruct.h" 42#include "resource.h" 43#include "opaque.h" 44#include <X11/extensions/shapeproto.h> 45#include "regionstr.h" 46#include "gcstruct.h" 47#include "extinit.h" 48#include "protocol-versions.h" 49 50typedef RegionPtr (*CreateDftPtr) (WindowPtr /* pWin */ 51 ); 52 53static int ShapeFreeClient(void * /* data */ , 54 XID /* id */ 55 ); 56static int ShapeFreeEvents(void * /* data */ , 57 XID /* id */ 58 ); 59static void SShapeNotifyEvent(xShapeNotifyEvent * /* from */ , 60 xShapeNotifyEvent * /* to */ 61 ); 62 63/* SendShapeNotify, CreateBoundingShape and CreateClipShape are used 64 * externally by the Xfixes extension and are now defined in window.h 65 */ 66 67#ifdef PANORAMIX 68#include "panoramiX.h" 69#include "panoramiXsrv.h" 70#endif 71 72static int ShapeEventBase = 0; 73static RESTYPE ClientType, ShapeEventType; /* resource types for event masks */ 74 75/* 76 * each window has a list of clients requesting 77 * ShapeNotify events. Each client has a resource 78 * for each window it selects ShapeNotify input for, 79 * this resource is used to delete the ShapeNotifyRec 80 * entry from the per-window queue. 81 */ 82 83typedef struct _ShapeEvent *ShapeEventPtr; 84 85typedef struct _ShapeEvent { 86 ShapeEventPtr next; 87 ClientPtr client; 88 WindowPtr window; 89 XID clientResource; 90} ShapeEventRec; 91 92/**************** 93 * ShapeExtensionInit 94 * 95 * Called from InitExtensions in main() or from QueryExtension() if the 96 * extension is dynamically loaded. 97 * 98 ****************/ 99 100static int 101RegionOperate(ClientPtr client, 102 WindowPtr pWin, 103 int kind, 104 RegionPtr *destRgnp, 105 RegionPtr srcRgn, int op, int xoff, int yoff, CreateDftPtr create) 106{ 107 if (srcRgn && (xoff || yoff)) 108 RegionTranslate(srcRgn, xoff, yoff); 109 if (!pWin->parent) { 110 if (srcRgn) 111 RegionDestroy(srcRgn); 112 return Success; 113 } 114 115 /* May/30/2001: 116 * The shape.PS specs say if src is None, existing shape is to be 117 * removed (and so the op-code has no meaning in such removal); 118 * see shape.PS, page 3, ShapeMask. 119 */ 120 if (srcRgn == NULL) { 121 if (*destRgnp != NULL) { 122 RegionDestroy(*destRgnp); 123 *destRgnp = 0; 124 /* go on to remove shape and generate ShapeNotify */ 125 } 126 else { 127 /* May/30/2001: 128 * The target currently has no shape in effect, so nothing to 129 * do here. The specs say that ShapeNotify is generated whenever 130 * the client region is "modified"; since no modification is done 131 * here, we do not generate that event. The specs does not say 132 * "it is an error to request removal when there is no shape in 133 * effect", so we return good status. 134 */ 135 return Success; 136 } 137 } 138 else 139 switch (op) { 140 case ShapeSet: 141 if (*destRgnp) 142 RegionDestroy(*destRgnp); 143 *destRgnp = srcRgn; 144 srcRgn = 0; 145 break; 146 case ShapeUnion: 147 if (*destRgnp) 148 RegionUnion(*destRgnp, *destRgnp, srcRgn); 149 break; 150 case ShapeIntersect: 151 if (*destRgnp) 152 RegionIntersect(*destRgnp, *destRgnp, srcRgn); 153 else { 154 *destRgnp = srcRgn; 155 srcRgn = 0; 156 } 157 break; 158 case ShapeSubtract: 159 if (!*destRgnp) 160 *destRgnp = (*create) (pWin); 161 RegionSubtract(*destRgnp, *destRgnp, srcRgn); 162 break; 163 case ShapeInvert: 164 if (!*destRgnp) 165 *destRgnp = RegionCreate((BoxPtr) 0, 0); 166 else 167 RegionSubtract(*destRgnp, srcRgn, *destRgnp); 168 break; 169 default: 170 client->errorValue = op; 171 return BadValue; 172 } 173 if (srcRgn) 174 RegionDestroy(srcRgn); 175 (*pWin->drawable.pScreen->SetShape) (pWin, kind); 176 SendShapeNotify(pWin, kind); 177 return Success; 178} 179 180RegionPtr 181CreateBoundingShape(WindowPtr pWin) 182{ 183 BoxRec extents; 184 185 extents.x1 = -wBorderWidth(pWin); 186 extents.y1 = -wBorderWidth(pWin); 187 extents.x2 = pWin->drawable.width + wBorderWidth(pWin); 188 extents.y2 = pWin->drawable.height + wBorderWidth(pWin); 189 return RegionCreate(&extents, 1); 190} 191 192RegionPtr 193CreateClipShape(WindowPtr pWin) 194{ 195 BoxRec extents; 196 197 extents.x1 = 0; 198 extents.y1 = 0; 199 extents.x2 = pWin->drawable.width; 200 extents.y2 = pWin->drawable.height; 201 return RegionCreate(&extents, 1); 202} 203 204static int 205ProcShapeQueryVersion(ClientPtr client) 206{ 207 xShapeQueryVersionReply rep = { 208 .type = X_Reply, 209 .sequenceNumber = client->sequence, 210 .length = 0, 211 .majorVersion = SERVER_SHAPE_MAJOR_VERSION, 212 .minorVersion = SERVER_SHAPE_MINOR_VERSION 213 }; 214 215 REQUEST_SIZE_MATCH(xShapeQueryVersionReq); 216 217 if (client->swapped) { 218 swaps(&rep.sequenceNumber); 219 swapl(&rep.length); 220 swaps(&rep.majorVersion); 221 swaps(&rep.minorVersion); 222 } 223 WriteToClient(client, sizeof(xShapeQueryVersionReply), &rep); 224 return Success; 225} 226 227/***************** 228 * ProcShapeRectangles 229 * 230 *****************/ 231 232static int 233ProcShapeRectangles(ClientPtr client) 234{ 235 WindowPtr pWin; 236 237 REQUEST(xShapeRectanglesReq); 238 xRectangle *prects; 239 int nrects, ctype, rc; 240 RegionPtr srcRgn; 241 RegionPtr *destRgn; 242 CreateDftPtr createDefault; 243 244 REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq); 245 UpdateCurrentTime(); 246 rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); 247 if (rc != Success) 248 return rc; 249 switch (stuff->destKind) { 250 case ShapeBounding: 251 createDefault = CreateBoundingShape; 252 break; 253 case ShapeClip: 254 createDefault = CreateClipShape; 255 break; 256 case ShapeInput: 257 createDefault = CreateBoundingShape; 258 break; 259 default: 260 client->errorValue = stuff->destKind; 261 return BadValue; 262 } 263 if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && 264 (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) { 265 client->errorValue = stuff->ordering; 266 return BadValue; 267 } 268 nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq)); 269 if (nrects & 4) 270 return BadLength; 271 nrects >>= 3; 272 prects = (xRectangle *) &stuff[1]; 273 ctype = VerifyRectOrder(nrects, prects, (int) stuff->ordering); 274 if (ctype < 0) 275 return BadMatch; 276 srcRgn = RegionFromRects(nrects, prects, ctype); 277 278 if (!pWin->optional) 279 MakeWindowOptional(pWin); 280 switch (stuff->destKind) { 281 case ShapeBounding: 282 destRgn = &pWin->optional->boundingShape; 283 break; 284 case ShapeClip: 285 destRgn = &pWin->optional->clipShape; 286 break; 287 case ShapeInput: 288 destRgn = &pWin->optional->inputShape; 289 break; 290 default: 291 return BadValue; 292 } 293 294 return RegionOperate(client, pWin, (int) stuff->destKind, 295 destRgn, srcRgn, (int) stuff->op, 296 stuff->xOff, stuff->yOff, createDefault); 297} 298 299#ifdef PANORAMIX 300static int 301ProcPanoramiXShapeRectangles(ClientPtr client) 302{ 303 REQUEST(xShapeRectanglesReq); 304 PanoramiXRes *win; 305 int j, result; 306 307 REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq); 308 309 result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW, 310 client, DixWriteAccess); 311 if (result != Success) 312 return result; 313 314 FOR_NSCREENS(j) { 315 stuff->dest = win->info[j].id; 316 result = ProcShapeRectangles(client); 317 if (result != Success) 318 break; 319 } 320 return result; 321} 322#endif 323 324/************** 325 * ProcShapeMask 326 **************/ 327 328static int 329ProcShapeMask(ClientPtr client) 330{ 331 WindowPtr pWin; 332 ScreenPtr pScreen; 333 334 REQUEST(xShapeMaskReq); 335 RegionPtr srcRgn; 336 RegionPtr *destRgn; 337 PixmapPtr pPixmap; 338 CreateDftPtr createDefault; 339 int rc; 340 341 REQUEST_SIZE_MATCH(xShapeMaskReq); 342 UpdateCurrentTime(); 343 rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); 344 if (rc != Success) 345 return rc; 346 switch (stuff->destKind) { 347 case ShapeBounding: 348 createDefault = CreateBoundingShape; 349 break; 350 case ShapeClip: 351 createDefault = CreateClipShape; 352 break; 353 case ShapeInput: 354 createDefault = CreateBoundingShape; 355 break; 356 default: 357 client->errorValue = stuff->destKind; 358 return BadValue; 359 } 360 pScreen = pWin->drawable.pScreen; 361 if (stuff->src == None) 362 srcRgn = 0; 363 else { 364 rc = dixLookupResourceByType((void **) &pPixmap, stuff->src, 365 RT_PIXMAP, client, DixReadAccess); 366 if (rc != Success) 367 return rc; 368 if (pPixmap->drawable.pScreen != pScreen || 369 pPixmap->drawable.depth != 1) 370 return BadMatch; 371 srcRgn = BitmapToRegion(pScreen, pPixmap); 372 if (!srcRgn) 373 return BadAlloc; 374 } 375 376 if (!pWin->optional) 377 MakeWindowOptional(pWin); 378 switch (stuff->destKind) { 379 case ShapeBounding: 380 destRgn = &pWin->optional->boundingShape; 381 break; 382 case ShapeClip: 383 destRgn = &pWin->optional->clipShape; 384 break; 385 case ShapeInput: 386 destRgn = &pWin->optional->inputShape; 387 break; 388 default: 389 return BadValue; 390 } 391 392 return RegionOperate(client, pWin, (int) stuff->destKind, 393 destRgn, srcRgn, (int) stuff->op, 394 stuff->xOff, stuff->yOff, createDefault); 395} 396 397#ifdef PANORAMIX 398static int 399ProcPanoramiXShapeMask(ClientPtr client) 400{ 401 REQUEST(xShapeMaskReq); 402 PanoramiXRes *win, *pmap; 403 int j, result; 404 405 REQUEST_SIZE_MATCH(xShapeMaskReq); 406 407 result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW, 408 client, DixWriteAccess); 409 if (result != Success) 410 return result; 411 412 if (stuff->src != None) { 413 result = dixLookupResourceByType((void **) &pmap, stuff->src, 414 XRT_PIXMAP, client, DixReadAccess); 415 if (result != Success) 416 return result; 417 } 418 else 419 pmap = NULL; 420 421 FOR_NSCREENS(j) { 422 stuff->dest = win->info[j].id; 423 if (pmap) 424 stuff->src = pmap->info[j].id; 425 result = ProcShapeMask(client); 426 if (result != Success) 427 break; 428 } 429 return result; 430} 431#endif 432 433/************ 434 * ProcShapeCombine 435 ************/ 436 437static int 438ProcShapeCombine(ClientPtr client) 439{ 440 WindowPtr pSrcWin, pDestWin; 441 442 REQUEST(xShapeCombineReq); 443 RegionPtr srcRgn; 444 RegionPtr *destRgn; 445 CreateDftPtr createDefault; 446 CreateDftPtr createSrc; 447 RegionPtr tmp; 448 int rc; 449 450 REQUEST_SIZE_MATCH(xShapeCombineReq); 451 UpdateCurrentTime(); 452 rc = dixLookupWindow(&pDestWin, stuff->dest, client, DixSetAttrAccess); 453 if (rc != Success) 454 return rc; 455 if (!pDestWin->optional) 456 MakeWindowOptional(pDestWin); 457 switch (stuff->destKind) { 458 case ShapeBounding: 459 createDefault = CreateBoundingShape; 460 break; 461 case ShapeClip: 462 createDefault = CreateClipShape; 463 break; 464 case ShapeInput: 465 createDefault = CreateBoundingShape; 466 break; 467 default: 468 client->errorValue = stuff->destKind; 469 return BadValue; 470 } 471 472 rc = dixLookupWindow(&pSrcWin, stuff->src, client, DixGetAttrAccess); 473 if (rc != Success) 474 return rc; 475 switch (stuff->srcKind) { 476 case ShapeBounding: 477 srcRgn = wBoundingShape(pSrcWin); 478 createSrc = CreateBoundingShape; 479 break; 480 case ShapeClip: 481 srcRgn = wClipShape(pSrcWin); 482 createSrc = CreateClipShape; 483 break; 484 case ShapeInput: 485 srcRgn = wInputShape(pSrcWin); 486 createSrc = CreateBoundingShape; 487 break; 488 default: 489 client->errorValue = stuff->srcKind; 490 return BadValue; 491 } 492 if (pSrcWin->drawable.pScreen != pDestWin->drawable.pScreen) { 493 return BadMatch; 494 } 495 496 if (srcRgn) { 497 tmp = RegionCreate((BoxPtr) 0, 0); 498 RegionCopy(tmp, srcRgn); 499 srcRgn = tmp; 500 } 501 else 502 srcRgn = (*createSrc) (pSrcWin); 503 504 if (!pDestWin->optional) 505 MakeWindowOptional(pDestWin); 506 switch (stuff->destKind) { 507 case ShapeBounding: 508 destRgn = &pDestWin->optional->boundingShape; 509 break; 510 case ShapeClip: 511 destRgn = &pDestWin->optional->clipShape; 512 break; 513 case ShapeInput: 514 destRgn = &pDestWin->optional->inputShape; 515 break; 516 default: 517 return BadValue; 518 } 519 520 return RegionOperate(client, pDestWin, (int) stuff->destKind, 521 destRgn, srcRgn, (int) stuff->op, 522 stuff->xOff, stuff->yOff, createDefault); 523} 524 525#ifdef PANORAMIX 526static int 527ProcPanoramiXShapeCombine(ClientPtr client) 528{ 529 REQUEST(xShapeCombineReq); 530 PanoramiXRes *win, *win2; 531 int j, result; 532 533 REQUEST_AT_LEAST_SIZE(xShapeCombineReq); 534 535 result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW, 536 client, DixWriteAccess); 537 if (result != Success) 538 return result; 539 540 result = dixLookupResourceByType((void **) &win2, stuff->src, XRT_WINDOW, 541 client, DixReadAccess); 542 if (result != Success) 543 return result; 544 545 FOR_NSCREENS(j) { 546 stuff->dest = win->info[j].id; 547 stuff->src = win2->info[j].id; 548 result = ProcShapeCombine(client); 549 if (result != Success) 550 break; 551 } 552 return result; 553} 554#endif 555 556/************* 557 * ProcShapeOffset 558 *************/ 559 560static int 561ProcShapeOffset(ClientPtr client) 562{ 563 WindowPtr pWin; 564 565 REQUEST(xShapeOffsetReq); 566 RegionPtr srcRgn; 567 int rc; 568 569 REQUEST_SIZE_MATCH(xShapeOffsetReq); 570 UpdateCurrentTime(); 571 rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); 572 if (rc != Success) 573 return rc; 574 switch (stuff->destKind) { 575 case ShapeBounding: 576 srcRgn = wBoundingShape(pWin); 577 break; 578 case ShapeClip: 579 srcRgn = wClipShape(pWin); 580 break; 581 case ShapeInput: 582 srcRgn = wInputShape(pWin); 583 break; 584 default: 585 client->errorValue = stuff->destKind; 586 return BadValue; 587 } 588 if (srcRgn) { 589 RegionTranslate(srcRgn, stuff->xOff, stuff->yOff); 590 (*pWin->drawable.pScreen->SetShape) (pWin, stuff->destKind); 591 } 592 SendShapeNotify(pWin, (int) stuff->destKind); 593 return Success; 594} 595 596#ifdef PANORAMIX 597static int 598ProcPanoramiXShapeOffset(ClientPtr client) 599{ 600 REQUEST(xShapeOffsetReq); 601 PanoramiXRes *win; 602 int j, result; 603 604 REQUEST_AT_LEAST_SIZE(xShapeOffsetReq); 605 606 result = dixLookupResourceByType((void **) &win, stuff->dest, XRT_WINDOW, 607 client, DixWriteAccess); 608 if (result != Success) 609 return result; 610 611 FOR_NSCREENS(j) { 612 stuff->dest = win->info[j].id; 613 result = ProcShapeOffset(client); 614 if (result != Success) 615 break; 616 } 617 return result; 618} 619#endif 620 621static int 622ProcShapeQueryExtents(ClientPtr client) 623{ 624 REQUEST(xShapeQueryExtentsReq); 625 WindowPtr pWin; 626 xShapeQueryExtentsReply rep; 627 BoxRec extents, *pExtents; 628 int rc; 629 RegionPtr region; 630 631 REQUEST_SIZE_MATCH(xShapeQueryExtentsReq); 632 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 633 if (rc != Success) 634 return rc; 635 rep = (xShapeQueryExtentsReply) { 636 .type = X_Reply, 637 .sequenceNumber = client->sequence, 638 .length = 0, 639 .boundingShaped = (wBoundingShape(pWin) != 0), 640 .clipShaped = (wClipShape(pWin) != 0) 641 }; 642 if ((region = wBoundingShape(pWin))) { 643 /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ 644 pExtents = RegionExtents(region); 645 extents = *pExtents; 646 } 647 else { 648 extents.x1 = -wBorderWidth(pWin); 649 extents.y1 = -wBorderWidth(pWin); 650 extents.x2 = pWin->drawable.width + wBorderWidth(pWin); 651 extents.y2 = pWin->drawable.height + wBorderWidth(pWin); 652 } 653 rep.xBoundingShape = extents.x1; 654 rep.yBoundingShape = extents.y1; 655 rep.widthBoundingShape = extents.x2 - extents.x1; 656 rep.heightBoundingShape = extents.y2 - extents.y1; 657 if ((region = wClipShape(pWin))) { 658 /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ 659 pExtents = RegionExtents(region); 660 extents = *pExtents; 661 } 662 else { 663 extents.x1 = 0; 664 extents.y1 = 0; 665 extents.x2 = pWin->drawable.width; 666 extents.y2 = pWin->drawable.height; 667 } 668 rep.xClipShape = extents.x1; 669 rep.yClipShape = extents.y1; 670 rep.widthClipShape = extents.x2 - extents.x1; 671 rep.heightClipShape = extents.y2 - extents.y1; 672 if (client->swapped) { 673 swaps(&rep.sequenceNumber); 674 swapl(&rep.length); 675 swaps(&rep.xBoundingShape); 676 swaps(&rep.yBoundingShape); 677 swaps(&rep.widthBoundingShape); 678 swaps(&rep.heightBoundingShape); 679 swaps(&rep.xClipShape); 680 swaps(&rep.yClipShape); 681 swaps(&rep.widthClipShape); 682 swaps(&rep.heightClipShape); 683 } 684 WriteToClient(client, sizeof(xShapeQueryExtentsReply), &rep); 685 return Success; 686} 687 688 /*ARGSUSED*/ static int 689ShapeFreeClient(void *data, XID id) 690{ 691 ShapeEventPtr pShapeEvent; 692 WindowPtr pWin; 693 ShapeEventPtr *pHead, pCur, pPrev; 694 int rc; 695 696 pShapeEvent = (ShapeEventPtr) data; 697 pWin = pShapeEvent->window; 698 rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id, 699 ShapeEventType, serverClient, DixReadAccess); 700 if (rc == Success) { 701 pPrev = 0; 702 for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur = pCur->next) 703 pPrev = pCur; 704 if (pCur) { 705 if (pPrev) 706 pPrev->next = pShapeEvent->next; 707 else 708 *pHead = pShapeEvent->next; 709 } 710 } 711 free((void *) pShapeEvent); 712 return 1; 713} 714 715 /*ARGSUSED*/ static int 716ShapeFreeEvents(void *data, XID id) 717{ 718 ShapeEventPtr *pHead, pCur, pNext; 719 720 pHead = (ShapeEventPtr *) data; 721 for (pCur = *pHead; pCur; pCur = pNext) { 722 pNext = pCur->next; 723 FreeResource(pCur->clientResource, ClientType); 724 free((void *) pCur); 725 } 726 free((void *) pHead); 727 return 1; 728} 729 730static int 731ProcShapeSelectInput(ClientPtr client) 732{ 733 REQUEST(xShapeSelectInputReq); 734 WindowPtr pWin; 735 ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead; 736 XID clientResource; 737 int rc; 738 739 REQUEST_SIZE_MATCH(xShapeSelectInputReq); 740 rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess); 741 if (rc != Success) 742 return rc; 743 rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id, 744 ShapeEventType, client, DixWriteAccess); 745 if (rc != Success && rc != BadValue) 746 return rc; 747 748 switch (stuff->enable) { 749 case xTrue: 750 if (pHead) { 751 752 /* check for existing entry. */ 753 for (pShapeEvent = *pHead; 754 pShapeEvent; pShapeEvent = pShapeEvent->next) { 755 if (pShapeEvent->client == client) 756 return Success; 757 } 758 } 759 760 /* build the entry */ 761 pNewShapeEvent = malloc(sizeof(ShapeEventRec)); 762 if (!pNewShapeEvent) 763 return BadAlloc; 764 pNewShapeEvent->next = 0; 765 pNewShapeEvent->client = client; 766 pNewShapeEvent->window = pWin; 767 /* 768 * add a resource that will be deleted when 769 * the client goes away 770 */ 771 clientResource = FakeClientID(client->index); 772 pNewShapeEvent->clientResource = clientResource; 773 if (!AddResource(clientResource, ClientType, (void *) pNewShapeEvent)) 774 return BadAlloc; 775 /* 776 * create a resource to contain a void *to the list 777 * of clients selecting input. This must be indirect as 778 * the list may be arbitrarily rearranged which cannot be 779 * done through the resource database. 780 */ 781 if (!pHead) { 782 pHead = malloc(sizeof(ShapeEventPtr)); 783 if (!pHead || 784 !AddResource(pWin->drawable.id, ShapeEventType, 785 (void *) pHead)) { 786 FreeResource(clientResource, RT_NONE); 787 return BadAlloc; 788 } 789 *pHead = 0; 790 } 791 pNewShapeEvent->next = *pHead; 792 *pHead = pNewShapeEvent; 793 break; 794 case xFalse: 795 /* delete the interest */ 796 if (pHead) { 797 pNewShapeEvent = 0; 798 for (pShapeEvent = *pHead; pShapeEvent; 799 pShapeEvent = pShapeEvent->next) { 800 if (pShapeEvent->client == client) 801 break; 802 pNewShapeEvent = pShapeEvent; 803 } 804 if (pShapeEvent) { 805 FreeResource(pShapeEvent->clientResource, ClientType); 806 if (pNewShapeEvent) 807 pNewShapeEvent->next = pShapeEvent->next; 808 else 809 *pHead = pShapeEvent->next; 810 free(pShapeEvent); 811 } 812 } 813 break; 814 default: 815 client->errorValue = stuff->enable; 816 return BadValue; 817 } 818 return Success; 819} 820 821/* 822 * deliver the event 823 */ 824 825void 826SendShapeNotify(WindowPtr pWin, int which) 827{ 828 ShapeEventPtr *pHead, pShapeEvent; 829 BoxRec extents; 830 RegionPtr region; 831 BYTE shaped; 832 int rc; 833 834 rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id, 835 ShapeEventType, serverClient, DixReadAccess); 836 if (rc != Success) 837 return; 838 switch (which) { 839 case ShapeBounding: 840 region = wBoundingShape(pWin); 841 if (region) { 842 extents = *RegionExtents(region); 843 shaped = xTrue; 844 } 845 else { 846 extents.x1 = -wBorderWidth(pWin); 847 extents.y1 = -wBorderWidth(pWin); 848 extents.x2 = pWin->drawable.width + wBorderWidth(pWin); 849 extents.y2 = pWin->drawable.height + wBorderWidth(pWin); 850 shaped = xFalse; 851 } 852 break; 853 case ShapeClip: 854 region = wClipShape(pWin); 855 if (region) { 856 extents = *RegionExtents(region); 857 shaped = xTrue; 858 } 859 else { 860 extents.x1 = 0; 861 extents.y1 = 0; 862 extents.x2 = pWin->drawable.width; 863 extents.y2 = pWin->drawable.height; 864 shaped = xFalse; 865 } 866 break; 867 case ShapeInput: 868 region = wInputShape(pWin); 869 if (region) { 870 extents = *RegionExtents(region); 871 shaped = xTrue; 872 } 873 else { 874 extents.x1 = -wBorderWidth(pWin); 875 extents.y1 = -wBorderWidth(pWin); 876 extents.x2 = pWin->drawable.width + wBorderWidth(pWin); 877 extents.y2 = pWin->drawable.height + wBorderWidth(pWin); 878 shaped = xFalse; 879 } 880 break; 881 default: 882 return; 883 } 884 UpdateCurrentTimeIf(); 885 for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { 886 xShapeNotifyEvent se = { 887 .type = ShapeNotify + ShapeEventBase, 888 .kind = which, 889 .window = pWin->drawable.id, 890 .x = extents.x1, 891 .y = extents.y1, 892 .width = extents.x2 - extents.x1, 893 .height = extents.y2 - extents.y1, 894 .time = currentTime.milliseconds, 895 .shaped = shaped 896 }; 897 WriteEventsToClient(pShapeEvent->client, 1, (xEvent *) &se); 898 } 899} 900 901static int 902ProcShapeInputSelected(ClientPtr client) 903{ 904 REQUEST(xShapeInputSelectedReq); 905 WindowPtr pWin; 906 ShapeEventPtr pShapeEvent, *pHead; 907 int enabled, rc; 908 xShapeInputSelectedReply rep; 909 910 REQUEST_SIZE_MATCH(xShapeInputSelectedReq); 911 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 912 if (rc != Success) 913 return rc; 914 rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id, 915 ShapeEventType, client, DixReadAccess); 916 if (rc != Success && rc != BadValue) 917 return rc; 918 enabled = xFalse; 919 if (pHead) { 920 for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { 921 if (pShapeEvent->client == client) { 922 enabled = xTrue; 923 break; 924 } 925 } 926 } 927 rep = (xShapeInputSelectedReply) { 928 .type = X_Reply, 929 .enabled = enabled, 930 .sequenceNumber = client->sequence, 931 .length = 0 932 }; 933 if (client->swapped) { 934 swaps(&rep.sequenceNumber); 935 swapl(&rep.length); 936 } 937 WriteToClient(client, sizeof(xShapeInputSelectedReply), &rep); 938 return Success; 939} 940 941static int 942ProcShapeGetRectangles(ClientPtr client) 943{ 944 REQUEST(xShapeGetRectanglesReq); 945 WindowPtr pWin; 946 xShapeGetRectanglesReply rep; 947 xRectangle *rects; 948 int nrects, i, rc; 949 RegionPtr region; 950 951 REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); 952 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 953 if (rc != Success) 954 return rc; 955 switch (stuff->kind) { 956 case ShapeBounding: 957 region = wBoundingShape(pWin); 958 break; 959 case ShapeClip: 960 region = wClipShape(pWin); 961 break; 962 case ShapeInput: 963 region = wInputShape(pWin); 964 break; 965 default: 966 client->errorValue = stuff->kind; 967 return BadValue; 968 } 969 if (!region) { 970 nrects = 1; 971 rects = malloc(sizeof(xRectangle)); 972 if (!rects) 973 return BadAlloc; 974 switch (stuff->kind) { 975 case ShapeBounding: 976 rects->x = -(int) wBorderWidth(pWin); 977 rects->y = -(int) wBorderWidth(pWin); 978 rects->width = pWin->drawable.width + wBorderWidth(pWin); 979 rects->height = pWin->drawable.height + wBorderWidth(pWin); 980 break; 981 case ShapeClip: 982 rects->x = 0; 983 rects->y = 0; 984 rects->width = pWin->drawable.width; 985 rects->height = pWin->drawable.height; 986 break; 987 case ShapeInput: 988 rects->x = -(int) wBorderWidth(pWin); 989 rects->y = -(int) wBorderWidth(pWin); 990 rects->width = pWin->drawable.width + wBorderWidth(pWin); 991 rects->height = pWin->drawable.height + wBorderWidth(pWin); 992 break; 993 } 994 } 995 else { 996 BoxPtr box; 997 998 nrects = RegionNumRects(region); 999 box = RegionRects(region); 1000 rects = xallocarray(nrects, sizeof(xRectangle)); 1001 if (!rects && nrects) 1002 return BadAlloc; 1003 for (i = 0; i < nrects; i++, box++) { 1004 rects[i].x = box->x1; 1005 rects[i].y = box->y1; 1006 rects[i].width = box->x2 - box->x1; 1007 rects[i].height = box->y2 - box->y1; 1008 } 1009 } 1010 rep = (xShapeGetRectanglesReply) { 1011 .type = X_Reply, 1012 .ordering = YXBanded, 1013 .sequenceNumber = client->sequence, 1014 .length = bytes_to_int32(nrects * sizeof(xRectangle)), 1015 .nrects = nrects 1016 }; 1017 if (client->swapped) { 1018 swaps(&rep.sequenceNumber); 1019 swapl(&rep.length); 1020 swapl(&rep.nrects); 1021 SwapShorts((short *) rects, (unsigned long) nrects * 4); 1022 } 1023 WriteToClient(client, sizeof(rep), &rep); 1024 WriteToClient(client, nrects * sizeof(xRectangle), rects); 1025 free(rects); 1026 return Success; 1027} 1028 1029static int 1030ProcShapeDispatch(ClientPtr client) 1031{ 1032 REQUEST(xReq); 1033 switch (stuff->data) { 1034 case X_ShapeQueryVersion: 1035 return ProcShapeQueryVersion(client); 1036 case X_ShapeRectangles: 1037#ifdef PANORAMIX 1038 if (!noPanoramiXExtension) 1039 return ProcPanoramiXShapeRectangles(client); 1040 else 1041#endif 1042 return ProcShapeRectangles(client); 1043 case X_ShapeMask: 1044#ifdef PANORAMIX 1045 if (!noPanoramiXExtension) 1046 return ProcPanoramiXShapeMask(client); 1047 else 1048#endif 1049 return ProcShapeMask(client); 1050 case X_ShapeCombine: 1051#ifdef PANORAMIX 1052 if (!noPanoramiXExtension) 1053 return ProcPanoramiXShapeCombine(client); 1054 else 1055#endif 1056 return ProcShapeCombine(client); 1057 case X_ShapeOffset: 1058#ifdef PANORAMIX 1059 if (!noPanoramiXExtension) 1060 return ProcPanoramiXShapeOffset(client); 1061 else 1062#endif 1063 return ProcShapeOffset(client); 1064 case X_ShapeQueryExtents: 1065 return ProcShapeQueryExtents(client); 1066 case X_ShapeSelectInput: 1067 return ProcShapeSelectInput(client); 1068 case X_ShapeInputSelected: 1069 return ProcShapeInputSelected(client); 1070 case X_ShapeGetRectangles: 1071 return ProcShapeGetRectangles(client); 1072 default: 1073 return BadRequest; 1074 } 1075} 1076 1077static void _X_COLD 1078SShapeNotifyEvent(xShapeNotifyEvent * from, xShapeNotifyEvent * to) 1079{ 1080 to->type = from->type; 1081 to->kind = from->kind; 1082 cpswapl(from->window, to->window); 1083 cpswaps(from->sequenceNumber, to->sequenceNumber); 1084 cpswaps(from->x, to->x); 1085 cpswaps(from->y, to->y); 1086 cpswaps(from->width, to->width); 1087 cpswaps(from->height, to->height); 1088 cpswapl(from->time, to->time); 1089 to->shaped = from->shaped; 1090} 1091 1092static int _X_COLD 1093SProcShapeQueryVersion(ClientPtr client) 1094{ 1095 REQUEST(xShapeQueryVersionReq); 1096 1097 swaps(&stuff->length); 1098 return ProcShapeQueryVersion(client); 1099} 1100 1101static int _X_COLD 1102SProcShapeRectangles(ClientPtr client) 1103{ 1104 REQUEST(xShapeRectanglesReq); 1105 1106 swaps(&stuff->length); 1107 REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq); 1108 swapl(&stuff->dest); 1109 swaps(&stuff->xOff); 1110 swaps(&stuff->yOff); 1111 SwapRestS(stuff); 1112 return ProcShapeRectangles(client); 1113} 1114 1115static int _X_COLD 1116SProcShapeMask(ClientPtr client) 1117{ 1118 REQUEST(xShapeMaskReq); 1119 1120 swaps(&stuff->length); 1121 REQUEST_SIZE_MATCH(xShapeMaskReq); 1122 swapl(&stuff->dest); 1123 swaps(&stuff->xOff); 1124 swaps(&stuff->yOff); 1125 swapl(&stuff->src); 1126 return ProcShapeMask(client); 1127} 1128 1129static int _X_COLD 1130SProcShapeCombine(ClientPtr client) 1131{ 1132 REQUEST(xShapeCombineReq); 1133 1134 swaps(&stuff->length); 1135 REQUEST_SIZE_MATCH(xShapeCombineReq); 1136 swapl(&stuff->dest); 1137 swaps(&stuff->xOff); 1138 swaps(&stuff->yOff); 1139 swapl(&stuff->src); 1140 return ProcShapeCombine(client); 1141} 1142 1143static int _X_COLD 1144SProcShapeOffset(ClientPtr client) 1145{ 1146 REQUEST(xShapeOffsetReq); 1147 1148 swaps(&stuff->length); 1149 REQUEST_SIZE_MATCH(xShapeOffsetReq); 1150 swapl(&stuff->dest); 1151 swaps(&stuff->xOff); 1152 swaps(&stuff->yOff); 1153 return ProcShapeOffset(client); 1154} 1155 1156static int _X_COLD 1157SProcShapeQueryExtents(ClientPtr client) 1158{ 1159 REQUEST(xShapeQueryExtentsReq); 1160 1161 swaps(&stuff->length); 1162 REQUEST_SIZE_MATCH(xShapeQueryExtentsReq); 1163 swapl(&stuff->window); 1164 return ProcShapeQueryExtents(client); 1165} 1166 1167static int _X_COLD 1168SProcShapeSelectInput(ClientPtr client) 1169{ 1170 REQUEST(xShapeSelectInputReq); 1171 1172 swaps(&stuff->length); 1173 REQUEST_SIZE_MATCH(xShapeSelectInputReq); 1174 swapl(&stuff->window); 1175 return ProcShapeSelectInput(client); 1176} 1177 1178static int _X_COLD 1179SProcShapeInputSelected(ClientPtr client) 1180{ 1181 REQUEST(xShapeInputSelectedReq); 1182 1183 swaps(&stuff->length); 1184 REQUEST_SIZE_MATCH(xShapeInputSelectedReq); 1185 swapl(&stuff->window); 1186 return ProcShapeInputSelected(client); 1187} 1188 1189static int _X_COLD 1190SProcShapeGetRectangles(ClientPtr client) 1191{ 1192 REQUEST(xShapeGetRectanglesReq); 1193 swaps(&stuff->length); 1194 REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); 1195 swapl(&stuff->window); 1196 return ProcShapeGetRectangles(client); 1197} 1198 1199static int _X_COLD 1200SProcShapeDispatch(ClientPtr client) 1201{ 1202 REQUEST(xReq); 1203 switch (stuff->data) { 1204 case X_ShapeQueryVersion: 1205 return SProcShapeQueryVersion(client); 1206 case X_ShapeRectangles: 1207 return SProcShapeRectangles(client); 1208 case X_ShapeMask: 1209 return SProcShapeMask(client); 1210 case X_ShapeCombine: 1211 return SProcShapeCombine(client); 1212 case X_ShapeOffset: 1213 return SProcShapeOffset(client); 1214 case X_ShapeQueryExtents: 1215 return SProcShapeQueryExtents(client); 1216 case X_ShapeSelectInput: 1217 return SProcShapeSelectInput(client); 1218 case X_ShapeInputSelected: 1219 return SProcShapeInputSelected(client); 1220 case X_ShapeGetRectangles: 1221 return SProcShapeGetRectangles(client); 1222 default: 1223 return BadRequest; 1224 } 1225} 1226 1227void 1228ShapeExtensionInit(void) 1229{ 1230 ExtensionEntry *extEntry; 1231 1232 ClientType = CreateNewResourceType(ShapeFreeClient, "ShapeClient"); 1233 ShapeEventType = CreateNewResourceType(ShapeFreeEvents, "ShapeEvent"); 1234 if (ClientType && ShapeEventType && 1235 (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, 1236 ProcShapeDispatch, SProcShapeDispatch, 1237 NULL, StandardMinorOpcode))) { 1238 ShapeEventBase = extEntry->eventBase; 1239 EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent; 1240 } 1241} 1242