window.c revision 637ac9ab
1/* 2 3Copyright (c) 2006, Red Hat, Inc. 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 17RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18IN AN 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 Red Hat shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from Red Hat. 24 25Copyright 1987, 1998 The Open Group 26 27Permission to use, copy, modify, distribute, and sell this software and its 28documentation for any purpose is hereby granted without fee, provided that 29the above copyright notice appear in all copies and that both that 30copyright notice and this permission notice appear in supporting 31documentation. 32 33The above copyright notice and this permission notice shall be included 34in all copies or substantial portions of the Software. 35 36THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 37OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 38MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 39IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 40OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 41ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 42OTHER DEALINGS IN THE SOFTWARE. 43 44Except as contained in this notice, the name of The Open Group shall 45not be used in advertising or otherwise to promote the sale, use or 46other dealings in this Software without prior written authorization 47from The Open Group. 48 49 50Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 51 52 All Rights Reserved 53 54Permission to use, copy, modify, and distribute this software and its 55documentation for any purpose and without fee is hereby granted, 56provided that the above copyright notice appear in all copies and that 57both that copyright notice and this permission notice appear in 58supporting documentation, and that the name of Digital not be 59used in advertising or publicity pertaining to distribution of the 60software without specific, written prior permission. 61 62DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 63ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 64DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 65ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 66WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 67ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 68SOFTWARE. 69 70*/ 71 72/* The panoramix components contained the following notice */ 73/***************************************************************** 74 75Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 76 77Permission is hereby granted, free of charge, to any person obtaining a copy 78of this software and associated documentation files (the "Software"), to deal 79in the Software without restriction, including without limitation the rights 80to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 81copies of the Software. 82 83The above copyright notice and this permission notice shall be included in 84all copies or substantial portions of the Software. 85 86THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 87IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 88FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 89DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 90BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 91WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 92IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 93 94Except as contained in this notice, the name of Digital Equipment Corporation 95shall not be used in advertising or otherwise to promote the sale, use or other 96dealings in this Software without prior written authorization from Digital 97Equipment Corporation. 98 99******************************************************************/ 100 101 102#ifdef HAVE_DIX_CONFIG_H 103#include <dix-config.h> 104#endif 105 106#include "misc.h" 107#include "scrnintstr.h" 108#include "os.h" 109#include "regionstr.h" 110#include "validate.h" 111#include "windowstr.h" 112#include "input.h" 113#include "inputstr.h" 114#include "resource.h" 115#include "colormapst.h" 116#include "cursorstr.h" 117#include "dixstruct.h" 118#include "gcstruct.h" 119#include "servermd.h" 120#ifdef PANORAMIX 121#include "panoramiX.h" 122#include "panoramiXsrv.h" 123#endif 124#include "dixevents.h" 125#include "globals.h" 126#include "mi.h" /* miPaintWindow */ 127 128#include "privates.h" 129#include "xace.h" 130 131/****** 132 * Window stuff for server 133 * 134 * CreateRootWindow, CreateWindow, ChangeWindowAttributes, 135 * GetWindowAttributes, DeleteWindow, DestroySubWindows, 136 * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, 137 * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, 138 * ChangeWindowDeviceCursor 139 ******/ 140 141static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11}; 142static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88}; 143 144static Bool WindowParentHasDeviceCursor(WindowPtr pWin, 145 DeviceIntPtr pDev, 146 CursorPtr pCurs); 147static Bool 148WindowSeekDeviceCursor(WindowPtr pWin, 149 DeviceIntPtr pDev, 150 DevCursNodePtr* pNode, 151 DevCursNodePtr* pPrev); 152 153_X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF; 154 155_X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; 156 157static int FocusPrivatesKeyIndex; 158_X_EXPORT DevPrivateKey FocusPrivatesKey = &FocusPrivatesKeyIndex; 159 160static Bool TileScreenSaver(int i, int kind); 161 162 163#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ 164 CWDontPropagate | CWOverrideRedirect | CWCursor ) 165 166#define BOXES_OVERLAP(b1, b2) \ 167 (!( ((b1)->x2 <= (b2)->x1) || \ 168 ( ((b1)->x1 >= (b2)->x2)) || \ 169 ( ((b1)->y2 <= (b2)->y1)) || \ 170 ( ((b1)->y1 >= (b2)->y2)) ) ) 171 172#define RedirectSend(pWin) \ 173 ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) 174 175#define SubSend(pWin) \ 176 ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) 177 178#define StrSend(pWin) \ 179 ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) 180 181#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) 182 183#ifdef DEBUG 184/****** 185 * PrintWindowTree 186 * For debugging only 187 ******/ 188 189static void 190PrintChildren(WindowPtr p1, int indent) 191{ 192 WindowPtr p2; 193 int i; 194 195 while (p1) 196 { 197 p2 = p1->firstChild; 198 ErrorF("[dix] "); 199 for (i=0; i<indent; i++) ErrorF(" "); 200 ErrorF("%lx\n", p1->drawable.id); 201 miPrintRegion(&p1->clipList); 202 PrintChildren(p2, indent+4); 203 p1 = p1->nextSib; 204 } 205} 206 207static void 208PrintWindowTree(void) 209{ 210 int i; 211 WindowPtr pWin, p1; 212 213 for (i=0; i<screenInfo.numScreens; i++) 214 { 215 ErrorF("[dix] WINDOW %d\n", i); 216 pWin = WindowTable[i]; 217 miPrintRegion(&pWin->clipList); 218 p1 = pWin->firstChild; 219 PrintChildren(p1, 4); 220 } 221} 222#endif 223 224_X_EXPORT int 225TraverseTree(WindowPtr pWin, VisitWindowProcPtr func, pointer data) 226{ 227 int result; 228 WindowPtr pChild; 229 230 if (!(pChild = pWin)) 231 return(WT_NOMATCH); 232 while (1) 233 { 234 result = (* func)(pChild, data); 235 if (result == WT_STOPWALKING) 236 return(WT_STOPWALKING); 237 if ((result == WT_WALKCHILDREN) && pChild->firstChild) 238 { 239 pChild = pChild->firstChild; 240 continue; 241 } 242 while (!pChild->nextSib && (pChild != pWin)) 243 pChild = pChild->parent; 244 if (pChild == pWin) 245 break; 246 pChild = pChild->nextSib; 247 } 248 return(WT_NOMATCH); 249} 250 251/***** 252 * WalkTree 253 * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on 254 * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, 255 * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING 256 * exit WalkTree. Does depth-first traverse. 257 *****/ 258 259_X_EXPORT int 260WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data) 261{ 262 return(TraverseTree(WindowTable[pScreen->myNum], func, data)); 263} 264 265/* hack for forcing backing store on all windows */ 266int defaultBackingStore = NotUseful; 267/* hack to force no backing store */ 268Bool disableBackingStore = FALSE; 269Bool enableBackingStore = FALSE; 270 271static void 272SetWindowToDefaults(WindowPtr pWin) 273{ 274 pWin->prevSib = NullWindow; 275 pWin->firstChild = NullWindow; 276 pWin->lastChild = NullWindow; 277 278 pWin->valdata = (ValidatePtr)NULL; 279 pWin->optional = (WindowOptPtr)NULL; 280 pWin->cursorIsNone = TRUE; 281 282 pWin->backingStore = NotUseful; 283 pWin->DIXsaveUnder = FALSE; 284 pWin->backStorage = (pointer) NULL; 285 286 pWin->mapped = FALSE; /* off */ 287 pWin->realized = FALSE; /* off */ 288 pWin->viewable = FALSE; 289 pWin->visibility = VisibilityNotViewable; 290 pWin->overrideRedirect = FALSE; 291 pWin->saveUnder = FALSE; 292 293 pWin->bitGravity = ForgetGravity; 294 pWin->winGravity = NorthWestGravity; 295 296 pWin->eventMask = 0; 297 pWin->deliverableEvents = 0; 298 pWin->dontPropagate = 0; 299 pWin->forcedBS = FALSE; 300 pWin->redirectDraw = RedirectDrawNone; 301 pWin->forcedBG = FALSE; 302 303#ifdef ROOTLESS 304 pWin->rootlessUnhittable = FALSE; 305#endif 306} 307 308static void 309MakeRootTile(WindowPtr pWin) 310{ 311 ScreenPtr pScreen = pWin->drawable.pScreen; 312 GCPtr pGC; 313 unsigned char back[128]; 314 int len = BitmapBytePad(sizeof(long)); 315 unsigned char *from, *to; 316 int i, j; 317 318 pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4, 319 pScreen->rootDepth, 0); 320 321 pWin->backgroundState = BackgroundPixmap; 322 pGC = GetScratchGC(pScreen->rootDepth, pScreen); 323 if (!pWin->background.pixmap || !pGC) 324 FatalError("could not create root tile"); 325 326 { 327 CARD32 attributes[2]; 328 329 attributes[0] = pScreen->whitePixel; 330 attributes[1] = pScreen->blackPixel; 331 332 (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); 333 } 334 335 ValidateGC((DrawablePtr)pWin->background.pixmap, pGC); 336 337 from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb; 338 to = back; 339 340 for (i = 4; i > 0; i--, from++) 341 for (j = len; j > 0; j--) 342 *to++ = *from; 343 344 (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, 345 0, 0, len, 4, 0, XYBitmap, (char *)back); 346 347 FreeScratchGC(pGC); 348 349} 350 351/***** 352 * CreateRootWindow 353 * Makes a window at initialization time for specified screen 354 *****/ 355 356Bool 357CreateRootWindow(ScreenPtr pScreen) 358{ 359 WindowPtr pWin; 360 BoxRec box; 361 PixmapFormatRec *format; 362 363 pWin = (WindowPtr)xalloc(sizeof(WindowRec)); 364 if (!pWin) 365 return FALSE; 366 367 savedScreenInfo[pScreen->myNum].pWindow = NULL; 368 savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); 369 savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; 370 screenIsSaved = SCREEN_SAVER_OFF; 371 372 WindowTable[pScreen->myNum] = pWin; 373 374 pWin->drawable.pScreen = pScreen; 375 pWin->drawable.type = DRAWABLE_WINDOW; 376 pWin->devPrivates = NULL; 377 378 pWin->drawable.depth = pScreen->rootDepth; 379 for (format = screenInfo.formats; 380 format->depth != pScreen->rootDepth; 381 format++) 382 ; 383 pWin->drawable.bitsPerPixel = format->bitsPerPixel; 384 385 pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; 386 387 pWin->parent = NullWindow; 388 SetWindowToDefaults(pWin); 389 390 pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); 391 if (!pWin->optional) 392 return FALSE; 393 394 pWin->optional->dontPropagateMask = 0; 395 pWin->optional->otherEventMasks = 0; 396 pWin->optional->otherClients = NULL; 397 pWin->optional->passiveGrabs = NULL; 398 pWin->optional->userProps = NULL; 399 pWin->optional->backingBitPlanes = ~0L; 400 pWin->optional->backingPixel = 0; 401 pWin->optional->boundingShape = NULL; 402 pWin->optional->clipShape = NULL; 403 pWin->optional->inputShape = NULL; 404 pWin->optional->inputMasks = NULL; 405 pWin->optional->deviceCursors = NULL; 406 pWin->optional->geMasks = (GenericClientMasksPtr)xcalloc(1, sizeof(GenericClientMasksRec)); 407 if (!pWin->optional->geMasks) 408 { 409 xfree(pWin->optional); 410 return FALSE; 411 } 412 413 pWin->optional->access.perm = NULL; 414 pWin->optional->access.deny = NULL; 415 pWin->optional->access.nperm = 0; 416 pWin->optional->access.ndeny = 0; 417 pWin->optional->access.defaultRule = 0; 418 419 pWin->optional->colormap = pScreen->defColormap; 420 pWin->optional->visual = pScreen->rootVisual; 421 422 pWin->nextSib = NullWindow; 423 424 pWin->drawable.id = FakeClientID(0); 425 426 pWin->origin.x = pWin->origin.y = 0; 427 pWin->drawable.height = pScreen->height; 428 pWin->drawable.width = pScreen->width; 429 pWin->drawable.x = pWin->drawable.y = 0; 430 431 box.x1 = 0; 432 box.y1 = 0; 433 box.x2 = pScreen->width; 434 box.y2 = pScreen->height; 435 REGION_INIT(pScreen, &pWin->clipList, &box, 1); 436 REGION_INIT(pScreen, &pWin->winSize, &box, 1); 437 REGION_INIT(pScreen, &pWin->borderSize, &box, 1); 438 REGION_INIT(pScreen, &pWin->borderClip, &box, 1); 439 440 pWin->drawable.class = InputOutput; 441 pWin->optional->visual = pScreen->rootVisual; 442 443 pWin->backgroundState = BackgroundPixel; 444 pWin->background.pixel = pScreen->whitePixel; 445 446 pWin->borderIsPixel = TRUE; 447 pWin->border.pixel = pScreen->blackPixel; 448 pWin->borderWidth = 0; 449 450 /* security creation/labeling check 451 */ 452 if (XaceHook(XACE_RESOURCE_ACCESS, serverClient, pWin->drawable.id, 453 RT_WINDOW, pWin, RT_NONE, NULL, DixCreateAccess)) 454 return FALSE; 455 456 if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) 457 return FALSE; 458 459 if (disableBackingStore) 460 pScreen->backingStoreSupport = NotUseful; 461 if (enableBackingStore) 462 pScreen->backingStoreSupport = Always; 463 464 pScreen->saveUnderSupport = NotUseful; 465 466 return TRUE; 467} 468 469void 470InitRootWindow(WindowPtr pWin) 471{ 472 ScreenPtr pScreen = pWin->drawable.pScreen; 473 int backFlag = CWBorderPixel | CWCursor | CWBackingStore; 474 475 if (!(*pScreen->CreateWindow)(pWin)) 476 return; /* XXX */ 477 (*pScreen->PositionWindow)(pWin, 0, 0); 478 479 pWin->cursorIsNone = FALSE; 480 pWin->optional->cursor = rootCursor; 481 rootCursor->refcnt++; 482 483 484 if (party_like_its_1989) { 485 MakeRootTile(pWin); 486 backFlag |= CWBackPixmap; 487 } else { 488 if (whiteRoot) 489 pWin->background.pixel = pScreen->whitePixel; 490 else 491 pWin->background.pixel = pScreen->blackPixel; 492 backFlag |= CWBackPixel; 493 } 494 495 pWin->backingStore = defaultBackingStore; 496 pWin->forcedBS = (defaultBackingStore != NotUseful); 497 /* We SHOULD check for an error value here XXX */ 498 (*pScreen->ChangeWindowAttributes)(pWin, backFlag); 499 500 MapWindow(pWin, serverClient); 501} 502 503/* Set the region to the intersection of the rectangle and the 504 * window's winSize. The window is typically the parent of the 505 * window from which the region came. 506 */ 507 508static void 509ClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn, 510 int x, int y, 511 int w, int h) 512{ 513 ScreenPtr pScreen; 514 BoxRec box; 515 516 pScreen = pWin->drawable.pScreen; 517 518 box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); 519 /* we do these calculations to avoid overflows */ 520 if (x > box.x1) 521 box.x1 = x; 522 if (y > box.y1) 523 box.y1 = y; 524 x += w; 525 if (x < box.x2) 526 box.x2 = x; 527 y += h; 528 if (y < box.y2) 529 box.y2 = y; 530 if (box.x1 > box.x2) 531 box.x2 = box.x1; 532 if (box.y1 > box.y2) 533 box.y2 = box.y1; 534 REGION_RESET(pScreen, Rgn, &box); 535 REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); 536} 537 538static RealChildHeadProc realChildHeadProc = NULL; 539 540void 541RegisterRealChildHeadProc (RealChildHeadProc proc) 542{ 543 realChildHeadProc = proc; 544} 545 546 547WindowPtr 548RealChildHead(WindowPtr pWin) 549{ 550 if (realChildHeadProc) { 551 return realChildHeadProc (pWin); 552 } 553 554 if (!pWin->parent && 555 (screenIsSaved == SCREEN_SAVER_ON) && 556 (HasSaverWindow (pWin->drawable.pScreen->myNum))) 557 return (pWin->firstChild); 558 else 559 return (NullWindow); 560} 561 562/***** 563 * CreateWindow 564 * Makes a window in response to client request 565 *****/ 566 567_X_EXPORT WindowPtr 568CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w, 569 unsigned h, unsigned bw, unsigned class, Mask vmask, XID *vlist, 570 int depth, ClientPtr client, VisualID visual, int *error) 571{ 572 WindowPtr pWin; 573 WindowPtr pHead; 574 ScreenPtr pScreen; 575 xEvent event; 576 int idepth, ivisual; 577 Bool fOK; 578 DepthPtr pDepth; 579 PixmapFormatRec *format; 580 WindowOptPtr ancwopt; 581 582 if (class == CopyFromParent) 583 class = pParent->drawable.class; 584 585 if ((class != InputOutput) && (class != InputOnly)) 586 { 587 *error = BadValue; 588 client->errorValue = class; 589 return NullWindow; 590 } 591 592 if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) 593 { 594 *error = BadMatch; 595 return NullWindow; 596 } 597 598 if ((class == InputOnly) && ((bw != 0) || (depth != 0))) 599 { 600 *error = BadMatch; 601 return NullWindow; 602 } 603 604 pScreen = pParent->drawable.pScreen; 605 if ((class == InputOutput) && (depth == 0)) 606 depth = pParent->drawable.depth; 607 ancwopt = pParent->optional; 608 if (!ancwopt) 609 ancwopt = FindWindowWithOptional(pParent)->optional; 610 if (visual == CopyFromParent) { 611 visual = ancwopt->visual; 612 } 613 614 /* Find out if the depth and visual are acceptable for this Screen */ 615 if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) 616 { 617 fOK = FALSE; 618 for(idepth = 0; idepth < pScreen->numDepths; idepth++) 619 { 620 pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; 621 if ((depth == pDepth->depth) || (depth == 0)) 622 { 623 for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) 624 { 625 if (visual == pDepth->vids[ivisual]) 626 { 627 fOK = TRUE; 628 break; 629 } 630 } 631 } 632 } 633 if (fOK == FALSE) 634 { 635 *error = BadMatch; 636 return NullWindow; 637 } 638 } 639 640 if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && 641 (class != InputOnly) && 642 (depth != pParent->drawable.depth)) 643 { 644 *error = BadMatch; 645 return NullWindow; 646 } 647 648 if (((vmask & CWColormap) == 0) && 649 (class != InputOnly) && 650 ((visual != ancwopt->visual) || (ancwopt->colormap == None))) 651 { 652 *error = BadMatch; 653 return NullWindow; 654 } 655 656 pWin = (WindowPtr)xalloc(sizeof(WindowRec)); 657 if (!pWin) 658 { 659 *error = BadAlloc; 660 return NullWindow; 661 } 662 pWin->drawable = pParent->drawable; 663 pWin->devPrivates = NULL; 664 pWin->drawable.depth = depth; 665 if (depth == pParent->drawable.depth) 666 pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; 667 else 668 { 669 for (format = screenInfo.formats; format->depth != depth; format++) 670 ; 671 pWin->drawable.bitsPerPixel = format->bitsPerPixel; 672 } 673 if (class == InputOnly) 674 pWin->drawable.type = (short) UNDRAWABLE_WINDOW; 675 pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; 676 677 pWin->drawable.id = wid; 678 pWin->drawable.class = class; 679 680 pWin->parent = pParent; 681 SetWindowToDefaults(pWin); 682 683 if (visual != ancwopt->visual) 684 { 685 if (!MakeWindowOptional (pWin)) 686 { 687 xfree (pWin); 688 *error = BadAlloc; 689 return NullWindow; 690 } 691 pWin->optional->visual = visual; 692 pWin->optional->colormap = None; 693 } 694 695 pWin->borderWidth = bw; 696 697 /* security creation/labeling check 698 */ 699 *error = XaceHook(XACE_RESOURCE_ACCESS, client, wid, RT_WINDOW, pWin, 700 RT_WINDOW, pWin->parent, DixCreateAccess|DixSetAttrAccess); 701 if (*error != Success) { 702 xfree(pWin); 703 return NullWindow; 704 } 705 706 pWin->backgroundState = XaceBackgroundNoneState(pWin); 707 pWin->background.pixel = pScreen->whitePixel; 708 709 pWin->borderIsPixel = pParent->borderIsPixel; 710 pWin->border = pParent->border; 711 if (pWin->borderIsPixel == FALSE) 712 pWin->border.pixmap->refcnt++; 713 714 pWin->origin.x = x + (int)bw; 715 pWin->origin.y = y + (int)bw; 716 pWin->drawable.width = w; 717 pWin->drawable.height = h; 718 pWin->drawable.x = pParent->drawable.x + x + (int)bw; 719 pWin->drawable.y = pParent->drawable.y + y + (int)bw; 720 721 /* set up clip list correctly for unobscured WindowPtr */ 722 REGION_NULL(pScreen, &pWin->clipList); 723 REGION_NULL(pScreen, &pWin->borderClip); 724 REGION_NULL(pScreen, &pWin->winSize); 725 REGION_NULL(pScreen, &pWin->borderSize); 726 727 pHead = RealChildHead(pParent); 728 if (pHead) 729 { 730 pWin->nextSib = pHead->nextSib; 731 if (pHead->nextSib) 732 pHead->nextSib->prevSib = pWin; 733 else 734 pParent->lastChild = pWin; 735 pHead->nextSib = pWin; 736 pWin->prevSib = pHead; 737 } 738 else 739 { 740 pWin->nextSib = pParent->firstChild; 741 if (pParent->firstChild) 742 pParent->firstChild->prevSib = pWin; 743 else 744 pParent->lastChild = pWin; 745 pParent->firstChild = pWin; 746 } 747 748 SetWinSize (pWin); 749 SetBorderSize (pWin); 750 751 /* We SHOULD check for an error value here XXX */ 752 if (!(*pScreen->CreateWindow)(pWin)) 753 { 754 *error = BadAlloc; 755 DeleteWindow(pWin, None); 756 return NullWindow; 757 } 758 /* We SHOULD check for an error value here XXX */ 759 (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); 760 761 if (!(vmask & CWEventMask)) 762 RecalculateDeliverableEvents(pWin); 763 764 if (vmask) 765 *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); 766 else 767 *error = Success; 768 769 if (*error != Success) 770 { 771 DeleteWindow(pWin, None); 772 return NullWindow; 773 } 774 if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) 775 { 776 XID value = defaultBackingStore; 777 (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); 778 pWin->forcedBS = TRUE; 779 } 780 781 if (SubSend(pParent)) 782 { 783 event.u.u.type = CreateNotify; 784 event.u.createNotify.window = wid; 785 event.u.createNotify.parent = pParent->drawable.id; 786 event.u.createNotify.x = x; 787 event.u.createNotify.y = y; 788 event.u.createNotify.width = w; 789 event.u.createNotify.height = h; 790 event.u.createNotify.borderWidth = bw; 791 event.u.createNotify.override = pWin->overrideRedirect; 792 DeliverEvents(pParent, &event, 1, NullWindow); 793 } 794 return pWin; 795} 796 797static void 798DisposeWindowOptional (WindowPtr pWin) 799{ 800 GenericMaskPtr gmask = NULL, next = NULL; 801 802 if (!pWin->optional) 803 return; 804 /* 805 * everything is peachy. Delete the optional record 806 * and clean up 807 */ 808 if (pWin->optional->cursor) 809 { 810 FreeCursor (pWin->optional->cursor, (Cursor)0); 811 pWin->cursorIsNone = FALSE; 812 } 813 else 814 pWin->cursorIsNone = TRUE; 815 816 if (pWin->optional->deviceCursors) 817 { 818 DevCursorList pList; 819 DevCursorList pPrev; 820 pList = pWin->optional->deviceCursors; 821 while(pList) 822 { 823 if (pList->cursor) 824 FreeCursor(pList->cursor, (XID)0); 825 pPrev = pList; 826 pList = pList->next; 827 xfree(pPrev); 828 } 829 pWin->optional->deviceCursors = NULL; 830 } 831 832 xfree(pWin->optional->access.perm); 833 xfree(pWin->optional->access.deny); 834 835 /* Remove generic event mask allocations */ 836 if (pWin->optional->geMasks) 837 gmask = pWin->optional->geMasks->geClients; 838 while(gmask) 839 { 840 next = gmask->next; 841 xfree(gmask); 842 gmask = next; 843 } 844 xfree (pWin->optional->geMasks); 845 846 xfree (pWin->optional); 847 pWin->optional = NULL; 848} 849 850static void 851FreeWindowResources(WindowPtr pWin) 852{ 853 ScreenPtr pScreen = pWin->drawable.pScreen; 854 855 DeleteWindowFromAnySaveSet(pWin); 856 DeleteWindowFromAnySelections(pWin); 857 DeleteWindowFromAnyEvents(pWin, TRUE); 858 REGION_UNINIT(pScreen, &pWin->clipList); 859 REGION_UNINIT(pScreen, &pWin->winSize); 860 REGION_UNINIT(pScreen, &pWin->borderClip); 861 REGION_UNINIT(pScreen, &pWin->borderSize); 862 if (wBoundingShape (pWin)) 863 REGION_DESTROY(pScreen, wBoundingShape (pWin)); 864 if (wClipShape (pWin)) 865 REGION_DESTROY(pScreen, wClipShape (pWin)); 866 if (wInputShape (pWin)) 867 REGION_DESTROY(pScreen, wInputShape (pWin)); 868 if (pWin->borderIsPixel == FALSE) 869 (*pScreen->DestroyPixmap)(pWin->border.pixmap); 870 if (pWin->backgroundState == BackgroundPixmap) 871 (*pScreen->DestroyPixmap)(pWin->background.pixmap); 872 873 DeleteAllWindowProperties(pWin); 874 /* We SHOULD check for an error value here XXX */ 875 (*pScreen->DestroyWindow)(pWin); 876 DisposeWindowOptional (pWin); 877} 878 879static void 880CrushTree(WindowPtr pWin) 881{ 882 WindowPtr pChild, pSib, pParent; 883 UnrealizeWindowProcPtr UnrealizeWindow; 884 xEvent event; 885 886 if (!(pChild = pWin->firstChild)) 887 return; 888 UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; 889 while (1) 890 { 891 if (pChild->firstChild) 892 { 893 pChild = pChild->firstChild; 894 continue; 895 } 896 while (1) 897 { 898 pParent = pChild->parent; 899 if (SubStrSend(pChild, pParent)) 900 { 901 event.u.u.type = DestroyNotify; 902 event.u.destroyNotify.window = pChild->drawable.id; 903 DeliverEvents(pChild, &event, 1, NullWindow); 904 } 905 FreeResource(pChild->drawable.id, RT_WINDOW); 906 pSib = pChild->nextSib; 907 pChild->viewable = FALSE; 908 if (pChild->realized) 909 { 910 pChild->realized = FALSE; 911 (*UnrealizeWindow)(pChild); 912 } 913 FreeWindowResources(pChild); 914 dixFreePrivates(pChild->devPrivates); 915 xfree(pChild); 916 if ( (pChild = pSib) ) 917 break; 918 pChild = pParent; 919 pChild->firstChild = NullWindow; 920 pChild->lastChild = NullWindow; 921 if (pChild == pWin) 922 return; 923 } 924 } 925} 926 927/***** 928 * DeleteWindow 929 * Deletes child of window then window itself 930 * If wid is None, don't send any events 931 *****/ 932 933int 934DeleteWindow(pointer value, XID wid) 935 { 936 WindowPtr pParent; 937 WindowPtr pWin = (WindowPtr)value; 938 xEvent event; 939 940 UnmapWindow(pWin, FALSE); 941 942 CrushTree(pWin); 943 944 pParent = pWin->parent; 945 if (wid && pParent && SubStrSend(pWin, pParent)) 946 { 947 event.u.u.type = DestroyNotify; 948 event.u.destroyNotify.window = pWin->drawable.id; 949 DeliverEvents(pWin, &event, 1, NullWindow); 950 } 951 952 FreeWindowResources(pWin); 953 if (pParent) 954 { 955 if (pParent->firstChild == pWin) 956 pParent->firstChild = pWin->nextSib; 957 if (pParent->lastChild == pWin) 958 pParent->lastChild = pWin->prevSib; 959 if (pWin->nextSib) 960 pWin->nextSib->prevSib = pWin->prevSib; 961 if (pWin->prevSib) 962 pWin->prevSib->nextSib = pWin->nextSib; 963 } 964 xfree(dixLookupPrivate(&pWin->devPrivates, FocusPrivatesKey)); 965 dixFreePrivates(pWin->devPrivates); 966 xfree(pWin); 967 return Success; 968} 969 970int 971DestroySubwindows(WindowPtr pWin, ClientPtr client) 972{ 973 /* XXX 974 * The protocol is quite clear that each window should be 975 * destroyed in turn, however, unmapping all of the first 976 * eliminates most of the calls to ValidateTree. So, 977 * this implementation is incorrect in that all of the 978 * UnmapNotifies occur before all of the DestroyNotifies. 979 * If you care, simply delete the call to UnmapSubwindows. 980 */ 981 UnmapSubwindows(pWin); 982 while (pWin->lastChild) { 983 int rc = XaceHook(XACE_RESOURCE_ACCESS, client, 984 pWin->lastChild->drawable.id, RT_WINDOW, 985 pWin->lastChild, RT_NONE, NULL, DixDestroyAccess); 986 if (rc != Success) 987 return rc; 988 FreeResource(pWin->lastChild->drawable.id, RT_NONE); 989 } 990 return Success; 991} 992 993#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ 994 ButtonReleaseMask | PointerMotionMask) 995 996/***** 997 * ChangeWindowAttributes 998 * 999 * The value-mask specifies which attributes are to be changed; the 1000 * value-list contains one value for each one bit in the mask, from least 1001 * to most significant bit in the mask. 1002 *****/ 1003 1004_X_EXPORT int 1005ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) 1006{ 1007 XID *pVlist; 1008 PixmapPtr pPixmap; 1009 Pixmap pixID; 1010 CursorPtr pCursor, pOldCursor; 1011 Cursor cursorID; 1012 WindowPtr pChild; 1013 Colormap cmap; 1014 ColormapPtr pCmap; 1015 xEvent xE; 1016 int error, rc; 1017 ScreenPtr pScreen; 1018 Mask index2, tmask, vmaskCopy = 0; 1019 unsigned int val; 1020 Bool checkOptional = FALSE, borderRelative = FALSE; 1021 1022 if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) 1023 return BadMatch; 1024 1025 error = Success; 1026 pScreen = pWin->drawable.pScreen; 1027 pVlist = vlist; 1028 tmask = vmask; 1029 while (tmask) 1030 { 1031 index2 = (Mask) lowbit (tmask); 1032 tmask &= ~index2; 1033 switch (index2) 1034 { 1035 case CWBackPixmap: 1036 pixID = (Pixmap )*pVlist; 1037 pVlist++; 1038 if (pWin->backgroundState == ParentRelative) 1039 borderRelative = TRUE; 1040 if (pixID == None) 1041 { 1042 if (pWin->backgroundState == BackgroundPixmap) 1043 (*pScreen->DestroyPixmap)(pWin->background.pixmap); 1044 if (!pWin->parent) 1045 MakeRootTile(pWin); 1046 else { 1047 pWin->backgroundState = XaceBackgroundNoneState(pWin); 1048 pWin->background.pixel = pScreen->whitePixel; 1049 } 1050 } 1051 else if (pixID == ParentRelative) 1052 { 1053 if (pWin->parent && 1054 pWin->drawable.depth != pWin->parent->drawable.depth) 1055 { 1056 error = BadMatch; 1057 goto PatchUp; 1058 } 1059 if (pWin->backgroundState == BackgroundPixmap) 1060 (*pScreen->DestroyPixmap)(pWin->background.pixmap); 1061 if (!pWin->parent) 1062 MakeRootTile(pWin); 1063 else 1064 pWin->backgroundState = ParentRelative; 1065 borderRelative = TRUE; 1066 /* Note that the parent's backgroundTile's refcnt is NOT 1067 * incremented. */ 1068 } 1069 else 1070 { 1071 rc = dixLookupResource((pointer *)&pPixmap, pixID, RT_PIXMAP, 1072 client, DixReadAccess); 1073 if (rc == Success) 1074 { 1075 if ((pPixmap->drawable.depth != pWin->drawable.depth) || 1076 (pPixmap->drawable.pScreen != pScreen)) 1077 { 1078 error = BadMatch; 1079 goto PatchUp; 1080 } 1081 if (pWin->backgroundState == BackgroundPixmap) 1082 (*pScreen->DestroyPixmap)(pWin->background.pixmap); 1083 pWin->backgroundState = BackgroundPixmap; 1084 pWin->background.pixmap = pPixmap; 1085 pPixmap->refcnt++; 1086 } 1087 else 1088 { 1089 error = (rc == BadValue) ? BadPixmap : rc; 1090 client->errorValue = pixID; 1091 goto PatchUp; 1092 } 1093 } 1094 break; 1095 case CWBackPixel: 1096 if (pWin->backgroundState == ParentRelative) 1097 borderRelative = TRUE; 1098 if (pWin->backgroundState == BackgroundPixmap) 1099 (*pScreen->DestroyPixmap)(pWin->background.pixmap); 1100 pWin->backgroundState = BackgroundPixel; 1101 pWin->background.pixel = (CARD32 ) *pVlist; 1102 /* background pixel overrides background pixmap, 1103 so don't let the ddx layer see both bits */ 1104 vmaskCopy &= ~CWBackPixmap; 1105 pVlist++; 1106 break; 1107 case CWBorderPixmap: 1108 pixID = (Pixmap ) *pVlist; 1109 pVlist++; 1110 if (pixID == CopyFromParent) 1111 { 1112 if (!pWin->parent || 1113 (pWin->drawable.depth != pWin->parent->drawable.depth)) 1114 { 1115 error = BadMatch; 1116 goto PatchUp; 1117 } 1118 if (pWin->parent->borderIsPixel == TRUE) { 1119 if (pWin->borderIsPixel == FALSE) 1120 (*pScreen->DestroyPixmap)(pWin->border.pixmap); 1121 pWin->border = pWin->parent->border; 1122 pWin->borderIsPixel = TRUE; 1123 index2 = CWBorderPixel; 1124 break; 1125 } 1126 else 1127 { 1128 pixID = pWin->parent->border.pixmap->drawable.id; 1129 } 1130 } 1131 rc = dixLookupResource((pointer *)&pPixmap, pixID, RT_PIXMAP, 1132 client, DixReadAccess); 1133 if (rc == Success) 1134 { 1135 if ((pPixmap->drawable.depth != pWin->drawable.depth) || 1136 (pPixmap->drawable.pScreen != pScreen)) 1137 { 1138 error = BadMatch; 1139 goto PatchUp; 1140 } 1141 if (pWin->borderIsPixel == FALSE) 1142 (*pScreen->DestroyPixmap)(pWin->border.pixmap); 1143 pWin->borderIsPixel = FALSE; 1144 pWin->border.pixmap = pPixmap; 1145 pPixmap->refcnt++; 1146 } 1147 else 1148 { 1149 error = (rc == BadValue) ? BadPixmap : rc; 1150 client->errorValue = pixID; 1151 goto PatchUp; 1152 } 1153 break; 1154 case CWBorderPixel: 1155 if (pWin->borderIsPixel == FALSE) 1156 (*pScreen->DestroyPixmap)(pWin->border.pixmap); 1157 pWin->borderIsPixel = TRUE; 1158 pWin->border.pixel = (CARD32) *pVlist; 1159 /* border pixel overrides border pixmap, 1160 so don't let the ddx layer see both bits */ 1161 vmaskCopy &= ~CWBorderPixmap; 1162 pVlist++; 1163 break; 1164 case CWBitGravity: 1165 val = (CARD8 )*pVlist; 1166 pVlist++; 1167 if (val > StaticGravity) 1168 { 1169 error = BadValue; 1170 client->errorValue = val; 1171 goto PatchUp; 1172 } 1173 pWin->bitGravity = val; 1174 break; 1175 case CWWinGravity: 1176 val = (CARD8 )*pVlist; 1177 pVlist++; 1178 if (val > StaticGravity) 1179 { 1180 error = BadValue; 1181 client->errorValue = val; 1182 goto PatchUp; 1183 } 1184 pWin->winGravity = val; 1185 break; 1186 case CWBackingStore: 1187 val = (CARD8 )*pVlist; 1188 pVlist++; 1189 if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) 1190 { 1191 error = BadValue; 1192 client->errorValue = val; 1193 goto PatchUp; 1194 } 1195 pWin->backingStore = val; 1196 pWin->forcedBS = FALSE; 1197 break; 1198 case CWBackingPlanes: 1199 if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { 1200 if (!pWin->optional && !MakeWindowOptional (pWin)) 1201 { 1202 error = BadAlloc; 1203 goto PatchUp; 1204 } 1205 pWin->optional->backingBitPlanes = (CARD32) *pVlist; 1206 if ((CARD32)*pVlist == (CARD32)~0L) 1207 checkOptional = TRUE; 1208 } 1209 pVlist++; 1210 break; 1211 case CWBackingPixel: 1212 if (pWin->optional || (CARD32) *pVlist) { 1213 if (!pWin->optional && !MakeWindowOptional (pWin)) 1214 { 1215 error = BadAlloc; 1216 goto PatchUp; 1217 } 1218 pWin->optional->backingPixel = (CARD32) *pVlist; 1219 if (!*pVlist) 1220 checkOptional = TRUE; 1221 } 1222 pVlist++; 1223 break; 1224 case CWSaveUnder: 1225 val = (BOOL) *pVlist; 1226 pVlist++; 1227 if ((val != xTrue) && (val != xFalse)) 1228 { 1229 error = BadValue; 1230 client->errorValue = val; 1231 goto PatchUp; 1232 } 1233 pWin->saveUnder = val; 1234 break; 1235 case CWEventMask: 1236 rc = EventSelectForWindow(pWin, client, (Mask )*pVlist); 1237 if (rc) 1238 { 1239 error = rc; 1240 goto PatchUp; 1241 } 1242 pVlist++; 1243 break; 1244 case CWDontPropagate: 1245 rc = EventSuppressForWindow(pWin, client, (Mask )*pVlist, 1246 &checkOptional); 1247 if (rc) 1248 { 1249 error = rc; 1250 goto PatchUp; 1251 } 1252 pVlist++; 1253 break; 1254 case CWOverrideRedirect: 1255 val = (BOOL ) *pVlist; 1256 pVlist++; 1257 if ((val != xTrue) && (val != xFalse)) 1258 { 1259 error = BadValue; 1260 client->errorValue = val; 1261 goto PatchUp; 1262 } 1263 if (val == xTrue) { 1264 rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 1265 RT_WINDOW, pWin, RT_NONE, NULL, DixGrabAccess); 1266 if (rc != Success) { 1267 error = rc; 1268 client->errorValue = pWin->drawable.id; 1269 goto PatchUp; 1270 } 1271 } 1272 pWin->overrideRedirect = val; 1273 break; 1274 case CWColormap: 1275 cmap = (Colormap) *pVlist; 1276 pVlist++; 1277 if (cmap == CopyFromParent) 1278 { 1279 if (pWin->parent && 1280 (!pWin->optional || 1281 pWin->optional->visual == wVisual (pWin->parent))) 1282 { 1283 cmap = wColormap (pWin->parent); 1284 } 1285 else 1286 cmap = None; 1287 } 1288 if (cmap == None) 1289 { 1290 error = BadMatch; 1291 goto PatchUp; 1292 } 1293 rc = dixLookupResource((pointer *)&pCmap, cmap, RT_COLORMAP, 1294 client, DixUseAccess); 1295 if (rc != Success) 1296 { 1297 error = (rc == BadValue) ? BadColor : rc; 1298 client->errorValue = cmap; 1299 goto PatchUp; 1300 } 1301 if (pCmap->pVisual->vid != wVisual (pWin) || 1302 pCmap->pScreen != pScreen) 1303 { 1304 error = BadMatch; 1305 goto PatchUp; 1306 } 1307 if (cmap != wColormap (pWin)) 1308 { 1309 if (!pWin->optional) 1310 { 1311 if (!MakeWindowOptional (pWin)) 1312 { 1313 error = BadAlloc; 1314 goto PatchUp; 1315 } 1316 } 1317 else if (pWin->parent && cmap == wColormap (pWin->parent)) 1318 checkOptional = TRUE; 1319 1320 /* 1321 * propagate the original colormap to any children 1322 * inheriting it 1323 */ 1324 1325 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) 1326 { 1327 if (!pChild->optional && !MakeWindowOptional (pChild)) 1328 { 1329 error = BadAlloc; 1330 goto PatchUp; 1331 } 1332 } 1333 1334 pWin->optional->colormap = cmap; 1335 1336 /* 1337 * check on any children now matching the new colormap 1338 */ 1339 1340 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) 1341 { 1342 if (pChild->optional->colormap == cmap) 1343 CheckWindowOptionalNeed (pChild); 1344 } 1345 1346 xE.u.u.type = ColormapNotify; 1347 xE.u.colormap.window = pWin->drawable.id; 1348 xE.u.colormap.colormap = cmap; 1349 xE.u.colormap.new = xTrue; 1350 xE.u.colormap.state = IsMapInstalled(cmap, pWin); 1351 DeliverEvents(pWin, &xE, 1, NullWindow); 1352 } 1353 break; 1354 case CWCursor: 1355 cursorID = (Cursor ) *pVlist; 1356 pVlist++; 1357 /* 1358 * install the new 1359 */ 1360 if ( cursorID == None) 1361 { 1362 if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) 1363 pCursor = rootCursor; 1364 else 1365 pCursor = (CursorPtr) None; 1366 } 1367 else 1368 { 1369 rc = dixLookupResource((pointer *)&pCursor, cursorID, 1370 RT_CURSOR, client, DixUseAccess); 1371 if (rc != Success) 1372 { 1373 error = (rc == BadValue) ? BadCursor : rc; 1374 client->errorValue = cursorID; 1375 goto PatchUp; 1376 } 1377 } 1378 1379 if (pCursor != wCursor (pWin)) 1380 { 1381 /* 1382 * patch up child windows so they don't lose cursors. 1383 */ 1384 1385 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) 1386 { 1387 if (!pChild->optional && !pChild->cursorIsNone && 1388 !MakeWindowOptional (pChild)) 1389 { 1390 error = BadAlloc; 1391 goto PatchUp; 1392 } 1393 } 1394 1395 pOldCursor = 0; 1396 if (pCursor == (CursorPtr) None) 1397 { 1398 pWin->cursorIsNone = TRUE; 1399 if (pWin->optional) 1400 { 1401 pOldCursor = pWin->optional->cursor; 1402 pWin->optional->cursor = (CursorPtr) None; 1403 checkOptional = TRUE; 1404 } 1405 } else { 1406 if (!pWin->optional) 1407 { 1408 if (!MakeWindowOptional (pWin)) 1409 { 1410 error = BadAlloc; 1411 goto PatchUp; 1412 } 1413 } 1414 else if (pWin->parent && pCursor == wCursor (pWin->parent)) 1415 checkOptional = TRUE; 1416 pOldCursor = pWin->optional->cursor; 1417 pWin->optional->cursor = pCursor; 1418 pCursor->refcnt++; 1419 pWin->cursorIsNone = FALSE; 1420 /* 1421 * check on any children now matching the new cursor 1422 */ 1423 1424 for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) 1425 { 1426 if (pChild->optional && 1427 (pChild->optional->cursor == pCursor)) 1428 CheckWindowOptionalNeed (pChild); 1429 } 1430 } 1431 1432 if (pWin->realized) 1433 WindowHasNewCursor( pWin); 1434 1435 /* Can't free cursor until here - old cursor 1436 * is needed in WindowHasNewCursor 1437 */ 1438 if (pOldCursor) 1439 FreeCursor (pOldCursor, (Cursor)0); 1440 } 1441 break; 1442 default: 1443 error = BadValue; 1444 client->errorValue = vmask; 1445 goto PatchUp; 1446 } 1447 vmaskCopy |= index2; 1448 } 1449PatchUp: 1450 if (checkOptional) 1451 CheckWindowOptionalNeed (pWin); 1452 1453 /* We SHOULD check for an error value here XXX */ 1454 (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); 1455 1456 /* 1457 If the border contents have changed, redraw the border. 1458 Note that this has to be done AFTER pScreen->ChangeWindowAttributes 1459 for the tile to be rotated, and the correct function selected. 1460 */ 1461 if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) 1462 && pWin->viewable && HasBorder (pWin)) 1463 { 1464 RegionRec exposed; 1465 1466 REGION_NULL(pScreen, &exposed); 1467 REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); 1468 miPaintWindow(pWin, &exposed, PW_BORDER); 1469 REGION_UNINIT(pScreen, &exposed); 1470 } 1471 return error; 1472} 1473 1474 1475/***** 1476 * GetWindowAttributes 1477 * Notice that this is different than ChangeWindowAttributes 1478 *****/ 1479 1480void 1481GetWindowAttributes(WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply *wa) 1482{ 1483 wa->type = X_Reply; 1484 wa->bitGravity = pWin->bitGravity; 1485 wa->winGravity = pWin->winGravity; 1486 if (pWin->forcedBS && pWin->backingStore != Always) 1487 wa->backingStore = NotUseful; 1488 else 1489 wa->backingStore = pWin->backingStore; 1490 wa->length = (sizeof(xGetWindowAttributesReply) - 1491 sizeof(xGenericReply)) >> 2; 1492 wa->sequenceNumber = client->sequence; 1493 wa->backingBitPlanes = wBackingBitPlanes (pWin); 1494 wa->backingPixel = wBackingPixel (pWin); 1495 wa->saveUnder = (BOOL)pWin->saveUnder; 1496 wa->override = pWin->overrideRedirect; 1497 if (!pWin->mapped) 1498 wa->mapState = IsUnmapped; 1499 else if (pWin->realized) 1500 wa->mapState = IsViewable; 1501 else 1502 wa->mapState = IsUnviewable; 1503 1504 wa->colormap = wColormap (pWin); 1505 wa->mapInstalled = (wa->colormap == None) ? xFalse 1506 : IsMapInstalled(wa->colormap, pWin); 1507 1508 wa->yourEventMask = EventMaskForClient(pWin, client); 1509 wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); 1510 wa->doNotPropagateMask = wDontPropagateMask (pWin); 1511 wa->class = pWin->drawable.class; 1512 wa->visualID = wVisual (pWin); 1513} 1514 1515 1516WindowPtr 1517MoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib) 1518{ 1519 WindowPtr pParent = pWin->parent; 1520 WindowPtr pFirstChange = pWin; /* highest window where list changes */ 1521 1522 if (pWin->nextSib != pNextSib) 1523 { 1524 WindowPtr pOldNextSib = pWin->nextSib; 1525 1526 if (!pNextSib) /* move to bottom */ 1527 { 1528 if (pParent->firstChild == pWin) 1529 pParent->firstChild = pWin->nextSib; 1530 /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL 1531 * and pWin->nextSib != pNextSib 1532 * therefore pWin->nextSib != NULL */ 1533 pFirstChange = pWin->nextSib; 1534 pWin->nextSib->prevSib = pWin->prevSib; 1535 if (pWin->prevSib) 1536 pWin->prevSib->nextSib = pWin->nextSib; 1537 pParent->lastChild->nextSib = pWin; 1538 pWin->prevSib = pParent->lastChild; 1539 pWin->nextSib = NullWindow; 1540 pParent->lastChild = pWin; 1541 } 1542 else if (pParent->firstChild == pNextSib) /* move to top */ 1543 { 1544 pFirstChange = pWin; 1545 if (pParent->lastChild == pWin) 1546 pParent->lastChild = pWin->prevSib; 1547 if (pWin->nextSib) 1548 pWin->nextSib->prevSib = pWin->prevSib; 1549 if (pWin->prevSib) 1550 pWin->prevSib->nextSib = pWin->nextSib; 1551 pWin->nextSib = pParent->firstChild; 1552 pWin->prevSib = (WindowPtr ) NULL; 1553 pNextSib->prevSib = pWin; 1554 pParent->firstChild = pWin; 1555 } 1556 else /* move in middle of list */ 1557 { 1558 WindowPtr pOldNext = pWin->nextSib; 1559 1560 pFirstChange = NullWindow; 1561 if (pParent->firstChild == pWin) 1562 pFirstChange = pParent->firstChild = pWin->nextSib; 1563 if (pParent->lastChild == pWin) { 1564 pFirstChange = pWin; 1565 pParent->lastChild = pWin->prevSib; 1566 } 1567 if (pWin->nextSib) 1568 pWin->nextSib->prevSib = pWin->prevSib; 1569 if (pWin->prevSib) 1570 pWin->prevSib->nextSib = pWin->nextSib; 1571 pWin->nextSib = pNextSib; 1572 pWin->prevSib = pNextSib->prevSib; 1573 if (pNextSib->prevSib) 1574 pNextSib->prevSib->nextSib = pWin; 1575 pNextSib->prevSib = pWin; 1576 if (!pFirstChange) { /* do we know it yet? */ 1577 pFirstChange = pParent->firstChild; /* no, search from top */ 1578 while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) 1579 pFirstChange = pFirstChange->nextSib; 1580 } 1581 } 1582 if(pWin->drawable.pScreen->RestackWindow) 1583 (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); 1584 } 1585 1586#ifdef ROOTLESS 1587 /* 1588 * In rootless mode we can't optimize away window restacks. 1589 * There may be non-X windows around, so even if the window 1590 * is in the correct position from X's point of view, 1591 * the underlying window system may want to reorder it. 1592 */ 1593 else if (pWin->drawable.pScreen->RestackWindow) 1594 (*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib); 1595#endif 1596 1597 return( pFirstChange ); 1598} 1599 1600_X_EXPORT RegionPtr 1601CreateUnclippedWinSize (WindowPtr pWin) 1602{ 1603 RegionPtr pRgn; 1604 BoxRec box; 1605 1606 box.x1 = pWin->drawable.x; 1607 box.y1 = pWin->drawable.y; 1608 box.x2 = pWin->drawable.x + (int) pWin->drawable.width; 1609 box.y2 = pWin->drawable.y + (int) pWin->drawable.height; 1610 pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); 1611 if (wBoundingShape (pWin) || wClipShape (pWin)) { 1612 ScreenPtr pScreen; 1613 pScreen = pWin->drawable.pScreen; 1614 1615 REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, 1616 - pWin->drawable.y); 1617 if (wBoundingShape (pWin)) 1618 REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); 1619 if (wClipShape (pWin)) 1620 REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); 1621 REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); 1622 } 1623 return pRgn; 1624} 1625 1626void 1627SetWinSize (WindowPtr pWin) 1628{ 1629#ifdef COMPOSITE 1630 if (pWin->redirectDraw != RedirectDrawNone) 1631 { 1632 BoxRec box; 1633 1634 /* 1635 * Redirected clients get clip list equal to their 1636 * own geometry, not clipped to their parent 1637 */ 1638 box.x1 = pWin->drawable.x; 1639 box.y1 = pWin->drawable.y; 1640 box.x2 = pWin->drawable.x + pWin->drawable.width; 1641 box.y2 = pWin->drawable.y + pWin->drawable.height; 1642 REGION_RESET (pScreen, &pWin->winSize, &box); 1643 } 1644 else 1645#endif 1646 ClippedRegionFromBox(pWin->parent, &pWin->winSize, 1647 pWin->drawable.x, pWin->drawable.y, 1648 (int)pWin->drawable.width, 1649 (int)pWin->drawable.height); 1650 if (wBoundingShape (pWin) || wClipShape (pWin)) { 1651 ScreenPtr pScreen; 1652 pScreen = pWin->drawable.pScreen; 1653 1654 REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, 1655 - pWin->drawable.y); 1656 if (wBoundingShape (pWin)) 1657 REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, 1658 wBoundingShape (pWin)); 1659 if (wClipShape (pWin)) 1660 REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, 1661 wClipShape (pWin)); 1662 REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, 1663 pWin->drawable.y); 1664 } 1665} 1666 1667void 1668SetBorderSize (WindowPtr pWin) 1669{ 1670 int bw; 1671 1672 if (HasBorder (pWin)) { 1673 bw = wBorderWidth (pWin); 1674#ifdef COMPOSITE 1675 if (pWin->redirectDraw != RedirectDrawNone) 1676 { 1677 BoxRec box; 1678 1679 /* 1680 * Redirected clients get clip list equal to their 1681 * own geometry, not clipped to their parent 1682 */ 1683 box.x1 = pWin->drawable.x - bw; 1684 box.y1 = pWin->drawable.y - bw; 1685 box.x2 = pWin->drawable.x + pWin->drawable.width + bw; 1686 box.y2 = pWin->drawable.y + pWin->drawable.height + bw; 1687 REGION_RESET (pScreen, &pWin->borderSize, &box); 1688 } 1689 else 1690#endif 1691 ClippedRegionFromBox(pWin->parent, &pWin->borderSize, 1692 pWin->drawable.x - bw, pWin->drawable.y - bw, 1693 (int)(pWin->drawable.width + (bw<<1)), 1694 (int)(pWin->drawable.height + (bw<<1))); 1695 if (wBoundingShape (pWin)) { 1696 ScreenPtr pScreen; 1697 pScreen = pWin->drawable.pScreen; 1698 1699 REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, 1700 - pWin->drawable.y); 1701 REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, 1702 wBoundingShape (pWin)); 1703 REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, 1704 pWin->drawable.y); 1705 REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, 1706 &pWin->winSize); 1707 } 1708 } else { 1709 REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, 1710 &pWin->winSize); 1711 } 1712} 1713 1714/** 1715 * 1716 * \param x,y new window position 1717 * \param oldx,oldy old window position 1718 * \param destx,desty position relative to gravity 1719 */ 1720 1721_X_EXPORT void 1722GravityTranslate (int x, int y, int oldx, int oldy, 1723 int dw, int dh, unsigned gravity, 1724 int *destx, int *desty) 1725{ 1726 switch (gravity) { 1727 case NorthGravity: 1728 *destx = x + dw / 2; 1729 *desty = y; 1730 break; 1731 case NorthEastGravity: 1732 *destx = x + dw; 1733 *desty = y; 1734 break; 1735 case WestGravity: 1736 *destx = x; 1737 *desty = y + dh / 2; 1738 break; 1739 case CenterGravity: 1740 *destx = x + dw / 2; 1741 *desty = y + dh / 2; 1742 break; 1743 case EastGravity: 1744 *destx = x + dw; 1745 *desty = y + dh / 2; 1746 break; 1747 case SouthWestGravity: 1748 *destx = x; 1749 *desty = y + dh; 1750 break; 1751 case SouthGravity: 1752 *destx = x + dw / 2; 1753 *desty = y + dh; 1754 break; 1755 case SouthEastGravity: 1756 *destx = x + dw; 1757 *desty = y + dh; 1758 break; 1759 case StaticGravity: 1760 *destx = oldx; 1761 *desty = oldy; 1762 break; 1763 default: 1764 *destx = x; 1765 *desty = y; 1766 break; 1767 } 1768} 1769 1770/* XXX need to retile border on each window with ParentRelative origin */ 1771void 1772ResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh) 1773{ 1774 ScreenPtr pScreen; 1775 WindowPtr pSib, pChild; 1776 Bool resized = (dw || dh); 1777 1778 pScreen = pWin->drawable.pScreen; 1779 1780 for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) 1781 { 1782 if (resized && (pSib->winGravity > NorthWestGravity)) 1783 { 1784 int cwsx, cwsy; 1785 1786 cwsx = pSib->origin.x; 1787 cwsy = pSib->origin.y; 1788 GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, 1789 pSib->winGravity, &cwsx, &cwsy); 1790 if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) 1791 { 1792 xEvent event; 1793 1794 event.u.u.type = GravityNotify; 1795 event.u.gravity.window = pSib->drawable.id; 1796 event.u.gravity.x = cwsx - wBorderWidth (pSib); 1797 event.u.gravity.y = cwsy - wBorderWidth (pSib); 1798 DeliverEvents (pSib, &event, 1, NullWindow); 1799 pSib->origin.x = cwsx; 1800 pSib->origin.y = cwsy; 1801 } 1802 } 1803 pSib->drawable.x = pWin->drawable.x + pSib->origin.x; 1804 pSib->drawable.y = pWin->drawable.y + pSib->origin.y; 1805 SetWinSize (pSib); 1806 SetBorderSize (pSib); 1807 (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); 1808 1809 if ( (pChild = pSib->firstChild) ) 1810 { 1811 while (1) 1812 { 1813 pChild->drawable.x = pChild->parent->drawable.x + 1814 pChild->origin.x; 1815 pChild->drawable.y = pChild->parent->drawable.y + 1816 pChild->origin.y; 1817 SetWinSize (pChild); 1818 SetBorderSize (pChild); 1819 (*pScreen->PositionWindow)(pChild, 1820 pChild->drawable.x, pChild->drawable.y); 1821 if (pChild->firstChild) 1822 { 1823 pChild = pChild->firstChild; 1824 continue; 1825 } 1826 while (!pChild->nextSib && (pChild != pSib)) 1827 pChild = pChild->parent; 1828 if (pChild == pSib) 1829 break; 1830 pChild = pChild->nextSib; 1831 } 1832 } 1833 } 1834} 1835 1836#define GET_INT16(m, f) \ 1837 if (m & mask) \ 1838 { \ 1839 f = (INT16) *pVlist;\ 1840 pVlist++; \ 1841 } 1842#define GET_CARD16(m, f) \ 1843 if (m & mask) \ 1844 { \ 1845 f = (CARD16) *pVlist;\ 1846 pVlist++;\ 1847 } 1848 1849#define GET_CARD8(m, f) \ 1850 if (m & mask) \ 1851 { \ 1852 f = (CARD8) *pVlist;\ 1853 pVlist++;\ 1854 } 1855 1856#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) 1857 1858#define IllegalInputOnlyConfigureMask (CWBorderWidth) 1859 1860/* 1861 * IsSiblingAboveMe 1862 * returns Above if pSib above pMe in stack or Below otherwise 1863 */ 1864 1865static int 1866IsSiblingAboveMe( 1867 WindowPtr pMe, 1868 WindowPtr pSib) 1869{ 1870 WindowPtr pWin; 1871 1872 pWin = pMe->parent->firstChild; 1873 while (pWin) 1874 { 1875 if (pWin == pSib) 1876 return(Above); 1877 else if (pWin == pMe) 1878 return(Below); 1879 pWin = pWin->nextSib; 1880 } 1881 return(Below); 1882} 1883 1884static BoxPtr 1885WindowExtents( 1886 WindowPtr pWin, 1887 BoxPtr pBox) 1888{ 1889 pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); 1890 pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); 1891 pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width 1892 + wBorderWidth (pWin); 1893 pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height 1894 + wBorderWidth (pWin); 1895 return(pBox); 1896} 1897 1898#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) 1899 1900static RegionPtr 1901MakeBoundingRegion ( 1902 WindowPtr pWin, 1903 BoxPtr pBox) 1904{ 1905 RegionPtr pRgn; 1906 ScreenPtr pScreen; 1907 pScreen = pWin->drawable.pScreen; 1908 1909 pRgn = REGION_CREATE(pScreen, pBox, 1); 1910 if (wBoundingShape (pWin)) { 1911 REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, 1912 -pWin->origin.y); 1913 REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); 1914 REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, 1915 pWin->origin.y); 1916 } 1917 return pRgn; 1918} 1919 1920static Bool 1921ShapeOverlap ( 1922 WindowPtr pWin, 1923 BoxPtr pWinBox, 1924 WindowPtr pSib, 1925 BoxPtr pSibBox) 1926{ 1927 RegionPtr pWinRgn, pSibRgn; 1928 ScreenPtr pScreen; 1929 Bool ret; 1930 1931 if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) 1932 return TRUE; 1933 pScreen = pWin->drawable.pScreen; 1934 pWinRgn = MakeBoundingRegion (pWin, pWinBox); 1935 pSibRgn = MakeBoundingRegion (pSib, pSibBox); 1936 REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); 1937 ret = REGION_NOTEMPTY(pScreen, pWinRgn); 1938 REGION_DESTROY(pScreen, pWinRgn); 1939 REGION_DESTROY(pScreen, pSibRgn); 1940 return ret; 1941} 1942 1943static Bool 1944AnyWindowOverlapsMe( 1945 WindowPtr pWin, 1946 WindowPtr pHead, 1947 BoxPtr box) 1948{ 1949 WindowPtr pSib; 1950 BoxRec sboxrec; 1951 BoxPtr sbox; 1952 1953 for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) 1954 { 1955 if (pSib->mapped) 1956 { 1957 sbox = WindowExtents(pSib, &sboxrec); 1958 if (BOXES_OVERLAP(sbox, box) 1959 && ShapeOverlap (pWin, box, pSib, sbox) 1960 ) 1961 return(TRUE); 1962 } 1963 } 1964 return(FALSE); 1965} 1966 1967static Bool 1968IOverlapAnyWindow( 1969 WindowPtr pWin, 1970 BoxPtr box) 1971{ 1972 WindowPtr pSib; 1973 BoxRec sboxrec; 1974 BoxPtr sbox; 1975 1976 for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) 1977 { 1978 if (pSib->mapped) 1979 { 1980 sbox = WindowExtents(pSib, &sboxrec); 1981 if (BOXES_OVERLAP(sbox, box) 1982 && ShapeOverlap (pWin, box, pSib, sbox) 1983 ) 1984 return(TRUE); 1985 } 1986 } 1987 return(FALSE); 1988} 1989 1990/* 1991 * WhereDoIGoInTheStack() 1992 * Given pWin and pSib and the relationshipe smode, return 1993 * the window that pWin should go ABOVE. 1994 * If a pSib is specified: 1995 * Above: pWin is placed just above pSib 1996 * Below: pWin is placed just below pSib 1997 * TopIf: if pSib occludes pWin, then pWin is placed 1998 * at the top of the stack 1999 * BottomIf: if pWin occludes pSib, then pWin is 2000 * placed at the bottom of the stack 2001 * Opposite: if pSib occludes pWin, then pWin is placed at the 2002 * top of the stack, else if pWin occludes pSib, then 2003 * pWin is placed at the bottom of the stack 2004 * 2005 * If pSib is NULL: 2006 * Above: pWin is placed at the top of the stack 2007 * Below: pWin is placed at the bottom of the stack 2008 * TopIf: if any sibling occludes pWin, then pWin is placed at 2009 * the top of the stack 2010 * BottomIf: if pWin occludes any sibline, then pWin is placed at 2011 * the bottom of the stack 2012 * Opposite: if any sibling occludes pWin, then pWin is placed at 2013 * the top of the stack, else if pWin occludes any 2014 * sibling, then pWin is placed at the bottom of the stack 2015 * 2016 */ 2017 2018static WindowPtr 2019WhereDoIGoInTheStack( 2020 WindowPtr pWin, 2021 WindowPtr pSib, 2022 short x, 2023 short y, 2024 unsigned short w, 2025 unsigned short h, 2026 int smode) 2027{ 2028 BoxRec box; 2029 ScreenPtr pScreen; 2030 WindowPtr pHead, pFirst; 2031 2032 if ((pWin == pWin->parent->firstChild) && 2033 (pWin == pWin->parent->lastChild)) 2034 return((WindowPtr ) NULL); 2035 pHead = RealChildHead(pWin->parent); 2036 pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; 2037 pScreen = pWin->drawable.pScreen; 2038 box.x1 = x; 2039 box.y1 = y; 2040 box.x2 = x + (int)w; 2041 box.y2 = y + (int)h; 2042 switch (smode) 2043 { 2044 case Above: 2045 if (pSib) 2046 return(pSib); 2047 else if (pWin == pFirst) 2048 return(pWin->nextSib); 2049 else 2050 return(pFirst); 2051 case Below: 2052 if (pSib) 2053 if (pSib->nextSib != pWin) 2054 return(pSib->nextSib); 2055 else 2056 return(pWin->nextSib); 2057 else 2058 return NullWindow; 2059 case TopIf: 2060 if ((!pWin->mapped || (pSib && !pSib->mapped))) 2061 return(pWin->nextSib); 2062 else if (pSib) 2063 { 2064 if ((IsSiblingAboveMe(pWin, pSib) == Above) && 2065 (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) 2066 return(pFirst); 2067 else 2068 return(pWin->nextSib); 2069 } 2070 else if (AnyWindowOverlapsMe(pWin, pHead, &box)) 2071 return(pFirst); 2072 else 2073 return(pWin->nextSib); 2074 case BottomIf: 2075 if ((!pWin->mapped || (pSib && !pSib->mapped))) 2076 return(pWin->nextSib); 2077 else if (pSib) 2078 { 2079 if ((IsSiblingAboveMe(pWin, pSib) == Below) && 2080 (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) 2081 return NullWindow; 2082 else 2083 return(pWin->nextSib); 2084 } 2085 else if (IOverlapAnyWindow(pWin, &box)) 2086 return NullWindow; 2087 else 2088 return(pWin->nextSib); 2089 case Opposite: 2090 if ((!pWin->mapped || (pSib && !pSib->mapped))) 2091 return(pWin->nextSib); 2092 else if (pSib) 2093 { 2094 if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) 2095 { 2096 if (IsSiblingAboveMe(pWin, pSib) == Above) 2097 return(pFirst); 2098 else 2099 return NullWindow; 2100 } 2101 else 2102 return(pWin->nextSib); 2103 } 2104 else if (AnyWindowOverlapsMe(pWin, pHead, &box)) 2105 { 2106 /* If I'm occluded, I can't possibly be the first child 2107 * if (pWin == pWin->parent->firstChild) 2108 * return pWin->nextSib; 2109 */ 2110 return(pFirst); 2111 } 2112 else if (IOverlapAnyWindow(pWin, &box)) 2113 return NullWindow; 2114 else 2115 return pWin->nextSib; 2116 default: 2117 { 2118 /* should never happen; make something up. */ 2119 return pWin->nextSib; 2120 } 2121 } 2122} 2123 2124static void 2125ReflectStackChange( 2126 WindowPtr pWin, 2127 WindowPtr pSib, 2128 VTKind kind) 2129{ 2130/* Note that pSib might be NULL */ 2131 2132 Bool WasViewable = (Bool)pWin->viewable; 2133 Bool anyMarked; 2134 WindowPtr pFirstChange; 2135 WindowPtr pLayerWin; 2136 ScreenPtr pScreen = pWin->drawable.pScreen; 2137 2138 /* if this is a root window, can't be restacked */ 2139 if (!pWin->parent) 2140 return; 2141 2142 pFirstChange = MoveWindowInStack(pWin, pSib); 2143 2144 if (WasViewable) 2145 { 2146 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, 2147 &pLayerWin); 2148 if (pLayerWin != pWin) pFirstChange = pLayerWin; 2149 if (anyMarked) 2150 { 2151 (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); 2152 (*pScreen->HandleExposures)(pLayerWin->parent); 2153 } 2154 if (anyMarked && pWin->drawable.pScreen->PostValidateTree) 2155 (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); 2156 } 2157 if (pWin->realized) 2158 WindowsRestructured (); 2159} 2160 2161/***** 2162 * ConfigureWindow 2163 *****/ 2164 2165int 2166ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client) 2167{ 2168#define RESTACK_WIN 0 2169#define MOVE_WIN 1 2170#define RESIZE_WIN 2 2171#define REBORDER_WIN 3 2172 WindowPtr pSib = NullWindow; 2173 WindowPtr pParent = pWin->parent; 2174 Window sibwid = 0; 2175 Mask index2, tmask; 2176 XID *pVlist; 2177 short x, y, beforeX, beforeY; 2178 unsigned short w = pWin->drawable.width, 2179 h = pWin->drawable.height, 2180 bw = pWin->borderWidth; 2181 int rc, action, smode = Above; 2182 xEvent event; 2183 2184 if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) 2185 return(BadMatch); 2186 2187 if ((mask & CWSibling) && !(mask & CWStackMode)) 2188 return(BadMatch); 2189 2190 pVlist = vlist; 2191 2192 if (pParent) 2193 { 2194 x = pWin->drawable.x - pParent->drawable.x - (int)bw; 2195 y = pWin->drawable.y - pParent->drawable.y - (int)bw; 2196 } 2197 else 2198 { 2199 x = pWin->drawable.x; 2200 y = pWin->drawable.y; 2201 } 2202 beforeX = x; 2203 beforeY = y; 2204 action = RESTACK_WIN; 2205 if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) 2206 { 2207 GET_INT16(CWX, x); 2208 GET_INT16(CWY, y); 2209 action = MOVE_WIN; 2210 } 2211 /* or should be resized */ 2212 else if (mask & (CWX | CWY | CWWidth | CWHeight)) 2213 { 2214 GET_INT16(CWX, x); 2215 GET_INT16(CWY, y); 2216 GET_CARD16(CWWidth, w); 2217 GET_CARD16 (CWHeight, h); 2218 if (!w || !h) 2219 { 2220 client->errorValue = 0; 2221 return BadValue; 2222 } 2223 action = RESIZE_WIN; 2224 } 2225 tmask = mask & ~ChangeMask; 2226 while (tmask) 2227 { 2228 index2 = (Mask)lowbit (tmask); 2229 tmask &= ~index2; 2230 switch (index2) 2231 { 2232 case CWBorderWidth: 2233 GET_CARD16(CWBorderWidth, bw); 2234 break; 2235 case CWSibling: 2236 sibwid = (Window ) *pVlist; 2237 pVlist++; 2238 rc = dixLookupWindow(&pSib, sibwid, client, DixGetAttrAccess); 2239 if (rc != Success) 2240 { 2241 client->errorValue = sibwid; 2242 return rc; 2243 } 2244 if (pSib->parent != pParent) 2245 return(BadMatch); 2246 if (pSib == pWin) 2247 return(BadMatch); 2248 break; 2249 case CWStackMode: 2250 GET_CARD8(CWStackMode, smode); 2251 if ((smode != TopIf) && (smode != BottomIf) && 2252 (smode != Opposite) && (smode != Above) && (smode != Below)) 2253 { 2254 client->errorValue = smode; 2255 return(BadValue); 2256 } 2257 break; 2258 default: 2259 client->errorValue = mask; 2260 return(BadValue); 2261 } 2262 } 2263 /* root really can't be reconfigured, so just return */ 2264 if (!pParent) 2265 return Success; 2266 2267 /* Figure out if the window should be moved. Doesnt 2268 make the changes to the window if event sent */ 2269 2270 if (mask & CWStackMode) 2271 pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, 2272 pParent->drawable.y + y, 2273 w + (bw << 1), h + (bw << 1), smode); 2274 else 2275 pSib = pWin->nextSib; 2276 2277 2278 if ((!pWin->overrideRedirect) && 2279 (RedirectSend(pParent) 2280 )) 2281 { 2282 event.u.u.type = ConfigureRequest; 2283 event.u.configureRequest.window = pWin->drawable.id; 2284 if (mask & CWSibling) 2285 event.u.configureRequest.sibling = sibwid; 2286 else 2287 event.u.configureRequest.sibling = None; 2288 if (mask & CWStackMode) 2289 event.u.u.detail = smode; 2290 else 2291 event.u.u.detail = Above; 2292 event.u.configureRequest.x = x; 2293 event.u.configureRequest.y = y; 2294#ifdef PANORAMIX 2295 if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { 2296 event.u.configureRequest.x += panoramiXdataPtr[0].x; 2297 event.u.configureRequest.y += panoramiXdataPtr[0].y; 2298 } 2299#endif 2300 event.u.configureRequest.width = w; 2301 event.u.configureRequest.height = h; 2302 event.u.configureRequest.borderWidth = bw; 2303 event.u.configureRequest.valueMask = mask; 2304 event.u.configureRequest.parent = pParent->drawable.id; 2305 if (MaybeDeliverEventsToClient(pParent, &event, 1, 2306 SubstructureRedirectMask, client) == 1) 2307 return(Success); 2308 } 2309 if (action == RESIZE_WIN) 2310 { 2311 Bool size_change = (w != pWin->drawable.width) 2312 || (h != pWin->drawable.height); 2313 if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) 2314 { 2315 xEvent eventT; 2316 eventT.u.u.type = ResizeRequest; 2317 eventT.u.resizeRequest.window = pWin->drawable.id; 2318 eventT.u.resizeRequest.width = w; 2319 eventT.u.resizeRequest.height = h; 2320 if (MaybeDeliverEventsToClient(pWin, &eventT, 1, 2321 ResizeRedirectMask, client) == 1) 2322 { 2323 /* if event is delivered, leave the actual size alone. */ 2324 w = pWin->drawable.width; 2325 h = pWin->drawable.height; 2326 size_change = FALSE; 2327 } 2328 } 2329 if (!size_change) 2330 { 2331 if (mask & (CWX | CWY)) 2332 action = MOVE_WIN; 2333 else if (mask & (CWStackMode | CWBorderWidth)) 2334 action = RESTACK_WIN; 2335 else /* really nothing to do */ 2336 return(Success) ; 2337 } 2338 } 2339 2340 if (action == RESIZE_WIN) 2341 /* we've already checked whether there's really a size change */ 2342 goto ActuallyDoSomething; 2343 if ((mask & CWX) && (x != beforeX)) 2344 goto ActuallyDoSomething; 2345 if ((mask & CWY) && (y != beforeY)) 2346 goto ActuallyDoSomething; 2347 if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) 2348 goto ActuallyDoSomething; 2349 if (mask & CWStackMode) 2350 { 2351#ifndef ROOTLESS 2352 /* See above for why we always reorder in rootless mode. */ 2353 if (pWin->nextSib != pSib) 2354#endif 2355 goto ActuallyDoSomething; 2356 } 2357 return(Success); 2358 2359ActuallyDoSomething: 2360 if (SubStrSend(pWin, pParent)) 2361 { 2362 event.u.u.type = ConfigureNotify; 2363 event.u.configureNotify.window = pWin->drawable.id; 2364 if (pSib) 2365 event.u.configureNotify.aboveSibling = pSib->drawable.id; 2366 else 2367 event.u.configureNotify.aboveSibling = None; 2368 event.u.configureNotify.x = x; 2369 event.u.configureNotify.y = y; 2370#ifdef PANORAMIX 2371 if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { 2372 event.u.configureNotify.x += panoramiXdataPtr[0].x; 2373 event.u.configureNotify.y += panoramiXdataPtr[0].y; 2374 } 2375#endif 2376 event.u.configureNotify.width = w; 2377 event.u.configureNotify.height = h; 2378 event.u.configureNotify.borderWidth = bw; 2379 event.u.configureNotify.override = pWin->overrideRedirect; 2380 DeliverEvents(pWin, &event, 1, NullWindow); 2381 } 2382 if (mask & CWBorderWidth) 2383 { 2384 if (action == RESTACK_WIN) 2385 { 2386 action = MOVE_WIN; 2387 pWin->borderWidth = bw; 2388 } 2389 else if ((action == MOVE_WIN) && 2390 (beforeX + wBorderWidth (pWin) == x + (int)bw) && 2391 (beforeY + wBorderWidth (pWin) == y + (int)bw)) 2392 { 2393 action = REBORDER_WIN; 2394 (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); 2395 } 2396 else 2397 pWin->borderWidth = bw; 2398 } 2399 if (action == MOVE_WIN) 2400 (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, 2401 (mask & CWBorderWidth) ? VTOther : VTMove); 2402 else if (action == RESIZE_WIN) 2403 (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); 2404 else if (mask & CWStackMode) 2405 ReflectStackChange(pWin, pSib, VTOther); 2406 2407 if (action != RESTACK_WIN) 2408 CheckCursorConfinement(pWin); 2409 return(Success); 2410#undef RESTACK_WIN 2411#undef MOVE_WIN 2412#undef RESIZE_WIN 2413#undef REBORDER_WIN 2414} 2415 2416 2417/****** 2418 * 2419 * CirculateWindow 2420 * For RaiseLowest, raises the lowest mapped child (if any) that is 2421 * obscured by another child to the top of the stack. For LowerHighest, 2422 * lowers the highest mapped child (if any) that is obscuring another 2423 * child to the bottom of the stack. Exposure processing is performed 2424 * 2425 ******/ 2426 2427int 2428CirculateWindow(WindowPtr pParent, int direction, ClientPtr client) 2429{ 2430 WindowPtr pWin, pHead, pFirst; 2431 xEvent event; 2432 BoxRec box; 2433 2434 pHead = RealChildHead(pParent); 2435 pFirst = pHead ? pHead->nextSib : pParent->firstChild; 2436 if (direction == RaiseLowest) 2437 { 2438 for (pWin = pParent->lastChild; 2439 (pWin != pHead) && 2440 !(pWin->mapped && 2441 AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); 2442 pWin = pWin->prevSib) ; 2443 if (pWin == pHead) 2444 return Success; 2445 } 2446 else 2447 { 2448 for (pWin = pFirst; 2449 pWin && 2450 !(pWin->mapped && 2451 IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); 2452 pWin = pWin->nextSib) ; 2453 if (!pWin) 2454 return Success; 2455 } 2456 2457 event.u.circulate.window = pWin->drawable.id; 2458 event.u.circulate.parent = pParent->drawable.id; 2459 event.u.circulate.event = pParent->drawable.id; 2460 if (direction == RaiseLowest) 2461 event.u.circulate.place = PlaceOnTop; 2462 else 2463 event.u.circulate.place = PlaceOnBottom; 2464 2465 if (RedirectSend(pParent)) 2466 { 2467 event.u.u.type = CirculateRequest; 2468 if (MaybeDeliverEventsToClient(pParent, &event, 1, 2469 SubstructureRedirectMask, client) == 1) 2470 return(Success); 2471 } 2472 2473 event.u.u.type = CirculateNotify; 2474 DeliverEvents(pWin, &event, 1, NullWindow); 2475 ReflectStackChange(pWin, 2476 (direction == RaiseLowest) ? pFirst : NullWindow, 2477 VTStack); 2478 2479 return(Success); 2480} 2481 2482static int 2483CompareWIDs( 2484 WindowPtr pWin, 2485 pointer value) /* must conform to VisitWindowProcPtr */ 2486{ 2487 Window *wid = (Window *)value; 2488 2489 if (pWin->drawable.id == *wid) 2490 return(WT_STOPWALKING); 2491 else 2492 return(WT_WALKCHILDREN); 2493} 2494 2495/***** 2496 * ReparentWindow 2497 *****/ 2498 2499int 2500ReparentWindow(WindowPtr pWin, WindowPtr pParent, 2501 int x, int y, ClientPtr client) 2502{ 2503 WindowPtr pPrev, pPriorParent; 2504 Bool WasMapped = (Bool)(pWin->mapped); 2505 xEvent event; 2506 int bw = wBorderWidth (pWin); 2507 ScreenPtr pScreen; 2508 2509 pScreen = pWin->drawable.pScreen; 2510 if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) 2511 return(BadMatch); 2512 if (!MakeWindowOptional(pWin)) 2513 return(BadAlloc); 2514 2515 if (WasMapped) 2516 UnmapWindow(pWin, FALSE); 2517 2518 event.u.u.type = ReparentNotify; 2519 event.u.reparent.window = pWin->drawable.id; 2520 event.u.reparent.parent = pParent->drawable.id; 2521 event.u.reparent.x = x; 2522 event.u.reparent.y = y; 2523#ifdef PANORAMIX 2524 if(!noPanoramiXExtension && !pParent->parent) { 2525 event.u.reparent.x += panoramiXdataPtr[0].x; 2526 event.u.reparent.y += panoramiXdataPtr[0].y; 2527 } 2528#endif 2529 event.u.reparent.override = pWin->overrideRedirect; 2530 DeliverEvents(pWin, &event, 1, pParent); 2531 2532 /* take out of sibling chain */ 2533 2534 pPriorParent = pPrev = pWin->parent; 2535 if (pPrev->firstChild == pWin) 2536 pPrev->firstChild = pWin->nextSib; 2537 if (pPrev->lastChild == pWin) 2538 pPrev->lastChild = pWin->prevSib; 2539 2540 if (pWin->nextSib) 2541 pWin->nextSib->prevSib = pWin->prevSib; 2542 if (pWin->prevSib) 2543 pWin->prevSib->nextSib = pWin->nextSib; 2544 2545 /* insert at begining of pParent */ 2546 pWin->parent = pParent; 2547 pPrev = RealChildHead(pParent); 2548 if (pPrev) 2549 { 2550 pWin->nextSib = pPrev->nextSib; 2551 if (pPrev->nextSib) 2552 pPrev->nextSib->prevSib = pWin; 2553 else 2554 pParent->lastChild = pWin; 2555 pPrev->nextSib = pWin; 2556 pWin->prevSib = pPrev; 2557 } 2558 else 2559 { 2560 pWin->nextSib = pParent->firstChild; 2561 pWin->prevSib = NullWindow; 2562 if (pParent->firstChild) 2563 pParent->firstChild->prevSib = pWin; 2564 else 2565 pParent->lastChild = pWin; 2566 pParent->firstChild = pWin; 2567 } 2568 2569 pWin->origin.x = x + bw; 2570 pWin->origin.y = y + bw; 2571 pWin->drawable.x = x + bw + pParent->drawable.x; 2572 pWin->drawable.y = y + bw + pParent->drawable.y; 2573 2574 /* clip to parent */ 2575 SetWinSize (pWin); 2576 SetBorderSize (pWin); 2577 2578 if (pScreen->ReparentWindow) 2579 (*pScreen->ReparentWindow)(pWin, pPriorParent); 2580 (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); 2581 ResizeChildrenWinSize(pWin, 0, 0, 0, 0); 2582 2583 CheckWindowOptionalNeed(pWin); 2584 2585 if (WasMapped) 2586 MapWindow(pWin, client); 2587 RecalculateDeliverableEvents(pWin); 2588 return(Success); 2589} 2590 2591static void 2592RealizeTree(WindowPtr pWin) 2593{ 2594 WindowPtr pChild; 2595 RealizeWindowProcPtr Realize; 2596 2597 Realize = pWin->drawable.pScreen->RealizeWindow; 2598 pChild = pWin; 2599 while (1) 2600 { 2601 if (pChild->mapped) 2602 { 2603 pChild->realized = TRUE; 2604 pChild->viewable = (pChild->drawable.class == InputOutput); 2605 (* Realize)(pChild); 2606 if (pChild->firstChild) 2607 { 2608 pChild = pChild->firstChild; 2609 continue; 2610 } 2611 } 2612 while (!pChild->nextSib && (pChild != pWin)) 2613 pChild = pChild->parent; 2614 if (pChild == pWin) 2615 return; 2616 pChild = pChild->nextSib; 2617 } 2618} 2619 2620static WindowPtr windowDisableMapUnmapEvents; 2621 2622void 2623DisableMapUnmapEvents(WindowPtr pWin) 2624{ 2625 assert (windowDisableMapUnmapEvents == NULL); 2626 2627 windowDisableMapUnmapEvents = pWin; 2628} 2629 2630void 2631EnableMapUnmapEvents(WindowPtr pWin) 2632{ 2633 assert (windowDisableMapUnmapEvents != NULL); 2634 2635 windowDisableMapUnmapEvents = NULL; 2636} 2637 2638static Bool 2639MapUnmapEventsEnabled(WindowPtr pWin) 2640{ 2641 return pWin != windowDisableMapUnmapEvents; 2642} 2643 2644/***** 2645 * MapWindow 2646 * If some other client has selected SubStructureReDirect on the parent 2647 * and override-redirect is xFalse, then a MapRequest event is generated, 2648 * but the window remains unmapped. Otherwise, the window is mapped and a 2649 * MapNotify event is generated. 2650 *****/ 2651 2652_X_EXPORT int 2653MapWindow(WindowPtr pWin, ClientPtr client) 2654{ 2655 ScreenPtr pScreen; 2656 2657 WindowPtr pParent; 2658 WindowPtr pLayerWin; 2659 2660 if (pWin->mapped) 2661 return(Success); 2662 2663 /* general check for permission to map window */ 2664 if (XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, RT_WINDOW, 2665 pWin, RT_NONE, NULL, DixShowAccess) != Success) 2666 return Success; 2667 2668 pScreen = pWin->drawable.pScreen; 2669 if ( (pParent = pWin->parent) ) 2670 { 2671 xEvent event; 2672 Bool anyMarked; 2673 2674 if ((!pWin->overrideRedirect) && 2675 (RedirectSend(pParent) 2676 )) 2677 { 2678 event.u.u.type = MapRequest; 2679 event.u.mapRequest.window = pWin->drawable.id; 2680 event.u.mapRequest.parent = pParent->drawable.id; 2681 2682 if (MaybeDeliverEventsToClient(pParent, &event, 1, 2683 SubstructureRedirectMask, client) == 1) 2684 return(Success); 2685 } 2686 2687 pWin->mapped = TRUE; 2688 if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin)) 2689 { 2690 event.u.u.type = MapNotify; 2691 event.u.mapNotify.window = pWin->drawable.id; 2692 event.u.mapNotify.override = pWin->overrideRedirect; 2693 DeliverEvents(pWin, &event, 1, NullWindow); 2694 } 2695 2696 if (!pParent->realized) 2697 return(Success); 2698 RealizeTree(pWin); 2699 if (pWin->viewable) 2700 { 2701 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, 2702 &pLayerWin); 2703 if (anyMarked) 2704 { 2705 (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); 2706 (*pScreen->HandleExposures)(pLayerWin->parent); 2707 } 2708 if (anyMarked && pScreen->PostValidateTree) 2709 (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); 2710 } 2711 WindowsRestructured (); 2712 } 2713 else 2714 { 2715 RegionRec temp; 2716 2717 pWin->mapped = TRUE; 2718 pWin->realized = TRUE; /* for roots */ 2719 pWin->viewable = pWin->drawable.class == InputOutput; 2720 /* We SHOULD check for an error value here XXX */ 2721 (*pScreen->RealizeWindow)(pWin); 2722 if (pScreen->ClipNotify) 2723 (*pScreen->ClipNotify) (pWin, 0, 0); 2724 if (pScreen->PostValidateTree) 2725 (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); 2726 REGION_NULL(pScreen, &temp); 2727 REGION_COPY(pScreen, &temp, &pWin->clipList); 2728 (*pScreen->WindowExposures) (pWin, &temp, NullRegion); 2729 REGION_UNINIT(pScreen, &temp); 2730 } 2731 2732 return(Success); 2733} 2734 2735 2736/***** 2737 * MapSubwindows 2738 * Performs a MapWindow all unmapped children of the window, in top 2739 * to bottom stacking order. 2740 *****/ 2741 2742void 2743MapSubwindows(WindowPtr pParent, ClientPtr client) 2744{ 2745 WindowPtr pWin; 2746 WindowPtr pFirstMapped = NullWindow; 2747 ScreenPtr pScreen; 2748 Mask parentRedirect; 2749 Mask parentNotify; 2750 xEvent event; 2751 Bool anyMarked; 2752 WindowPtr pLayerWin; 2753 2754 pScreen = pParent->drawable.pScreen; 2755 parentRedirect = RedirectSend(pParent); 2756 parentNotify = SubSend(pParent); 2757 anyMarked = FALSE; 2758 for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) 2759 { 2760 if (!pWin->mapped) 2761 { 2762 if (parentRedirect && !pWin->overrideRedirect) 2763 { 2764 event.u.u.type = MapRequest; 2765 event.u.mapRequest.window = pWin->drawable.id; 2766 event.u.mapRequest.parent = pParent->drawable.id; 2767 2768 if (MaybeDeliverEventsToClient(pParent, &event, 1, 2769 SubstructureRedirectMask, client) == 1) 2770 continue; 2771 } 2772 2773 pWin->mapped = TRUE; 2774 if (parentNotify || StrSend(pWin)) 2775 { 2776 event.u.u.type = MapNotify; 2777 event.u.mapNotify.window = pWin->drawable.id; 2778 event.u.mapNotify.override = pWin->overrideRedirect; 2779 DeliverEvents(pWin, &event, 1, NullWindow); 2780 } 2781 2782 if (!pFirstMapped) 2783 pFirstMapped = pWin; 2784 if (pParent->realized) 2785 { 2786 RealizeTree(pWin); 2787 if (pWin->viewable) 2788 { 2789 anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, 2790 (WindowPtr *)NULL); 2791 } 2792 } 2793 } 2794 } 2795 2796 if (pFirstMapped) 2797 { 2798 pLayerWin = (*pScreen->GetLayerWindow)(pParent); 2799 if (pLayerWin->parent != pParent) { 2800 anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, 2801 pLayerWin, 2802 (WindowPtr *)NULL); 2803 pFirstMapped = pLayerWin; 2804 } 2805 if (anyMarked) 2806 { 2807 (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); 2808 (*pScreen->HandleExposures)(pLayerWin->parent); 2809 } 2810 if (anyMarked && pScreen->PostValidateTree) 2811 (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, 2812 VTMap); 2813 WindowsRestructured (); 2814 } 2815} 2816 2817static void 2818UnrealizeTree( 2819 WindowPtr pWin, 2820 Bool fromConfigure) 2821{ 2822 WindowPtr pChild; 2823 UnrealizeWindowProcPtr Unrealize; 2824 MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; 2825 2826 Unrealize = pWin->drawable.pScreen->UnrealizeWindow; 2827 MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; 2828 pChild = pWin; 2829 while (1) 2830 { 2831 if (pChild->realized) 2832 { 2833 pChild->realized = FALSE; 2834 pChild->visibility = VisibilityNotViewable; 2835#ifdef PANORAMIX 2836 if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { 2837 PanoramiXRes *win; 2838 win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, 2839 XRT_WINDOW); 2840 if(win) 2841 win->u.win.visibility = VisibilityNotViewable; 2842 } 2843#endif 2844 (* Unrealize)(pChild); 2845 if (MapUnmapEventsEnabled(pWin)) 2846 DeleteWindowFromAnyEvents(pChild, FALSE); 2847 if (pChild->viewable) 2848 { 2849 pChild->viewable = FALSE; 2850 (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); 2851 pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; 2852 } 2853 if (pChild->firstChild) 2854 { 2855 pChild = pChild->firstChild; 2856 continue; 2857 } 2858 } 2859 while (!pChild->nextSib && (pChild != pWin)) 2860 pChild = pChild->parent; 2861 if (pChild == pWin) 2862 return; 2863 pChild = pChild->nextSib; 2864 } 2865} 2866 2867/***** 2868 * UnmapWindow 2869 * If the window is already unmapped, this request has no effect. 2870 * Otherwise, the window is unmapped and an UnMapNotify event is 2871 * generated. Cannot unmap a root window. 2872 *****/ 2873 2874_X_EXPORT int 2875UnmapWindow(WindowPtr pWin, Bool fromConfigure) 2876{ 2877 WindowPtr pParent; 2878 xEvent event; 2879 Bool wasRealized = (Bool)pWin->realized; 2880 Bool wasViewable = (Bool)pWin->viewable; 2881 ScreenPtr pScreen = pWin->drawable.pScreen; 2882 WindowPtr pLayerWin = pWin; 2883 2884 if ((!pWin->mapped) || (!(pParent = pWin->parent))) 2885 return(Success); 2886 if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin)) 2887 { 2888 event.u.u.type = UnmapNotify; 2889 event.u.unmapNotify.window = pWin->drawable.id; 2890 event.u.unmapNotify.fromConfigure = fromConfigure; 2891 DeliverEvents(pWin, &event, 1, NullWindow); 2892 } 2893 if (wasViewable && !fromConfigure) 2894 { 2895 pWin->valdata = UnmapValData; 2896 (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); 2897 (*pScreen->MarkWindow)(pLayerWin->parent); 2898 } 2899 pWin->mapped = FALSE; 2900 if (wasRealized) 2901 UnrealizeTree(pWin, fromConfigure); 2902 if (wasViewable) 2903 { 2904 if (!fromConfigure) 2905 { 2906 (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); 2907 (*pScreen->HandleExposures)(pLayerWin->parent); 2908 } 2909 if (!fromConfigure && pScreen->PostValidateTree) 2910 (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); 2911 } 2912 if (wasRealized && !fromConfigure) 2913 WindowsRestructured (); 2914 return(Success); 2915} 2916 2917/***** 2918 * UnmapSubwindows 2919 * Performs an UnmapWindow request with the specified mode on all mapped 2920 * children of the window, in bottom to top stacking order. 2921 *****/ 2922 2923void 2924UnmapSubwindows(WindowPtr pWin) 2925{ 2926 WindowPtr pChild, pHead; 2927 xEvent event; 2928 Bool wasRealized = (Bool)pWin->realized; 2929 Bool wasViewable = (Bool)pWin->viewable; 2930 Bool anyMarked = FALSE; 2931 Mask parentNotify; 2932 WindowPtr pLayerWin = NULL; 2933 ScreenPtr pScreen = pWin->drawable.pScreen; 2934 2935 if (!pWin->firstChild) 2936 return; 2937 parentNotify = SubSend(pWin); 2938 pHead = RealChildHead(pWin); 2939 2940 if (wasViewable) 2941 pLayerWin = (*pScreen->GetLayerWindow)(pWin); 2942 2943 for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) 2944 { 2945 if (pChild->mapped) 2946 { 2947 if (parentNotify || StrSend(pChild)) 2948 { 2949 event.u.u.type = UnmapNotify; 2950 event.u.unmapNotify.window = pChild->drawable.id; 2951 event.u.unmapNotify.fromConfigure = xFalse; 2952 DeliverEvents(pChild, &event, 1, NullWindow); 2953 } 2954 if (pChild->viewable) 2955 { 2956 pChild->valdata = UnmapValData; 2957 anyMarked = TRUE; 2958 } 2959 pChild->mapped = FALSE; 2960 if (pChild->realized) 2961 UnrealizeTree(pChild, FALSE); 2962 if (wasViewable) 2963 { 2964 } 2965 } 2966 } 2967 if (wasViewable) 2968 { 2969 if (anyMarked) 2970 { 2971 if (pLayerWin->parent == pWin) 2972 (*pScreen->MarkWindow)(pWin); 2973 else 2974 { 2975 WindowPtr ptmp; 2976 (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, 2977 (WindowPtr *)NULL); 2978 (*pScreen->MarkWindow)(pLayerWin->parent); 2979 2980 /* Windows between pWin and pLayerWin may not have been marked */ 2981 ptmp = pWin; 2982 2983 while (ptmp != pLayerWin->parent) 2984 { 2985 (*pScreen->MarkWindow)(ptmp); 2986 ptmp = ptmp->parent; 2987 } 2988 pHead = pWin->firstChild; 2989 } 2990 (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); 2991 (*pScreen->HandleExposures)(pLayerWin->parent); 2992 } 2993 if (anyMarked && pScreen->PostValidateTree) 2994 (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); 2995 } 2996 if (wasRealized) 2997 WindowsRestructured (); 2998} 2999 3000 3001void 3002HandleSaveSet(ClientPtr client) 3003{ 3004 WindowPtr pParent, pWin; 3005 int j; 3006 3007 for (j=0; j<client->numSaved; j++) 3008 { 3009 pWin = SaveSetWindow(client->saveSet[j]); 3010#ifdef XFIXES 3011 if (SaveSetToRoot(client->saveSet[j])) 3012 pParent = WindowTable[pWin->drawable.pScreen->myNum]; 3013 else 3014#endif 3015 { 3016 pParent = pWin->parent; 3017 while (pParent && (wClient (pParent) == client)) 3018 pParent = pParent->parent; 3019 } 3020 if (pParent) 3021 { 3022 if (pParent != pWin->parent) 3023 { 3024#ifdef XFIXES 3025 /* unmap first so that ReparentWindow doesn't remap */ 3026 if (!SaveSetShouldMap (client->saveSet[j])) 3027 UnmapWindow(pWin, FALSE); 3028#endif 3029 ReparentWindow(pWin, pParent, 3030 pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, 3031 pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, 3032 client); 3033 if(!pWin->realized && pWin->mapped) 3034 pWin->mapped = FALSE; 3035 } 3036#ifdef XFIXES 3037 if (SaveSetShouldMap (client->saveSet[j])) 3038#endif 3039 MapWindow(pWin, client); 3040 } 3041 } 3042 xfree(client->saveSet); 3043 client->numSaved = 0; 3044 client->saveSet = (SaveSetElt *)NULL; 3045} 3046 3047/** 3048 * 3049 * \param x,y in root 3050 */ 3051Bool 3052PointInWindowIsVisible(WindowPtr pWin, int x, int y) 3053{ 3054 BoxRec box; 3055 3056 if (!pWin->realized) 3057 return (FALSE); 3058 if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, 3059 x, y, &box) 3060 && (!wInputShape(pWin) || 3061 POINT_IN_REGION(pWin->drawable.pScreen, 3062 wInputShape(pWin), 3063 x - pWin->drawable.x, 3064 y - pWin->drawable.y, &box))) 3065 return(TRUE); 3066 return(FALSE); 3067} 3068 3069 3070_X_EXPORT RegionPtr 3071NotClippedByChildren(WindowPtr pWin) 3072{ 3073 ScreenPtr pScreen; 3074 RegionPtr pReg; 3075 3076 pScreen = pWin->drawable.pScreen; 3077 pReg = REGION_CREATE(pScreen, NullBox, 1); 3078 if (pWin->parent || 3079 screenIsSaved != SCREEN_SAVER_ON || 3080 !HasSaverWindow (pWin->drawable.pScreen->myNum)) 3081 { 3082 REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); 3083 } 3084 return(pReg); 3085} 3086 3087void 3088SendVisibilityNotify(WindowPtr pWin) 3089{ 3090 xEvent event; 3091 if (!MapUnmapEventsEnabled(pWin)) 3092 return; 3093#ifndef NO_XINERAMA_PORT 3094 unsigned int visibility = pWin->visibility; 3095#endif 3096#ifdef PANORAMIX 3097 /* This is not quite correct yet, but it's close */ 3098 if(!noPanoramiXExtension) { 3099 PanoramiXRes *win; 3100 WindowPtr pWin2; 3101 int i, Scrnum; 3102 3103 Scrnum = pWin->drawable.pScreen->myNum; 3104 3105 win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); 3106 3107 if(!win || (win->u.win.visibility == visibility)) 3108 return; 3109 3110 switch(visibility) { 3111 case VisibilityUnobscured: 3112 for(i = 0; i < PanoramiXNumScreens; i++) { 3113 if(i == Scrnum) continue; 3114 3115 pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); 3116 3117 if (pWin2) { 3118 if(pWin2->visibility == VisibilityPartiallyObscured) 3119 return; 3120 3121 if(!i) pWin = pWin2; 3122 } 3123 } 3124 break; 3125 case VisibilityPartiallyObscured: 3126 if(Scrnum) { 3127 pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); 3128 if (pWin2) pWin = pWin2; 3129 } 3130 break; 3131 case VisibilityFullyObscured: 3132 for(i = 0; i < PanoramiXNumScreens; i++) { 3133 if(i == Scrnum) continue; 3134 3135 pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); 3136 3137 if (pWin2) { 3138 if(pWin2->visibility != VisibilityFullyObscured) 3139 return; 3140 3141 if(!i) pWin = pWin2; 3142 } 3143 } 3144 break; 3145 } 3146 3147 win->u.win.visibility = visibility; 3148 } 3149#endif 3150 3151 event.u.u.type = VisibilityNotify; 3152 event.u.visibility.window = pWin->drawable.id; 3153 event.u.visibility.state = visibility; 3154 DeliverEvents(pWin, &event, 1, NullWindow); 3155} 3156 3157#define RANDOM_WIDTH 32 3158 3159#ifndef NOLOGOHACK 3160static void DrawLogo( 3161 WindowPtr pWin 3162); 3163#endif 3164 3165_X_EXPORT int 3166dixSaveScreens(ClientPtr client, int on, int mode) 3167{ 3168 int rc, i, what, type; 3169 3170 if (on == SCREEN_SAVER_FORCER) 3171 { 3172 UpdateCurrentTimeIf(); 3173 lastDeviceEventTime = currentTime; 3174 if (mode == ScreenSaverReset) 3175 what = SCREEN_SAVER_OFF; 3176 else 3177 what = SCREEN_SAVER_ON; 3178 type = what; 3179 } 3180 else 3181 { 3182 what = on; 3183 type = what; 3184 if (what == screenIsSaved) 3185 type = SCREEN_SAVER_CYCLE; 3186 } 3187 3188 for (i = 0; i < screenInfo.numScreens; i++) { 3189 rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], 3190 DixShowAccess | DixHideAccess); 3191 if (rc != Success) 3192 return rc; 3193 } 3194 for (i = 0; i < screenInfo.numScreens; i++) 3195 { 3196 if (on == SCREEN_SAVER_FORCER) 3197 (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); 3198 if (savedScreenInfo[i].ExternalScreenSaver) 3199 { 3200 if ((*savedScreenInfo[i].ExternalScreenSaver) 3201 (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) 3202 continue; 3203 } 3204 if (type == screenIsSaved) 3205 continue; 3206 switch (type) { 3207 case SCREEN_SAVER_OFF: 3208 if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) 3209 { 3210 (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], 3211 what); 3212 } 3213 else if (HasSaverWindow (i)) 3214 { 3215 savedScreenInfo[i].pWindow = NullWindow; 3216 FreeResource(savedScreenInfo[i].wid, RT_NONE); 3217 } 3218 break; 3219 case SCREEN_SAVER_CYCLE: 3220 if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) 3221 { 3222 WindowPtr pWin = savedScreenInfo[i].pWindow; 3223 /* make it look like screen saver is off, so that 3224 * NotClippedByChildren will compute a clip list 3225 * for the root window, so miPaintWindow works 3226 */ 3227 screenIsSaved = SCREEN_SAVER_OFF; 3228#ifndef NOLOGOHACK 3229 if (logoScreenSaver) 3230 (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); 3231#endif 3232 (*pWin->drawable.pScreen->MoveWindow)(pWin, 3233 (short)(-(rand() % RANDOM_WIDTH)), 3234 (short)(-(rand() % RANDOM_WIDTH)), 3235 pWin->nextSib, VTMove); 3236#ifndef NOLOGOHACK 3237 if (logoScreenSaver) 3238 DrawLogo(pWin); 3239#endif 3240 screenIsSaved = SCREEN_SAVER_ON; 3241 } 3242 /* 3243 * Call the DDX saver in case it wants to do something 3244 * at cycle time 3245 */ 3246 else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) 3247 { 3248 (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], 3249 type); 3250 } 3251 break; 3252 case SCREEN_SAVER_ON: 3253 if (ScreenSaverBlanking != DontPreferBlanking) 3254 { 3255 if ((* screenInfo.screens[i]->SaveScreen) 3256 (screenInfo.screens[i], what)) 3257 { 3258 savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; 3259 continue; 3260 } 3261 if ((ScreenSaverAllowExposures != DontAllowExposures) && 3262 TileScreenSaver(i, SCREEN_IS_BLACK)) 3263 { 3264 savedScreenInfo[i].blanked = SCREEN_IS_BLACK; 3265 continue; 3266 } 3267 } 3268 if ((ScreenSaverAllowExposures != DontAllowExposures) && 3269 TileScreenSaver(i, SCREEN_IS_TILED)) 3270 { 3271 savedScreenInfo[i].blanked = SCREEN_IS_TILED; 3272 } 3273 else 3274 savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; 3275 break; 3276 } 3277 } 3278 screenIsSaved = what; 3279 if (mode == ScreenSaverReset) 3280 SetScreenSaverTimer(); 3281 return Success; 3282} 3283 3284_X_EXPORT int 3285SaveScreens(int on, int mode) 3286{ 3287 return dixSaveScreens(serverClient, on, mode); 3288} 3289 3290static Bool 3291TileScreenSaver(int i, int kind) 3292{ 3293 int j; 3294 int result; 3295 XID attributes[3]; 3296 Mask mask; 3297 WindowPtr pWin; 3298 CursorMetricRec cm; 3299 unsigned char *srcbits, *mskbits; 3300 CursorPtr cursor; 3301 XID cursorID = 0; 3302 int attri; 3303 3304 mask = 0; 3305 attri = 0; 3306 switch (kind) { 3307 case SCREEN_IS_TILED: 3308 switch (WindowTable[i]->backgroundState) { 3309 case BackgroundPixel: 3310 attributes[attri++] = WindowTable[i]->background.pixel; 3311 mask |= CWBackPixel; 3312 break; 3313 case BackgroundPixmap: 3314 attributes[attri++] = None; 3315 mask |= CWBackPixmap; 3316 break; 3317 default: 3318 break; 3319 } 3320 break; 3321 case SCREEN_IS_BLACK: 3322 attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; 3323 mask |= CWBackPixel; 3324 break; 3325 } 3326 mask |= CWOverrideRedirect; 3327 attributes[attri++] = xTrue; 3328 3329 /* 3330 * create a blank cursor 3331 */ 3332 3333 cm.width=16; 3334 cm.height=16; 3335 cm.xhot=8; 3336 cm.yhot=8; 3337 srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); 3338 mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); 3339 if (!srcbits || !mskbits) 3340 { 3341 xfree(srcbits); 3342 xfree(mskbits); 3343 cursor = 0; 3344 } 3345 else 3346 { 3347 for (j=0; j<BitmapBytePad(32)*16; j++) 3348 srcbits[j] = mskbits[j] = 0x0; 3349 result = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 0, 0, 0, 0, 0, 0, 3350 &cursor, serverClient, (XID)0); 3351 if (cursor) 3352 { 3353 cursorID = FakeClientID(0); 3354 if (AddResource (cursorID, RT_CURSOR, (pointer) cursor)) 3355 { 3356 attributes[attri] = cursorID; 3357 mask |= CWCursor; 3358 } 3359 else 3360 cursor = 0; 3361 } 3362 else 3363 { 3364 xfree (srcbits); 3365 xfree (mskbits); 3366 } 3367 } 3368 3369 pWin = savedScreenInfo[i].pWindow = 3370 CreateWindow(savedScreenInfo[i].wid, 3371 WindowTable[i], 3372 -RANDOM_WIDTH, -RANDOM_WIDTH, 3373 (unsigned short)screenInfo.screens[i]->width + RANDOM_WIDTH, 3374 (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, 3375 0, InputOutput, mask, attributes, 0, serverClient, 3376 wVisual (WindowTable[i]), &result); 3377 3378 if (cursor) 3379 FreeResource (cursorID, RT_NONE); 3380 3381 if (!pWin) 3382 return FALSE; 3383 3384 if (!AddResource(pWin->drawable.id, RT_WINDOW, 3385 (pointer)savedScreenInfo[i].pWindow)) 3386 return FALSE; 3387 3388 if (mask & CWBackPixmap) 3389 { 3390 MakeRootTile (pWin); 3391 (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); 3392 } 3393 MapWindow(pWin, serverClient); 3394#ifndef NOLOGOHACK 3395 if (kind == SCREEN_IS_TILED && logoScreenSaver) 3396 DrawLogo(pWin); 3397#endif 3398 return TRUE; 3399} 3400 3401/* 3402 * FindWindowWithOptional 3403 * 3404 * search ancestors of the given window for an entry containing 3405 * a WindowOpt structure. Assumptions: some parent will 3406 * contain the structure. 3407 */ 3408 3409_X_EXPORT WindowPtr 3410FindWindowWithOptional (WindowPtr w) 3411{ 3412 do 3413 w = w->parent; 3414 while (!w->optional); 3415 return w; 3416} 3417 3418/* 3419 * CheckWindowOptionalNeed 3420 * 3421 * check each optional entry in the given window to see if 3422 * the value is satisfied by the default rules. If so, 3423 * release the optional record 3424 */ 3425 3426_X_EXPORT void 3427CheckWindowOptionalNeed (WindowPtr w) 3428{ 3429 WindowOptPtr optional; 3430 WindowOptPtr parentOptional; 3431 3432 if (!w->parent) 3433 return; 3434 optional = w->optional; 3435 if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) 3436 return; 3437 if (optional->otherEventMasks != 0) 3438 return; 3439 if (optional->otherClients != NULL) 3440 return; 3441 if (optional->passiveGrabs != NULL) 3442 return; 3443 if (optional->userProps != NULL) 3444 return; 3445 if (optional->backingBitPlanes != ~0L) 3446 return; 3447 if (optional->backingPixel != 0) 3448 return; 3449 if (optional->boundingShape != NULL) 3450 return; 3451 if (optional->clipShape != NULL) 3452 return; 3453 if (optional->inputShape != NULL) 3454 return; 3455 if (optional->inputMasks != NULL) 3456 return; 3457 if (optional->deviceCursors != NULL) 3458 { 3459 DevCursNodePtr pNode = optional->deviceCursors; 3460 while(pNode) 3461 { 3462 if (pNode->cursor != None) 3463 return; 3464 pNode = pNode->next; 3465 } 3466 } 3467 if (optional->access.nperm != 0 || 3468 optional->access.ndeny != 0) 3469 return; 3470 3471 if (optional->geMasks != NULL) 3472 return; 3473 3474 parentOptional = FindWindowWithOptional(w)->optional; 3475 if (optional->visual != parentOptional->visual) 3476 return; 3477 if (optional->cursor != None && 3478 (optional->cursor != parentOptional->cursor || 3479 w->parent->cursorIsNone)) 3480 return; 3481 if (optional->colormap != parentOptional->colormap) 3482 return; 3483 DisposeWindowOptional (w); 3484} 3485 3486/* 3487 * MakeWindowOptional 3488 * 3489 * create an optional record and initialize it with the default 3490 * values. 3491 */ 3492 3493_X_EXPORT Bool 3494MakeWindowOptional (WindowPtr pWin) 3495{ 3496 WindowOptPtr optional; 3497 WindowOptPtr parentOptional; 3498 3499 if (pWin->optional) 3500 return TRUE; 3501 optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); 3502 if (!optional) 3503 return FALSE; 3504 optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; 3505 optional->otherEventMasks = 0; 3506 optional->otherClients = NULL; 3507 optional->passiveGrabs = NULL; 3508 optional->userProps = NULL; 3509 optional->backingBitPlanes = ~0L; 3510 optional->backingPixel = 0; 3511 optional->boundingShape = NULL; 3512 optional->clipShape = NULL; 3513 optional->inputShape = NULL; 3514 optional->inputMasks = NULL; 3515 optional->deviceCursors = NULL; 3516 3517 optional->geMasks = 3518 (GenericClientMasksPtr)xalloc(sizeof(GenericClientMasksRec)); 3519 if (!optional->geMasks) 3520 { 3521 xfree(optional); 3522 return FALSE; 3523 } else { 3524 int i; 3525 optional->geMasks->geClients = 0; 3526 for (i = 0; i < MAXEXTENSIONS; i++) 3527 optional->geMasks->eventMasks[i] = 0; 3528 } 3529 3530 optional->access.nperm = 0; 3531 optional->access.ndeny = 0; 3532 optional->access.perm = NULL; 3533 optional->access.deny = NULL; 3534 optional->access.defaultRule = 0; 3535 parentOptional = FindWindowWithOptional(pWin)->optional; 3536 optional->visual = parentOptional->visual; 3537 if (!pWin->cursorIsNone) 3538 { 3539 optional->cursor = parentOptional->cursor; 3540 optional->cursor->refcnt++; 3541 } 3542 else 3543 { 3544 optional->cursor = None; 3545 } 3546 optional->colormap = parentOptional->colormap; 3547 pWin->optional = optional; 3548 return TRUE; 3549} 3550 3551/* 3552 * Changes the cursor struct for the given device and the given window. 3553 * A cursor that does not have a device cursor set will use whatever the 3554 * standard cursor is for the window. If all devices have a cursor set, 3555 * changing the window cursor (e.g. using XDefineCursor()) will not have any 3556 * visible effect. Only when one of the device cursors is set to None again, 3557 * this device's cursor will display the changed standard cursor. 3558 * 3559 * CursorIsNone of the window struct is NOT modified if you set a device 3560 * cursor. 3561 * 3562 * Assumption: If there is a node for a device in the list, the device has a 3563 * cursor. If the cursor is set to None, it is inherited by the parent. 3564 */ 3565_X_EXPORT int 3566ChangeWindowDeviceCursor(WindowPtr pWin, 3567 DeviceIntPtr pDev, 3568 CursorPtr pCursor) 3569{ 3570 DevCursNodePtr pNode, pPrev; 3571 CursorPtr pOldCursor = NULL; 3572 ScreenPtr pScreen; 3573 WindowPtr pChild; 3574 3575 if (!pWin->optional && !MakeWindowOptional(pWin)) 3576 return BadAlloc; 3577 3578 /* 1) Check if window has device cursor set 3579 * Yes: 1.1) swap cursor with given cursor if parent does not have same 3580 * cursor, free old cursor 3581 * 1.2) free old cursor, use parent cursor 3582 * No: 1.1) add node to beginning of list. 3583 * 1.2) add cursor to node if parent does not have same cursor 3584 * 1.3) use parent cursor if parent does not have same cursor 3585 * 2) Patch up children if child has a devcursor 3586 * 2.1) if child has cursor None, it inherited from parent, set to old 3587 * cursor 3588 * 2.2) if child has same cursor as new cursor, remove and set to None 3589 */ 3590 3591 pScreen = pWin->drawable.pScreen; 3592 3593 if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev)) 3594 { 3595 /* has device cursor */ 3596 3597 if (pNode->cursor == pCursor) 3598 return Success; 3599 3600 pOldCursor = pNode->cursor; 3601 3602 if (!pCursor) /* remove from list */ 3603 { 3604 if(pPrev) 3605 pPrev->next = pNode->next; 3606 else 3607 /* first item in list */ 3608 pWin->optional->deviceCursors = pNode->next; 3609 3610 xfree(pNode); 3611 return Success; 3612 } 3613 3614 } else 3615 { 3616 /* no device cursor yet */ 3617 DevCursNodePtr pNewNode; 3618 3619 if (!pCursor) 3620 return Success; 3621 3622 pNewNode = (DevCursNodePtr)xalloc(sizeof(DevCursNodeRec)); 3623 pNewNode->dev = pDev; 3624 pNewNode->next = pWin->optional->deviceCursors; 3625 pWin->optional->deviceCursors = pNewNode; 3626 pNode = pNewNode; 3627 3628 } 3629 3630 if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor)) 3631 pNode->cursor = None; 3632 else 3633 { 3634 pNode->cursor = pCursor; 3635 pCursor->refcnt++; 3636 } 3637 3638 pNode = pPrev = NULL; 3639 /* fix up children */ 3640 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) 3641 { 3642 if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) 3643 { 3644 if (pNode->cursor == None) /* inherited from parent */ 3645 { 3646 pNode->cursor = pOldCursor; 3647 pOldCursor->refcnt++; 3648 } else if (pNode->cursor == pCursor) 3649 { 3650 pNode->cursor = None; 3651 FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */ 3652 } 3653 } 3654 } 3655 3656 if (pWin->realized) 3657 WindowHasNewCursor(pWin); 3658 3659 if (pOldCursor) 3660 FreeCursor(pOldCursor, (Cursor)0); 3661 3662 /* FIXME: We SHOULD check for an error value here XXX 3663 (comment taken from ChangeWindowAttributes) */ 3664 (*pScreen->ChangeWindowAttributes)(pWin, CWCursor); 3665 3666 return Success; 3667} 3668 3669/* Get device cursor for given device or None if none is set */ 3670_X_EXPORT CursorPtr 3671WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev) 3672{ 3673 DevCursorList pList; 3674 3675 if (!pWin->optional || !pWin->optional->deviceCursors) 3676 return NULL; 3677 3678 pList = pWin->optional->deviceCursors; 3679 3680 while(pList) 3681 { 3682 if (pList->dev == pDev) 3683 { 3684 if (pList->cursor == None) /* inherited from parent */ 3685 return WindowGetDeviceCursor(pWin->parent, pDev); 3686 else 3687 return pList->cursor; 3688 } 3689 pList = pList->next; 3690 } 3691 return NULL; 3692} 3693 3694/* Searches for a DevCursorNode for the given window and device. If one is 3695 * found, return True and set pNode and pPrev to the node and to the node 3696 * before the node respectively. Otherwise return False. 3697 * If the device is the first in list, pPrev is set to NULL. 3698 */ 3699static Bool 3700WindowSeekDeviceCursor(WindowPtr pWin, 3701 DeviceIntPtr pDev, 3702 DevCursNodePtr* pNode, 3703 DevCursNodePtr* pPrev) 3704{ 3705 DevCursorList pList; 3706 3707 if (!pWin->optional) 3708 return FALSE; 3709 3710 pList = pWin->optional->deviceCursors; 3711 3712 if (pList && pList->dev == pDev) 3713 { 3714 *pNode = pList; 3715 *pPrev = NULL; 3716 return TRUE; 3717 } 3718 3719 while(pList) 3720 { 3721 if (pList->next) 3722 { 3723 if (pList->next->dev == pDev) 3724 { 3725 *pNode = pList->next; 3726 *pPrev = pList; 3727 return TRUE; 3728 } 3729 } 3730 pList = pList->next; 3731 } 3732 return FALSE; 3733} 3734 3735/* Return True if a parent has the same device cursor set or False if 3736 * otherwise 3737 */ 3738static Bool 3739WindowParentHasDeviceCursor(WindowPtr pWin, 3740 DeviceIntPtr pDev, 3741 CursorPtr pCursor) 3742{ 3743 WindowPtr pParent; 3744 DevCursNodePtr pParentNode, pParentPrev; 3745 3746 pParent = pWin->parent; 3747 while(pParent) 3748 { 3749 if (WindowSeekDeviceCursor(pParent, pDev, 3750 &pParentNode, &pParentPrev)) 3751 { 3752 /* if there is a node in the list, the win has a dev cursor */ 3753 if (!pParentNode->cursor) /* inherited. loop needs to cont. */ 3754 { 3755 } else if (pParentNode->cursor == pCursor) /* inherit */ 3756 return TRUE; 3757 else /* different cursor */ 3758 return FALSE; 3759 } 3760 else 3761 /* parent does not have a device cursor for our device */ 3762 return FALSE; 3763 } 3764 return FALSE; 3765} 3766 3767#ifndef NOLOGOHACK 3768static void 3769DrawLogo(WindowPtr pWin) 3770{ 3771 DrawablePtr pDraw; 3772 ScreenPtr pScreen; 3773 int x, y; 3774 unsigned int width, height, size; 3775 GC *pGC; 3776 int thin, gap, d31; 3777 DDXPointRec poly[4]; 3778 ChangeGCVal fore[2], back[2]; 3779 xrgb rgb[2]; 3780 BITS32 fmask, bmask; 3781 ColormapPtr cmap; 3782 3783 pDraw = (DrawablePtr)pWin; 3784 pScreen = pDraw->pScreen; 3785 x = -pWin->origin.x; 3786 y = -pWin->origin.y; 3787 width = pScreen->width; 3788 height = pScreen->height; 3789 pGC = GetScratchGC(pScreen->rootDepth, pScreen); 3790 if (!pGC) 3791 return; 3792 3793 if ((rand() % 100) <= 17) /* make the probability for white fairly low */ 3794 fore[0].val = pScreen->whitePixel; 3795 else 3796 fore[0].val = pScreen->blackPixel; 3797 if ((pWin->backgroundState == BackgroundPixel) && 3798 (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { 3799 Pixel querypixels[2]; 3800 3801 querypixels[0] = fore[0].val; 3802 querypixels[1] = pWin->background.pixel; 3803 QueryColors(cmap, 2, querypixels, rgb); 3804 if ((rgb[0].red == rgb[1].red) && 3805 (rgb[0].green == rgb[1].green) && 3806 (rgb[0].blue == rgb[1].blue)) { 3807 if (fore[0].val == pScreen->blackPixel) 3808 fore[0].val = pScreen->whitePixel; 3809 else 3810 fore[0].val = pScreen->blackPixel; 3811 } 3812 } 3813 fore[1].val = FillSolid; 3814 fmask = GCForeground|GCFillStyle; 3815 if (pWin->backgroundState == BackgroundPixel) { 3816 back[0].val = pWin->background.pixel; 3817 back[1].val = FillSolid; 3818 bmask = GCForeground|GCFillStyle; 3819 } else { 3820 back[0].val = 0; 3821 back[1].val = 0; 3822 dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, 3823 NULL, back); 3824 back[0].val = FillTiled; 3825 back[1].ptr = pWin->background.pixmap; 3826 bmask = GCFillStyle|GCTile; 3827 } 3828 3829 /* should be the same as the reference function XmuDrawLogo() */ 3830 3831 size = width; 3832 if (height < width) 3833 size = height; 3834 size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); 3835 size &= ~1; 3836 x += rand() % (width - size); 3837 y += rand() % (height - size); 3838 3839/* 3840 * Draw what will be the thin strokes. 3841 * 3842 * ----- 3843 * / / 3844 * / / 3845 * / / 3846 * / / 3847 * /____/ 3848 * d 3849 * 3850 * Point d is 9/44 (~1/5) of the way across. 3851 */ 3852 3853 thin = (size / 11); 3854 if (thin < 1) thin = 1; 3855 gap = (thin+3) / 4; 3856 d31 = thin + thin + gap; 3857 poly[0].x = x + size; poly[0].y = y; 3858 poly[1].x = x + size-d31; poly[1].y = y; 3859 poly[2].x = x + 0; poly[2].y = y + size; 3860 poly[3].x = x + d31; poly[3].y = y + size; 3861 dixChangeGC(NullClient, pGC, fmask, NULL, fore); 3862 ValidateGC(pDraw, pGC); 3863 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); 3864 3865/* 3866 * Erase area not needed for lower thin stroke. 3867 * 3868 * ------ 3869 * / / 3870 * / __ / 3871 * / / / 3872 * / / / 3873 * /__/__/ 3874 */ 3875 3876 poly[0].x = x + d31/2; poly[0].y = y + size; 3877 poly[1].x = x + size / 2; poly[1].y = y + size/2; 3878 poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; 3879 poly[3].x = x + d31; poly[3].y = y + size; 3880 dixChangeGC(NullClient, pGC, bmask, NULL, back); 3881 ValidateGC(pDraw, pGC); 3882 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); 3883 3884/* 3885 * Erase area not needed for upper thin stroke. 3886 * 3887 * ------ 3888 * / / / 3889 * /--/ / 3890 * / / 3891 * / / 3892 * /_____/ 3893 */ 3894 3895 poly[0].x = x + size - d31/2; poly[0].y = y; 3896 poly[1].x = x + size / 2; poly[1].y = y + size/2; 3897 poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; 3898 poly[3].x = x + size - d31; poly[3].y = y; 3899 ValidateGC(pDraw, pGC); 3900 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); 3901 3902/* 3903 * Draw thick stroke. 3904 * Point b is 1/4 of the way across. 3905 * 3906 * b 3907 * ----- 3908 * \ \ 3909 * \ \ 3910 * \ \ 3911 * \ \ 3912 * \____\ 3913 */ 3914 3915 poly[0].x = x; poly[0].y = y; 3916 poly[1].x = x + size/4; poly[1].y = y; 3917 poly[2].x = x + size; poly[2].y = y + size; 3918 poly[3].x = x + size - size/4; poly[3].y = y + size; 3919 dixChangeGC(NullClient, pGC, fmask, NULL, fore); 3920 ValidateGC(pDraw, pGC); 3921 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); 3922 3923/* 3924 * Erase to create gap. 3925 * 3926 * / 3927 * / 3928 * / 3929 * / 3930 * / 3931 */ 3932 3933 poly[0].x = x + size- thin; poly[0].y = y; 3934 poly[1].x = x + size-( thin+gap); poly[1].y = y; 3935 poly[2].x = x + thin; poly[2].y = y + size; 3936 poly[3].x = x + thin + gap; poly[3].y = y + size; 3937 dixChangeGC(NullClient, pGC, bmask, NULL, back); 3938 ValidateGC(pDraw, pGC); 3939 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); 3940 3941 FreeScratchGC(pGC); 3942} 3943 3944#endif 3945