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