/*********************************************************** Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, and the Massachusetts Institute of Technology, Cambridge, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Digital or MIT not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* $Header: window.c,v 1.144 87/06/16 15:27:22 toddb Exp $ */ #include "X.h" #define NEED←REPLIES #define NEED←EVENTS #include "Xproto.h" #include "misc.h" #include "scrnintstr.h" #include "os.h" #include "regionstr.h" #include "windowstr.h" #include "input.h" #include "resource.h" #include "colormapst.h" #include "cursorstr.h" #include "dixstruct.h" #include "gcstruct.h" #include "opaque.h" /****** * Window stuff for server * * CreateRootWindow, CreateWindow, ChangeWindowAttributes, * GetWindowAttributes, DeleteWindow, DestroySubWindows, * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, * ******/ int ←back[16] = {0x8888, 0x2222, 0x4444, 0x1111, 0x8888, 0x2222, 0x4444, 0x1111, 0x8888, 0x2222, 0x4444, 0x1111, 0x8888, 0x2222, 0x4444, 0x1111}; typedef struct ←ScreenSaverStuff { WindowPtr pWindow; XID wid; XID cid; BYTE blanked; } ScreenSaverStuffRec; #define SCREEN←IS←BLANKED 0 #define SCREEN←IS←TILED 1 #define SCREEN←ISNT←SAVED 2 extern int ScreenSaverBlanking, ScreenSaverAllowExposures; int screenIsSaved = FALSE; ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; extern WindowRec WindowTable[]; extern void (* ReplySwapVector[256]) (); #define INPUTONLY←LEGAL←MASK (CWWinGravity | CWEventMask | \ CWDontPropagate | CWCursor ) /****** * PrintWindowTree * For debugging only ******/ int PrintChildren(p1, indent) WindowPtr p1; int indent; { WindowPtr p2; int i; while (p1) { p2 = p1->firstChild; for (i=0; i<indent; i++) ErrorF( " "); ErrorF( "%x\n", p1->wid); miprintRects(p1->clipList); PrintChildren(p2, indent+4); p1 = p1->nextSib; } } PrintWindowTree() { int i; WindowPtr pWin, p1; for (i=0; i<screenInfo.numScreens; i++) { ErrorF( "WINDOW %d\n", i); pWin = &WindowTable[i]; miprintRects(pWin->clipList); p1 = pWin->firstChild; PrintChildren(p1, 4); } } /***** * WalkTree * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on * each window. If FUNC returns WT←WALKCHILDREN, traverse the children, * if it returns WT←DONTWALKCHILDREN, dont. If it returns WT←STOPWALKING * exit WalkTree. Does depth-first traverse. *****/ int TraverseTree(pWin, func, data) WindowPtr pWin; int (*func)(); pointer data; { int result; WindowPtr pChild; if (!pWin) return(WT←NOMATCH); result = (* func)(pWin, data); if (result == WT←STOPWALKING) return(WT←STOPWALKING); if (result == WT←WALKCHILDREN) for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) if (TraverseTree(pChild, func,data) == WT←STOPWALKING) return(WT←STOPWALKING); return(WT←NOMATCH); } int WalkTree(pScreen, func, data) ScreenPtr pScreen; int (* func)(); char *data; { WindowPtr pWin; pWin = &WindowTable[pScreen->myNum]; return(TraverseTree(pWin, func, (pointer)data)); } /***** * DoObscures(pWin) * *****/ void DoObscures(pWin) WindowPtr pWin; { WindowPtr pSib; if (!pWin->backStorage || (pWin->backingStore == NotUseful)) return ; if ((* pWin->drawable.pScreen->RegionNotEmpty)(pWin->backStorage->obscured)) { (*pWin->backStorage->SaveDoomedAreas)( pWin ); (* pWin->drawable.pScreen->RegionEmpty)(pWin->backStorage->obscured); } pSib = pWin->firstChild; while (pSib) { DoObscures(pSib); pSib = pSib->nextSib; } } /***** * HandleExposures(pWin) * starting at pWin, draw background in any windows that have exposure * regions, translate the regions, restore any backing store, * and then send any regions stille xposed to the client *****/ /* NOTE the order of painting and restoration needs to be different, to avoid an extra repaint of the background. --rgd */ void HandleExposures(pWin) WindowPtr pWin; { WindowPtr pSib; if ((* pWin->drawable.pScreen->RegionNotEmpty)(pWin->borderExposed)) { (*pWin->PaintWindowBorder)(pWin, pWin->borderExposed, PW←BORDER); (* pWin->drawable.pScreen->RegionEmpty)(pWin->borderExposed); } (* pWin->drawable.pScreen->WindowExposures)(pWin); pSib = pWin->firstChild; while (pSib) { HandleExposures(pSib); pSib = pSib->nextSib; } } static void InitProcedures(pWin) WindowPtr pWin; { #ifdef DEBUG void (**j) (); for (j = &pWin->PaintWindowBackground; j < &pWin->ClearToBackground; j++ ) *j = (void (*) ())NotImplemented; #endif /* DEBUG */ } static void SetWindowToDefaults(pWin, pScreen) WindowPtr pWin; ScreenPtr pScreen; { pWin->prevSib = NullWindow; pWin->firstChild = NullWindow; pWin->lastChild = NullWindow; /* pWin->drawable.lastGC = (pointer)NULL; */ pWin->userProps = (PropertyPtr)NULL; pWin->backingStore = NotUseful; pWin->backStorage = (BackingStorePtr) NULL; pWin->mapped = 0; /* off */ pWin->realized = 0; /* off */ pWin->viewable = 0; pWin->overrideRedirect = FALSE; pWin->saveUnder = FALSE; pWin->bitGravity = ForgetGravity; pWin->winGravity = NorthWestGravity; pWin->backingBitPlanes = -1; pWin->backingPixel = 0; pWin->eventMask = 0; pWin->dontPropagateMask = 0; pWin->allEventMasks = 0; pWin->deliverableEvents = 0; pWin->otherClients = (pointer)NULL; pWin->passiveGrabs = (pointer)NULL; pWin->colormap = (Colormap)None; /* None */ pWin->exposed = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); pWin->borderExposed = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); } static void MakeRootCursor(pWin) WindowPtr pWin; { unsigned char *srcbits, *mskbits; int i; if (rootCursor) { pWin->cursor = rootCursor; rootCursor->refcnt++; } else { CursorMetricRec cm; cm.width=32; cm.height=16; cm.xhot=8; cm.yhot=8; srcbits = (unsigned char *)Xalloc( PixmapBytePad(32, 1)*16); mskbits = (unsigned char *)Xalloc( PixmapBytePad(32, 1)*16); for (i=0; i<PixmapBytePad(32, 1)*16; i++) { srcbits[i] = mskbits[i] = 0xff; } pWin->cursor = AllocCursor( srcbits, mskbits, &cm, ~0, ~0, ~0, 0, 0, 0); } } static void MakeRootTile(pWin) WindowPtr pWin; { ScreenPtr pScreen = pWin->drawable.pScreen; GCPtr pGC; pWin->backgroundTile = (*pScreen->CreatePixmap)(pScreen, 16, 16, pScreen->rootDepth); pGC = GetScratchGC(pScreen->rootDepth, pScreen); { CARD32 attributes[3]; attributes[0] = pScreen->whitePixel; attributes[1] = pScreen->blackPixel; attributes[2] = FALSE; ChangeGC(pGC, GCForeground | GCBackground | GCGraphicsExposures, attributes); } ValidateGC((DrawablePtr)pWin->backgroundTile, pGC); (*pGC->PutImage)(pWin->backgroundTile, pGC, pScreen->rootDepth, 0, 0, 16, 16, 0, XYBitmap, ←back); pWin->backgroundTile->refcnt++; FreeScratchGC(pGC); } /***** * CreateRootWindow * Makes a window at initialization time for specified screen *****/ void CreateRootWindow(screen) int screen; { WindowPtr pWin; BoxRec box; ScreenPtr pScreen; int i; savedScreenInfo[screen].pWindow = NULL; savedScreenInfo[screen].wid = FakeClientID(0); savedScreenInfo[screen].cid = FakeClientID(0); screenIsSaved = SCREEN←SAVER←OFF; pWin = &WindowTable[screen]; pScreen = &screenInfo.screen[screen]; InitProcedures(pWin); pWin->drawable.pScreen = pScreen; pWin->drawable.type = DRAWABLE←WINDOW; pWin->drawable.depth = pScreen->rootDepth; pWin->parent = NullWindow; SetWindowToDefaults(pWin, pScreen); pWin->nextSib = NullWindow; MakeRootCursor(pWin); pWin->client = serverClient; /* since belongs to server */ pWin->wid = FakeClientID(0); pWin->clientWinSize.x = pWin->clientWinSize.y = 0; pWin->clientWinSize.height = screenInfo.screen[screen].height; pWin->clientWinSize.width = screenInfo.screen[screen].width; pWin->absCorner.x = pWin->absCorner.y = 0; pWin->oldAbsCorner.x = pWin->oldAbsCorner.y = 0; box.x1 = 0; box.y1 = 0; box.x2 = screenInfo.screen[screen].width ; box.y2 = screenInfo.screen[screen].height; pWin->clipList = (* pScreen->RegionCreate)(&box, 1); pWin->winSize = (* pScreen->RegionCreate)(&box, 1); pWin->borderSize = (* pScreen->RegionCreate)(&box, 1); pWin->borderClip = (* pScreen->RegionCreate)(&box, 1); pWin->class = InputOutput; pWin->visual = pScreen->rootVisual; pWin->backgroundPixel = pScreen->whitePixel; pWin->borderPixel = pScreen->blackPixel; pWin->borderWidth = 0; AddResource(pWin->wid, RT←WINDOW, (pointer)pWin, DeleteWindow, RC←CORE); MakeRootTile(pWin); pWin->borderTile = (PixmapPtr)USE←BORDER←PIXEL; /* re-validate GC for use with root Window */ (*pScreen->CreateWindow)(pWin); MapWindow(pWin, DONT←HANDLE←EXPOSURES, BITS←DISCARDED, DONT←SEND←NOTIFICATION, serverClient); (*pScreen->ChangeWindowAttributes)(pWin, (long)CWBackPixmap | CWBorderPixel); (*pWin->PaintWindowBackground)(pWin, pWin->clipList, PW←BACKGROUND); EventSelectForWindow(pWin, serverClient, (Mask) 0); } /***** * DestroyRootWindow * Cleans up the root window at re-initialization time. *****/ void DestroyRootWindow(screen) int screen; { WindowPtr pWin; pWin = &WindowTable[screen]; bzero((char *)pWin, sizeof (WindowRec)); } /***** * CreateWindow * Makes a window in response to client request * XXX What about depth of inputonly windows -- should be 0 *****/ WindowPtr CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist, depth, client, visual, error) Window wid; WindowPtr pParent; /* already looked up in table to do error checking*/ short x,y; unsigned short w, h, bw; int class; long vmask; long *vlist; int depth; ClientPtr client; VisualID visual; int *error; { WindowPtr pWin; ScreenPtr pScreen; BoxRec box; xEvent event; int idepth, ivisual; Bool fOK; DepthPtr pDepth; if ((class != InputOnly) && (pParent->class == InputOnly)) { *error = BadMatch; return (WindowPtr)NULL; } if ((class == InputOnly) && ((bw != 0) || (depth != 0))) { *error = BadMatch; return (WindowPtr)NULL; } pScreen = pParent->drawable.pScreen; /* Find out if the depth and visual are acceptable for this Screen */ fOK = FALSE; if ((class == InputOutput && depth == 0) || (class == InputOnly) || (class == CopyFromParent)) depth = pParent->drawable.depth; if (visual == CopyFromParent) visual = pParent->visual; else { for(idepth = 0; idepth < pScreen->numDepths; idepth++) { pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; if (depth == pDepth->depth) { for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) { if (visual == pDepth->vids[ivisual]) fOK = TRUE; } } } if (!fOK) { *error = BadMatch; return (WindowPtr)NULL; } } pWin = (WindowPtr ) Xalloc( sizeof(WindowRec) ); if (!pWin) { *error = BadAlloc; return (WindowPtr)NULL; } InitProcedures(pWin); pWin->drawable = pParent->drawable; if (class == InputOutput) pWin->drawable.depth = depth; else if (class == InputOnly) pWin->drawable.type = UNDRAWABLE←WINDOW; pWin->wid = wid; pWin->client = client; pWin->visual = visual; SetWindowToDefaults(pWin, pScreen); pWin->cursor = (CursorPtr)None; if (class == CopyFromParent) pWin->class = pParent->class; else pWin->class = class; pWin->borderWidth = bw; pWin->backgroundTile = (PixmapPtr)None; pWin->backgroundPixel = pScreen->whitePixel; if ((pWin->drawable.depth != pParent->drawable.depth) && (! (vmask & (CWBorderPixmap | CWBorderPixel)))) { Xfree(pWin); *error = BadMatch; return (WindowPtr)NULL; } if (vmask & (CWBorderPixmap | CWBorderPixel)) /* it will just get fixed in ChangeWindowAttributes */ pWin->borderTile = (PixmapPtr)NULL; else { /* this is WRONG!! XXX */ /* should be actually copied */ pWin->borderTile = pParent->borderTile; if (IS←VALID←PIXMAP(pParent->borderTile)) pParent->borderTile->refcnt++; } pWin->borderPixel = pParent->borderPixel; pWin->visibility = VisibilityFullyObscured; pWin->clientWinSize.x = x + bw; pWin->clientWinSize.y = y + bw; pWin->clientWinSize.height = h; pWin->clientWinSize.width = w; pWin->absCorner.x = pWin->oldAbsCorner.x = pParent->absCorner.x + x + bw; pWin->absCorner.y = pWin->oldAbsCorner.y = pParent->absCorner.y + y + bw; /* set up clip list correctly for unobscured WindowPtr */ pWin->clipList = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); pWin->borderClip = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); box.x1 = pWin->absCorner.x; box.y1 = pWin->absCorner.y; box.x2 = box.x1 + w; box.y2 = box.y1 + h; pWin->winSize = (* pScreen->RegionCreate)(&box, 1); (* pScreen->Intersect)(pWin->winSize, pWin->winSize, pParent->winSize); if (bw) { box.x1 -= bw; box.y1 -= bw; box.x2 += bw; box.y2 += bw; pWin->borderSize = (* pScreen->RegionCreate)(&box, 1); (* pScreen->Intersect)(pWin->borderSize, pWin->borderSize, pParent->winSize); } else { pWin->borderSize = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); (* pScreen->RegionCopy)(pWin->borderSize, pWin->winSize); } pWin->parent = pParent; if ((screenIsSaved == SCREEN←SAVER←ON) && (pParent == &WindowTable[pScreen->myNum]) && (pParent->firstChild) && (savedScreenInfo[pScreen->myNum].blanked == SCREEN←IS←TILED)) { WindowPtr pFirst = pParent->firstChild; pWin->nextSib = pFirst->nextSib; if (pFirst->nextSib) pFirst->nextSib->prevSib = pWin; else pParent->lastChild = pWin; pFirst->nextSib = pWin; pWin->prevSib = pFirst; } else { pWin->nextSib = pParent->firstChild; if (pParent->firstChild) pParent->firstChild->prevSib = pWin; else pParent->lastChild = pWin; pParent->firstChild = pWin; } (*pScreen->CreateWindow)(pWin); (*pScreen->PositionWindow)(pWin, pWin->absCorner.x, pWin->absCorner.y); if (! (vmask & CWEventMask)) EventSelectForWindow(pWin, client, (Mask) 0); if (vmask) *error = ChangeWindowAttributes(pWin, (unsigned long)vmask, vlist, pWin->client); else *error = Success; WindowHasNewCursor( pWin); event.u.u.type = CreateNotify; event.u.createNotify.window = wid; event.u.createNotify.parent = pParent->wid; event.u.createNotify.x = x; event.u.createNotify.y = y; event.u.createNotify.width = w; event.u.createNotify.height = h; event.u.createNotify.borderWidth = bw; event.u.createNotify.override = pWin->overrideRedirect; DeliverEvents(pWin->parent, &event, 1, NullWindow); return pWin; } /***** * DeleteWindow * Deletes child of window then window itself *****/ static void FreeWindowResources(pWin) WindowPtr pWin; { ScreenPtr pScreen; void (* proc)(); pScreen = pWin->drawable.pScreen; DeleteWindowFromAnySaveSet((pointer)pWin); DeleteWindowFromAnySelections(pWin); DeleteWindowFromAnyEvents(pWin, TRUE); proc = pScreen->RegionDestroy; (* proc)(pWin->clipList); (* proc)(pWin->winSize); (* proc)(pWin->borderClip); (* proc)(pWin->borderSize); (* proc)(pWin->exposed); (* proc)(pWin->borderExposed); if (pWin->backStorage) { (* proc)(pWin->backStorage->obscured); Xfree(pWin->backStorage); } (* pScreen->DestroyPixmap)(pWin->borderTile); (* pScreen->DestroyPixmap)(pWin->backgroundTile); if (pWin->cursor != (CursorPtr)None) FreeCursor( pWin->cursor, 0); DeleteAllWindowProperties(pWin); (* pScreen->DestroyWindow)(pWin); } static void CrushTree(pWin) WindowPtr pWin; { WindowPtr pSib; xEvent event; if (!pWin) return ; while (pWin) { FreeResource(pWin->wid, RC←CORE); pSib = pWin->nextSib; pWin->realized = FALSE; pWin->viewable = FALSE; (* pWin->drawable.pScreen->UnrealizeWindow)(pWin); FreeWindowResources(pWin); CrushTree(pWin->firstChild); event.u.u.type = DestroyNotify; event.u.destroyNotify.window = pWin->wid; DeliverEvents(pWin, &event, 1, NullWindow); Xfree(pWin); pWin = pSib; } } DeleteWindow(pWin, wid) WindowPtr pWin; int wid; { WindowPtr pParent; xEvent event; UnmapWindow(pWin, HANDLE←EXPOSURES, SEND←NOTIFICATION, FALSE); event.u.u.type = DestroyNotify; event.u.destroyNotify.window = pWin->wid; DeliverEvents(pWin, &event, 1, NullWindow); CrushTree(pWin->firstChild); pParent = pWin->parent; FreeWindowResources(pWin); if (pParent) { if (pParent->firstChild == pWin) pParent->firstChild = pWin->nextSib; if (pParent->lastChild == pWin) pParent->lastChild = pWin->prevSib; if (pWin->nextSib) pWin->nextSib->prevSib = pWin->prevSib; if (pWin->prevSib) pWin->prevSib->nextSib = pWin->nextSib; Xfree(pWin); } } DestroySubwindows(pWin, client) WindowPtr pWin; ClientPtr client; { WindowPtr pChild, pSib; xEvent event; if (!(pChild = pWin->lastChild)) return; while (pChild) { event.u.u.type = DestroyNotify; event.u.destroyNotify.window = pChild->wid; DeliverEvents(pChild, &event, 1, NullWindow); pSib = pChild->prevSib; /* a little lazy evaluation, don't send exposes until all deleted */ if (pSib != (WindowPtr )NULL) { event.u.u.type = UnmapNotify; event.u.unmapNotify.window = pWin->wid; event.u.unmapNotify.fromConfigure = xFalse; DeliverEvents(pWin, &event, 1, NullWindow); } else { pChild->nextSib = (WindowPtr)NULL; UnmapWindow(pChild, HANDLE←EXPOSURES, SEND←NOTIFICATION, FALSE); } FreeResource(pChild->wid, RC←CORE); CrushTree(pChild->firstChild); FreeWindowResources(pChild); Xfree(pChild); pChild = pSib; } pWin->firstChild = (WindowPtr )NULL; } /***** * ChangeWindowAttributes * * The value-mask specifies which attributes are to be changed; the * value-list contains one value for each one bit in the mask, from least * to most significant bit in the mask. *****/ int ChangeWindowAttributes(pWin, vmask, vlist, client) WindowPtr pWin; unsigned long vmask; long *vlist; ClientPtr client; { long index; long *pVlist; PixmapPtr pPixmap; Pixmap pixID; CursorPtr pCursor; Cursor cursorID; int result; ScreenPtr pScreen; unsigned long vmaskCopy = 0; int error; if ((pWin->class == InputOnly) && (vmask & (~INPUTONLY←LEGAL←MASK))) return BadMatch; error = Success; pScreen = pWin->drawable.pScreen; pVlist = vlist; while (vmask) { index = ffs((long)vmask) - 1; vmask &= ~(index = (1 << index)); switch (index) { case CWBackPixmap: pixID = (Pixmap )*pVlist; pVlist++; if (pixID == None) { (* pScreen->DestroyPixmap)(pWin->backgroundTile); if (!pWin->parent) MakeRootTile(pWin); else pWin->backgroundTile = (PixmapPtr)NULL; } else if (pixID == ParentRelative) { (* pScreen->DestroyPixmap)(pWin->backgroundTile); if (!pWin->parent) MakeRootTile(pWin); else pWin->backgroundTile = (PixmapPtr)ParentRelative; /* Note that the parent's backgroundTile's refcnt is NOT * incremented. */ } else { pPixmap = (PixmapPtr)LookupID((long)pixID, RT←PIXMAP, RC←CORE); if (pPixmap) { if ((pPixmap->drawable.depth != pWin->drawable.depth) || (pPixmap->drawable.pScreen != pScreen)) { error = BadMatch; goto PatchUp; } (* pScreen->DestroyPixmap)(pWin->backgroundTile); pWin->backgroundTile = pPixmap; pPixmap->refcnt++; } else { error = BadPixmap; goto PatchUp; } } break; case CWBackPixel: pWin->backgroundPixel = (CARD32 ) *pVlist; (* pScreen->DestroyPixmap)(pWin->backgroundTile); pWin->backgroundTile = (PixmapPtr)USE←BACKGROUND←PIXEL; pVlist++; break; case CWBorderPixmap: pixID = (Pixmap ) *pVlist; pVlist++; if (pixID == CopyFromParent) { GCPtr pGC; PixmapPtr parentPixmap; if ((!pWin->parent) || (pWin->parent && (pWin->drawable.depth != pWin->parent->drawable.depth))) { error = BadMatch; goto PatchUp; } (* pScreen->DestroyPixmap)(pWin->borderTile); parentPixmap = pWin->parent->borderTile; if (parentPixmap == (PixmapPtr)USE←BORDER←PIXEL) { pWin->borderTile = (PixmapPtr)USE←BORDER←PIXEL; pWin->borderPixel = pWin->parent->borderPixel; } else { CARD32 attribute; pPixmap = (* pWin->drawable.pScreen->CreatePixmap) (pWin->drawable.pScreen, parentPixmap->width, parentPixmap->height, pWin->drawable.depth); pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); attribute = GXcopy; ChangeGC(pGC, GCFunction, &attribute); ValidateGC((DrawablePtr)pPixmap, pGC); (* pGC->CopyArea)(parentPixmap, pPixmap, pGC, 0, 0, parentPixmap->width, parentPixmap->height, pWin->drawable.depth, 0, 0); pWin->borderTile = pPixmap; FreeScratchGC(pGC); } } else { pPixmap = (PixmapPtr)LookupID((long)pixID, RT←PIXMAP, RC←CORE); if (pPixmap) { if ((pPixmap->drawable.depth != pWin->drawable.depth) || (pPixmap->drawable.pScreen != pScreen)) { error = BadMatch; goto PatchUp; } (* pScreen->DestroyPixmap)(pWin->borderTile); pWin->borderTile = pPixmap; pPixmap->refcnt++; } else { error = BadPixmap; goto PatchUp; } } break; case CWBorderPixel: pWin->borderPixel = (CARD32) *pVlist; (* pScreen->DestroyPixmap)(pWin->borderTile); pWin->borderTile = (PixmapPtr)USE←BORDER←PIXEL; pVlist++; break; case CWBitGravity: pWin->bitGravity = (CARD8 )*pVlist; pVlist++; break; case CWWinGravity: pWin->winGravity = (CARD8 )*pVlist; pVlist++; break; case CWBackingStore: pWin->backingStore = (CARD8 )*pVlist; pVlist++; break; case CWBackingPlanes: pWin->backingBitPlanes = (CARD32) *pVlist; pVlist++; break; case CWBackingPixel: pWin->backingPixel = (CARD32)*pVlist; pVlist++; break; case CWSaveUnder: pWin->saveUnder = (Bool) *pVlist; pVlist++; break; case CWEventMask: result = EventSelectForWindow(pWin, client, (Mask )*pVlist); if (result) { error = result; goto PatchUp; } pVlist++; break; case CWDontPropagate: result = EventSuppressForWindow(pWin, client, (Mask )*pVlist); if (result) { error = result; goto PatchUp; } pVlist++; break; case CWOverrideRedirect: pWin->overrideRedirect = (Bool ) *pVlist; pVlist++; break; case CWColormap: { Colormap cmap; ColormapPtr pCmap; xEvent xE; WindowPtr pWinT; cmap = (Colormap ) *pVlist; pWinT = pWin; while(cmap == CopyFromParent || cmap == CopyFromParent) { if(pWinT->parent) { if((pWinT->parent->colormap != CopyFromParent) && (pWinT->parent->colormap != CopyFromParent)) { cmap = pWinT->parent->colormap; if(((Colormap ) *pVlist) == CopyFromParent) *( Colormap*)pVlist = cmap; } else pWinT = pWinT->parent; } else { error = BadMatch; goto PatchUp; } } pCmap = (ColormapPtr)LookupID(cmap, RT←COLORMAP, RC←CORE); if (pCmap) { if (pCmap->pVisual->vid == pWin->visual) { pWin->colormap = (Colormap ) *pVlist; xE.u.u.type = ColormapNotify; xE.u.colormap.new = TRUE; xE.u.colormap.state = IsMapInstalled(cmap, pWin); TraverseTree(pWin, TellNewMap, (pointer)&xE); } else { error = BadMatch; goto PatchUp; } } else { error = BadColor; goto PatchUp; } pVlist++; break; } case CWCursor: cursorID = (Cursor ) *pVlist; pVlist++; /* * install the new */ if ( cursorID == None) { if ( pWin->cursor != None) FreeCursor( pWin->cursor, 0); if (pWin == &WindowTable[pWin->drawable.pScreen->myNum]) MakeRootCursor( pWin); else pWin->cursor = (CursorPtr)None; } else { pCursor = (CursorPtr)LookupID(cursorID, RT←CURSOR, RC←CORE); if (pCursor) { if ( pWin->cursor != None) FreeCursor( pWin->cursor, 0); pWin->cursor = pCursor; pWin->cursor->refcnt++; } else { error = BadCursor; goto PatchUp; } } WindowHasNewCursor( pWin); break; default: break; } vmaskCopy |= index; } PatchUp: (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); /* If the border pixel changed, redraw the border. Note that this has to be done AFTER pScreen->ChangeWindowAttributes for the tile to be rotated, and the correct function selected. */ if ((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) && pWin->viewable && pWin->borderWidth) { (* pScreen->Subtract)(pWin->borderExposed, pWin->borderClip, pWin->winSize); (*pWin->PaintWindowBorder)(pWin, pWin->borderExposed, PW←BORDER); (* pScreen->RegionEmpty)(pWin->borderExposed); } return error; } /***** * GetWindowAttributes * Notice that this is different than ChangeWindowAttributes *****/ GetWindowAttributes(pWin, client) WindowPtr pWin; ClientPtr client; { xGetWindowAttributesReply wa; wa.type = X←Reply; wa.bitGravity = pWin->bitGravity; wa.winGravity = pWin->winGravity; wa.backingStore = pWin->backingStore; wa.length = (sizeof(xGetWindowAttributesReply) - sizeof(xGenericReply)) >> 2; wa.sequenceNumber = client->sequence; wa.backingBitPlanes = pWin->backingBitPlanes; wa.backingPixel = pWin->backingPixel; wa.saveUnder = (BOOL)pWin->saveUnder; wa.mapInstalled = IsMapInstalled(pWin->colormap, pWin); wa.override = pWin->overrideRedirect; wa.mapState = pWin->mapped; wa.colormap = pWin->colormap; wa.yourEventMask = EventMaskForClient(pWin, client, &wa.allEventMasks); wa.doNotPropagateMask = pWin->dontPropagateMask ; wa.class = pWin->class; wa.visualID = pWin->visual; WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); } void fixChildrenWinSize(pWin) WindowPtr pWin; { WindowPtr pSib; RegionPtr parentReg; BoxRec box; register short x, y, cwsx, cwsy; ScreenPtr pScreen; parentReg = pWin->winSize; pSib = pWin->firstChild; x = pWin->absCorner.x; y = pWin->absCorner.y; pScreen = pWin->drawable.pScreen; while (pSib) { cwsx = pSib->clientWinSize.x; cwsy = pSib->clientWinSize.y; box.x1 = x + cwsx; box.y1 = y + cwsy; box.x2 = box.x1 + pSib->clientWinSize.width; box.y2 = box.y1 + pSib->clientWinSize.height; pSib->oldAbsCorner.x = pSib->absCorner.x; pSib->oldAbsCorner.y = pSib->absCorner.y; pSib->absCorner.x = x + cwsx; pSib->absCorner.y = y + cwsy; (* pScreen->RegionReset)(pSib->winSize, &box); (* pScreen->Intersect)(pSib->winSize, pSib->winSize, parentReg); if (pSib->borderWidth) { box.x1 -= pSib->borderWidth; box.y1 -= pSib->borderWidth; box.x2 += pSib->borderWidth; box.y2 += pSib->borderWidth; (* pScreen->RegionReset)(pSib->borderSize, &box); (* pScreen->Intersect)(pSib->borderSize, pSib->borderSize, parentReg); } else { (* pScreen->RegionCopy)(pSib->borderSize, pSib->winSize); } (*pSib->drawable.pScreen->PositionWindow)(pSib, pSib->absCorner.x, pSib->absCorner.y); pSib->marked = 1; if (pSib->firstChild) fixChildrenWinSize(pSib); pSib = pSib->nextSib; } } void MoveWindowInStack(pWin, pNextSib) WindowPtr pWin, pNextSib; { WindowPtr pParent = pWin->parent; if (pWin->nextSib != pNextSib) { if (!pNextSib) /* move to bottom */ { if (pParent->firstChild == pWin) pParent->firstChild = pWin->nextSib; if (pWin->nextSib) pWin->nextSib->prevSib = pWin->prevSib; if (pWin->prevSib) pWin->prevSib->nextSib = pWin->nextSib; pParent->lastChild->nextSib = pWin; pWin->prevSib = pParent->lastChild; pWin->nextSib = (WindowPtr )NULL; pParent->lastChild = pWin; } else if (pParent->firstChild == pNextSib) { if (pParent->lastChild == pWin) pParent->lastChild = pWin->prevSib; if (pWin->nextSib) pWin->nextSib->prevSib = pWin->prevSib; if (pWin->prevSib) pWin->prevSib->nextSib = pWin->nextSib; pWin->nextSib = pParent->firstChild; pWin->prevSib = (WindowPtr ) NULL; pNextSib->prevSib = pWin; pParent->firstChild = pWin; } else { if (pParent->firstChild == pWin) pParent->firstChild = pWin->nextSib; if (pParent->lastChild == pWin) pParent->lastChild = pWin->prevSib; if (pWin->nextSib) pWin->nextSib->prevSib = pWin->prevSib; if (pWin->prevSib) pWin->prevSib->nextSib = pWin->nextSib; pWin->nextSib = pNextSib; pWin->prevSib = pNextSib->prevSib; if (pNextSib->prevSib) pNextSib->prevSib->nextSib = pWin; pNextSib->prevSib = pWin; } } } void MoveWindow(pWin, x, y, pNextSib, above) /* for first pass, puts window on top of stack first */ WindowPtr pWin; short x,y; WindowPtr pNextSib; int above; { WindowPtr pParent; Bool WasMapped = (Bool)(pWin->realized); BoxRec box; short oldx, oldy, bw; RegionPtr oldRegion; DDXPointRec oldpt; Bool anyMarked; register ScreenPtr pScreen; BoxPtr pBox; WindowPtr windowToValidate = pWin; /* if this is a root window, can't be moved */ if (!(pParent = pWin->parent)) return ; pScreen = pWin->drawable.pScreen; bw = pWin->borderWidth; oldx = pWin->absCorner.x; oldy = pWin->absCorner.y; oldpt.x = oldx; oldpt.y = oldy; if (WasMapped) { oldRegion = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); (* pScreen->RegionCopy)(oldRegion, pWin->borderClip); pBox = (* pScreen->RegionExtents)(pWin->borderSize); anyMarked = MarkSiblingsBelowMe(pWin, pBox, TRUE); } pWin->clientWinSize.x = x + bw; pWin->clientWinSize.y = y + bw; pWin->oldAbsCorner.x = oldx; pWin->oldAbsCorner.y = oldy; pWin->absCorner.x = pParent->absCorner.x + x +bw; pWin->absCorner.y = pParent->absCorner.y + y + bw; box.x1 = pWin->absCorner.x; box.y1 = pWin->absCorner.y; box.x2 = box.x1 + pWin->clientWinSize.width; box.y2 = box.y1+ pWin->clientWinSize.height; (* pScreen->RegionReset)(pWin->winSize, &box); (* pScreen->Intersect)(pWin->winSize, pWin->winSize, pParent->winSize); if (bw) { box.x1 -= bw; box.y1 -= bw; box.x2 += bw; box.y2 += bw; (* pScreen->RegionReset)(pWin->borderSize, &box); (* pScreen->Intersect)(pWin->borderSize, pWin->borderSize, pParent->winSize); } else (* pScreen->RegionCopy)(pWin->borderSize, pWin->winSize); (* pScreen->PositionWindow)(pWin,pWin->absCorner.x, pWin->absCorner.y); if (!pNextSib || (above == Above)) MoveWindowInStack(pWin, pNextSib); else { MoveWindowInStack(pNextSib, pWin); windowToValidate = pNextSib; } fixChildrenWinSize(pWin); if (WasMapped) { short wid, hgt; Bool addborder = TRUE; BoxPtr parentBox; parentBox = (* pScreen->RegionExtents)(pParent->winSize); x = pWin->absCorner.x; y = pWin->absCorner.y; wid = pWin->clientWinSize.width; hgt = pWin->clientWinSize.height; if (oldx - bw < 0) addborder = FALSE; else if (oldy - bw < 0) addborder = FALSE; else if (oldx + wid + bw > parentBox->x2) addborder = FALSE; else if (oldy + hgt + bw > parentBox->y2) addborder = FALSE; if (!addborder) (* pScreen->RegionEmpty)(pWin->borderClip); /* force redraw of border */ anyMarked = MarkSiblingsBelowMe(windowToValidate, pBox, TRUE) || anyMarked; (* pScreen->ValidateTree)(pParent, (WindowPtr)NULL, TRUE, anyMarked); /* (anyMarked ? windowToValidate : (WindowPtr )NULL), TRUE, anyMarked); */ DoObscures(pParent); if (pWin->backgroundTile == (PixmapPtr)ParentRelative) (* pScreen->RegionCopy)(pWin->exposed, pWin->clipList); else { (* pWin->CopyWindow)(pWin, oldpt, oldRegion); (* pScreen->Subtract)(pParent->exposed, pParent->exposed, pWin->borderSize); } (* pScreen->RegionDestroy)(oldRegion); HandleExposures(pParent); } } void ResizeChildrenWinSize(pWin, XYSame, dw, dh) WindowPtr pWin; Bool XYSame; int dw, dh; { WindowPtr pSib; RegionPtr parentReg; BoxRec box; register short x, y, cwsx, cwsy; Bool unmap = FALSE; register ScreenPtr pScreen; pScreen = pWin->drawable.pScreen; parentReg = pWin->winSize; pSib = pWin->firstChild; x = pWin->absCorner.x; y = pWin->absCorner.y; while (pSib) { cwsx = pSib->clientWinSize.x; cwsy = pSib->clientWinSize.y; switch (pSib->winGravity) { case UnmapGravity: unmap = TRUE; case NorthWestGravity: break; case NorthGravity: cwsx += dw/2; break; case NorthEastGravity: cwsx += dw; break; case WestGravity: cwsy += dh/2; break; case CenterGravity: cwsx += dw/2; cwsy += dh/2; break; case EastGravity: cwsx += dw; cwsy += dh/2; break; case SouthWestGravity: cwsy += dh; break; case SouthGravity: cwsx += dw/2; cwsy += dh; break; case SouthEastGravity: cwsx += dw; cwsy += dh; break; case StaticGravity: /* XXX */ break; default: break; } box.x1 = x + cwsx; box.y1 = y + cwsy; box.x2 = box.x1 + pSib->clientWinSize.width; box.y2 = box.y1 + pSib->clientWinSize.height; pSib->oldAbsCorner.x = pSib->absCorner.x; pSib->oldAbsCorner.y = pSib->absCorner.y; pSib->absCorner.x = x + cwsx; pSib->absCorner.y = y + cwsy; (* pScreen->RegionReset)(pSib->winSize, &box); (* pScreen->Intersect)(pSib->winSize, pSib->winSize, parentReg); if (pSib->borderWidth) { box.x1 -= pSib->borderWidth; box.y1 -= pSib->borderWidth; box.x2 += pSib->borderWidth; box.y2 += pSib->borderWidth; (* pScreen->RegionReset)(pSib->borderSize, &box); (* pScreen->Intersect)(pSib->borderSize, pSib->borderSize, parentReg); } else (* pScreen->RegionCopy)(pSib->borderSize, pSib->winSize); (* pScreen->PositionWindow)(pSib, pSib->absCorner.x, pSib->absCorner.y); pSib->marked = 1; if (pSib->firstChild) ResizeChildrenWinSize(pSib, XYSame, dw, dh); if (unmap) { UnmapWindow(pSib, DONT←HANDLE←EXPOSURES, SEND←NOTIFICATION, TRUE); unmap = FALSE; } pSib = pSib->nextSib; } } int ExposeAll(pWin, pScreen) WindowPtr pWin; ScreenPtr pScreen; { if (!pWin) return(WT←NOMATCH); if (pWin->mapped) { (* pScreen->RegionCopy)(pWin->exposed, pWin->clipList); return (WT←WALKCHILDREN); } else return(WT←NOMATCH); }