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