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