shape.c revision f7df2e56
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 for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { 885 xShapeNotifyEvent se = { 886 .type = ShapeNotify + ShapeEventBase, 887 .kind = which, 888 .window = pWin->drawable.id, 889 .x = extents.x1, 890 .y = extents.y1, 891 .width = extents.x2 - extents.x1, 892 .height = extents.y2 - extents.y1, 893 .time = currentTime.milliseconds, 894 .shaped = shaped 895 }; 896 WriteEventsToClient(pShapeEvent->client, 1, (xEvent *) &se); 897 } 898} 899 900static int 901ProcShapeInputSelected(ClientPtr client) 902{ 903 REQUEST(xShapeInputSelectedReq); 904 WindowPtr pWin; 905 ShapeEventPtr pShapeEvent, *pHead; 906 int enabled, rc; 907 xShapeInputSelectedReply rep; 908 909 REQUEST_SIZE_MATCH(xShapeInputSelectedReq); 910 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 911 if (rc != Success) 912 return rc; 913 rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id, 914 ShapeEventType, client, DixReadAccess); 915 if (rc != Success && rc != BadValue) 916 return rc; 917 enabled = xFalse; 918 if (pHead) { 919 for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { 920 if (pShapeEvent->client == client) { 921 enabled = xTrue; 922 break; 923 } 924 } 925 } 926 rep = (xShapeInputSelectedReply) { 927 .type = X_Reply, 928 .enabled = enabled, 929 .sequenceNumber = client->sequence, 930 .length = 0 931 }; 932 if (client->swapped) { 933 swaps(&rep.sequenceNumber); 934 swapl(&rep.length); 935 } 936 WriteToClient(client, sizeof(xShapeInputSelectedReply), &rep); 937 return Success; 938} 939 940static int 941ProcShapeGetRectangles(ClientPtr client) 942{ 943 REQUEST(xShapeGetRectanglesReq); 944 WindowPtr pWin; 945 xShapeGetRectanglesReply rep; 946 xRectangle *rects; 947 int nrects, i, rc; 948 RegionPtr region; 949 950 REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); 951 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 952 if (rc != Success) 953 return rc; 954 switch (stuff->kind) { 955 case ShapeBounding: 956 region = wBoundingShape(pWin); 957 break; 958 case ShapeClip: 959 region = wClipShape(pWin); 960 break; 961 case ShapeInput: 962 region = wInputShape(pWin); 963 break; 964 default: 965 client->errorValue = stuff->kind; 966 return BadValue; 967 } 968 if (!region) { 969 nrects = 1; 970 rects = malloc(sizeof(xRectangle)); 971 if (!rects) 972 return BadAlloc; 973 switch (stuff->kind) { 974 case ShapeBounding: 975 rects->x = -(int) wBorderWidth(pWin); 976 rects->y = -(int) wBorderWidth(pWin); 977 rects->width = pWin->drawable.width + wBorderWidth(pWin); 978 rects->height = pWin->drawable.height + wBorderWidth(pWin); 979 break; 980 case ShapeClip: 981 rects->x = 0; 982 rects->y = 0; 983 rects->width = pWin->drawable.width; 984 rects->height = pWin->drawable.height; 985 break; 986 case ShapeInput: 987 rects->x = -(int) wBorderWidth(pWin); 988 rects->y = -(int) wBorderWidth(pWin); 989 rects->width = pWin->drawable.width + wBorderWidth(pWin); 990 rects->height = pWin->drawable.height + wBorderWidth(pWin); 991 break; 992 } 993 } 994 else { 995 BoxPtr box; 996 997 nrects = RegionNumRects(region); 998 box = RegionRects(region); 999 rects = xallocarray(nrects, sizeof(xRectangle)); 1000 if (!rects && nrects) 1001 return BadAlloc; 1002 for (i = 0; i < nrects; i++, box++) { 1003 rects[i].x = box->x1; 1004 rects[i].y = box->y1; 1005 rects[i].width = box->x2 - box->x1; 1006 rects[i].height = box->y2 - box->y1; 1007 } 1008 } 1009 rep = (xShapeGetRectanglesReply) { 1010 .type = X_Reply, 1011 .ordering = YXBanded, 1012 .sequenceNumber = client->sequence, 1013 .length = bytes_to_int32(nrects * sizeof(xRectangle)), 1014 .nrects = nrects 1015 }; 1016 if (client->swapped) { 1017 swaps(&rep.sequenceNumber); 1018 swapl(&rep.length); 1019 swapl(&rep.nrects); 1020 SwapShorts((short *) rects, (unsigned long) nrects * 4); 1021 } 1022 WriteToClient(client, sizeof(rep), &rep); 1023 WriteToClient(client, nrects * sizeof(xRectangle), rects); 1024 free(rects); 1025 return Success; 1026} 1027 1028static int 1029ProcShapeDispatch(ClientPtr client) 1030{ 1031 REQUEST(xReq); 1032 switch (stuff->data) { 1033 case X_ShapeQueryVersion: 1034 return ProcShapeQueryVersion(client); 1035 case X_ShapeRectangles: 1036#ifdef PANORAMIX 1037 if (!noPanoramiXExtension) 1038 return ProcPanoramiXShapeRectangles(client); 1039 else 1040#endif 1041 return ProcShapeRectangles(client); 1042 case X_ShapeMask: 1043#ifdef PANORAMIX 1044 if (!noPanoramiXExtension) 1045 return ProcPanoramiXShapeMask(client); 1046 else 1047#endif 1048 return ProcShapeMask(client); 1049 case X_ShapeCombine: 1050#ifdef PANORAMIX 1051 if (!noPanoramiXExtension) 1052 return ProcPanoramiXShapeCombine(client); 1053 else 1054#endif 1055 return ProcShapeCombine(client); 1056 case X_ShapeOffset: 1057#ifdef PANORAMIX 1058 if (!noPanoramiXExtension) 1059 return ProcPanoramiXShapeOffset(client); 1060 else 1061#endif 1062 return ProcShapeOffset(client); 1063 case X_ShapeQueryExtents: 1064 return ProcShapeQueryExtents(client); 1065 case X_ShapeSelectInput: 1066 return ProcShapeSelectInput(client); 1067 case X_ShapeInputSelected: 1068 return ProcShapeInputSelected(client); 1069 case X_ShapeGetRectangles: 1070 return ProcShapeGetRectangles(client); 1071 default: 1072 return BadRequest; 1073 } 1074} 1075 1076static void 1077SShapeNotifyEvent(xShapeNotifyEvent * from, xShapeNotifyEvent * to) 1078{ 1079 to->type = from->type; 1080 to->kind = from->kind; 1081 cpswapl(from->window, to->window); 1082 cpswaps(from->sequenceNumber, to->sequenceNumber); 1083 cpswaps(from->x, to->x); 1084 cpswaps(from->y, to->y); 1085 cpswaps(from->width, to->width); 1086 cpswaps(from->height, to->height); 1087 cpswapl(from->time, to->time); 1088 to->shaped = from->shaped; 1089} 1090 1091static int 1092SProcShapeQueryVersion(ClientPtr client) 1093{ 1094 REQUEST(xShapeQueryVersionReq); 1095 1096 swaps(&stuff->length); 1097 return ProcShapeQueryVersion(client); 1098} 1099 1100static int 1101SProcShapeRectangles(ClientPtr client) 1102{ 1103 REQUEST(xShapeRectanglesReq); 1104 1105 swaps(&stuff->length); 1106 REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq); 1107 swapl(&stuff->dest); 1108 swaps(&stuff->xOff); 1109 swaps(&stuff->yOff); 1110 SwapRestS(stuff); 1111 return ProcShapeRectangles(client); 1112} 1113 1114static int 1115SProcShapeMask(ClientPtr client) 1116{ 1117 REQUEST(xShapeMaskReq); 1118 1119 swaps(&stuff->length); 1120 REQUEST_SIZE_MATCH(xShapeMaskReq); 1121 swapl(&stuff->dest); 1122 swaps(&stuff->xOff); 1123 swaps(&stuff->yOff); 1124 swapl(&stuff->src); 1125 return ProcShapeMask(client); 1126} 1127 1128static int 1129SProcShapeCombine(ClientPtr client) 1130{ 1131 REQUEST(xShapeCombineReq); 1132 1133 swaps(&stuff->length); 1134 REQUEST_SIZE_MATCH(xShapeCombineReq); 1135 swapl(&stuff->dest); 1136 swaps(&stuff->xOff); 1137 swaps(&stuff->yOff); 1138 swapl(&stuff->src); 1139 return ProcShapeCombine(client); 1140} 1141 1142static int 1143SProcShapeOffset(ClientPtr client) 1144{ 1145 REQUEST(xShapeOffsetReq); 1146 1147 swaps(&stuff->length); 1148 REQUEST_SIZE_MATCH(xShapeOffsetReq); 1149 swapl(&stuff->dest); 1150 swaps(&stuff->xOff); 1151 swaps(&stuff->yOff); 1152 return ProcShapeOffset(client); 1153} 1154 1155static int 1156SProcShapeQueryExtents(ClientPtr client) 1157{ 1158 REQUEST(xShapeQueryExtentsReq); 1159 1160 swaps(&stuff->length); 1161 REQUEST_SIZE_MATCH(xShapeQueryExtentsReq); 1162 swapl(&stuff->window); 1163 return ProcShapeQueryExtents(client); 1164} 1165 1166static int 1167SProcShapeSelectInput(ClientPtr client) 1168{ 1169 REQUEST(xShapeSelectInputReq); 1170 1171 swaps(&stuff->length); 1172 REQUEST_SIZE_MATCH(xShapeSelectInputReq); 1173 swapl(&stuff->window); 1174 return ProcShapeSelectInput(client); 1175} 1176 1177static int 1178SProcShapeInputSelected(ClientPtr client) 1179{ 1180 REQUEST(xShapeInputSelectedReq); 1181 1182 swaps(&stuff->length); 1183 REQUEST_SIZE_MATCH(xShapeInputSelectedReq); 1184 swapl(&stuff->window); 1185 return ProcShapeInputSelected(client); 1186} 1187 1188static int 1189SProcShapeGetRectangles(ClientPtr client) 1190{ 1191 REQUEST(xShapeGetRectanglesReq); 1192 swaps(&stuff->length); 1193 REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); 1194 swapl(&stuff->window); 1195 return ProcShapeGetRectangles(client); 1196} 1197 1198static int 1199SProcShapeDispatch(ClientPtr client) 1200{ 1201 REQUEST(xReq); 1202 switch (stuff->data) { 1203 case X_ShapeQueryVersion: 1204 return SProcShapeQueryVersion(client); 1205 case X_ShapeRectangles: 1206 return SProcShapeRectangles(client); 1207 case X_ShapeMask: 1208 return SProcShapeMask(client); 1209 case X_ShapeCombine: 1210 return SProcShapeCombine(client); 1211 case X_ShapeOffset: 1212 return SProcShapeOffset(client); 1213 case X_ShapeQueryExtents: 1214 return SProcShapeQueryExtents(client); 1215 case X_ShapeSelectInput: 1216 return SProcShapeSelectInput(client); 1217 case X_ShapeInputSelected: 1218 return SProcShapeInputSelected(client); 1219 case X_ShapeGetRectangles: 1220 return SProcShapeGetRectangles(client); 1221 default: 1222 return BadRequest; 1223 } 1224} 1225 1226void 1227ShapeExtensionInit(void) 1228{ 1229 ExtensionEntry *extEntry; 1230 1231 ClientType = CreateNewResourceType(ShapeFreeClient, "ShapeClient"); 1232 ShapeEventType = CreateNewResourceType(ShapeFreeEvents, "ShapeEvent"); 1233 if (ClientType && ShapeEventType && 1234 (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, 1235 ProcShapeDispatch, SProcShapeDispatch, 1236 NULL, StandardMinorOpcode))) { 1237 ShapeEventBase = extEntry->eventBase; 1238 EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent; 1239 } 1240} 1241