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