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