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