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