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