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