/*********************************************************** 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, * ******/ extern long _back[16]; extern void ResizeChildrenWinSize(); extern void MoveWindowInStack(); extern void DoObscures(); extern void fixChildrenWinSize(); extern void DoObscures(); extern void HandleExposures(); 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; extern int screenIsSaved ; extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; extern WindowRec WindowTable[]; extern int (* ReplySwapVector[256]) (); extern void MoveWindow(); extern int ExposeAll(); #define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ CWDontPropagate | CWCursor ) static void SlideAndSizeWindow(pWin, x, y, w, h, pSib, above) WindowPtr pWin; short x,y; unsigned short w, h; WindowPtr pSib; int above; { WindowPtr pParent; Bool WasMapped = (Bool)(pWin->realized); BoxRec box; unsigned short width = pWin->clientWinSize.width, height = pWin->clientWinSize.height; short oldx = pWin->absCorner.x, oldy = pWin->absCorner.y, bw = pWin->borderWidth; short dw, dh; Bool XYSame = FALSE; DDXPointRec oldpt; RegionPtr oldRegion; Bool anyMarked; register ScreenPtr pScreen; BoxPtr pBox; /* if this is a root window, can't be resized */ if (!(pParent = pWin->parent)) return ; pScreen = pWin->drawable.pScreen; if (WasMapped) { if ((pWin->bitGravity != ForgetGravity) || (pWin->backgroundTile == (PixmapPtr)ParentRelative)) oldRegion = NotClippedByChildren(pWin); pBox = (* pScreen->RegionExtents)(pWin->borderSize); anyMarked = MarkSiblingsBelowMe(pWin, pBox, TRUE); } pWin->clientWinSize.x = x + bw; pWin->clientWinSize.y = y + bw; pWin->clientWinSize.height = h; pWin->clientWinSize.width = w; XYSame = ((pParent->absCorner.x + x == pWin->absCorner.x) && (pParent->absCorner.y + y == pWin->absCorner.y)); pWin->oldAbsCorner.x = oldx; pWin->oldAbsCorner.y = oldy; oldpt.x = oldx; oldpt.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 = pWin->absCorner.x + w; box.y2 = pWin->absCorner.y + h; (* pScreen->RegionReset)(pWin->winSize, &box); (* pScreen->Intersect)(pWin->winSize, pWin->winSize, pParent->winSize); if (pWin->borderWidth) { 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); dw = w - width; dh = h - height; ResizeChildrenWinSize(pWin, XYSame, dw, dh); /* let the hardware adjust background and border pixmaps, if any */ (* pScreen->PositionWindow)(pWin, pWin->absCorner.x, pWin->absCorner.y); if (!pSib || (above == Above)) MoveWindowInStack(pWin, pSib); else MoveWindowInStack(pSib, pWin); if (WasMapped) { RegionPtr pRegion; if (!pSib || (above == Above)) anyMarked = MarkSiblingsBelowMe(pWin, pBox, TRUE) || anyMarked; else anyMarked = MarkSiblingsBelowMe(pSib, pBox, TRUE) || anyMarked; if ((pWin->bitGravity == ForgetGravity) || (pWin->backgroundTile == (PixmapPtr)ParentRelative)) { (* pScreen->ValidateTree)(pParent, (WindowPtr )NULL, TRUE, anyMarked); TraverseTree(pWin, ExposeAll, (pointer)pScreen); DoObscures(pParent); HandleExposures(pParent); } else { pRegion = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); (* pScreen->RegionCopy)(pRegion, pWin->clipList); x = pWin->absCorner.x; y = pWin->absCorner.y; switch (pWin->bitGravity) { case UnmapGravity: case NorthWestGravity: break; case NorthGravity: x += dw/2; break; case NorthEastGravity: x += dw; break; case WestGravity: y += dh/2; break; case CenterGravity: x += dw/2; y += dh/2; break; case EastGravity: x += dw; y += dh/2; break; case SouthWestGravity: y += dh; break; case SouthGravity: x += dw/2; y += dh; break; case SouthEastGravity: x += dw; y += dh; break; case StaticGravity: x = oldx; y = oldy; break; default: break; } if (dw < 0) { width = w; if (x < pWin->absCorner.x) x = pWin->absCorner.x; } if (dh < 0) { height = h; if (y < pWin->absCorner.y) y = pWin->absCorner.y; } if (pWin->bitGravity == UnmapGravity) { UnmapWindow(pSib, DONT_HANDLE_EXPOSURES, SEND_NOTIFICATION, TRUE); (* pScreen->RegionDestroy)(pRegion); (* pScreen->RegionDestroy)(oldRegion); return ; } (* pScreen->ValidateTree)(pParent, (anyMarked ? pWin : (WindowPtr )NULL), TRUE, anyMarked); DoObscures(pParent); if (pWin->backStorage && (pWin->backingStore != NotUseful)) { ErrorF("Going to translate backing store %d %d\n", oldx - x, oldy - y); (* pWin->backStorage->TranslateBackingStore) (pWin, oldx - x, oldy - y); } oldpt.x = oldx - x + pWin->absCorner.x; oldpt.y = oldy - y + pWin->absCorner.y; (* pWin->CopyWindow)(pWin, oldpt, oldRegion); /* Note that oldRegion is *translated* by CopyWindow */ (* pScreen->Subtract)(pWin->exposed, pWin->clipList, oldRegion); (* pScreen->Subtract)(pParent->exposed, pParent->exposed, pWin->borderSize); (* pScreen->RegionDestroy)(pRegion); if (!XYSame && (IS_VALID_PIXMAP(pWin->backgroundTile ))) /* tile was "rotated" so redraw entire thing */ (* pScreen->Subtract)(pWin->borderExposed, pWin->borderClip, pWin->winSize); HandleExposures(pParent); (* pScreen->RegionDestroy)(oldRegion); } } } static void ChangeBorderWidth(pWin, width) WindowPtr pWin; int width; { WindowPtr pParent; BoxRec box; BoxPtr pBox; int oldwidth; Bool anyMarked; register ScreenPtr pScreen; RegionPtr oldRegion; DDXPointRec oldpt; Bool WasMapped = (Bool)(pWin->realized); oldwidth = pWin->borderWidth; if (oldwidth == width) return ; pScreen = pWin->drawable.pScreen; pParent = pWin->parent; pWin->borderWidth = width; oldpt.x = pWin->absCorner.x; oldpt.y = pWin->absCorner.y; pWin->oldAbsCorner.x = oldpt.x; pWin->oldAbsCorner.y = oldpt.y; pWin->clientWinSize.x += width - oldwidth; pWin->clientWinSize.y += width - oldwidth; pWin->absCorner.x += width - oldwidth; pWin->absCorner.y += width - oldwidth; if (WasMapped) { oldRegion = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); (* pScreen->RegionCopy)(oldRegion, pWin->borderClip); } 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 (width) { box.x1 -= width; box.y1 -= width; box.x2 += width; box.y2 += width; (* pScreen->RegionReset)(pWin->borderSize, &box); (* pScreen->Intersect)(pWin->borderSize, pWin->borderSize, pParent->winSize); } else (* pScreen->RegionCopy)(pWin->borderSize, pWin->winSize); if (WasMapped) { if (width < oldwidth) pBox = (* pScreen->RegionExtents)(oldRegion); else pBox = (* pScreen->RegionExtents)(pWin->borderSize); anyMarked = MarkSiblingsBelowMe(pWin, pBox, TRUE); (* pScreen->ValidateTree)(pParent,(anyMarked ? pWin : (WindowPtr)NULL), TRUE, anyMarked ); (* pWin->CopyWindow)(pWin, oldpt, oldRegion); if (width > oldwidth) { DoObscures(pParent); (* pScreen->Subtract)(pWin->borderExposed, pWin->borderClip, pWin->winSize); (* pWin->PaintWindowBorder)(pWin, pWin->borderExposed, PW_BORDER); (* pScreen->RegionEmpty)(pWin->borderExposed); } else if (oldwidth > width) HandleExposures(pParent); (* pScreen->RegionDestroy)(oldRegion); } } /***** * ConfigureWindow *****/ #define GET_INT16(m, f) \ if (m & mask) \ { \ f = (short) *pVlist;\ pVlist++; \ } #define GET_CARD16(m, f) \ if (m & mask) \ { \ f = (CARD16) *pVlist;\ pVlist++;\ } #define GET_CARD8(m, f) \ if (m & mask) \ { \ f = (CARD8) *pVlist;\ pVlist++;\ } #define ChangeMask (CWX | CWY | CWWidth | CWHeight) #define IllegalInputOnlyConfigureMask (CWBorderWidth) /* returns Above if pSib above pMe in stack or Below otherwise */ static Bool WhereIsSiblingWithRespectToMe(pMe, pSib, above) WindowPtr pMe, pSib; int *above; { WindowPtr pWin; *above = Above; pWin = pMe->parent->firstChild; while (pWin) { if (pWin == pSib) return(TRUE); if (pWin == pMe) *above = Below; pWin = pWin->nextSib; } return(FALSE); } static Bool AnyWindowOverlapsMe(pWin, box) WindowPtr pWin; BoxPtr box; { WindowPtr pSib; register ScreenPtr pScreen; pSib = pWin->parent->firstChild; pScreen = pWin->drawable.pScreen; while (pSib) { if (pSib == pWin) return(FALSE); else if ((pSib->mapped) && ((* pScreen->RectIn)(pSib->borderSize, box) != rgnOUT)) return(TRUE); pSib = pSib->nextSib; } return(FALSE); } static WindowPtr IOverlapAnyWindow(pWin, box) WindowPtr pWin; BoxPtr box; { WindowPtr pSib; register ScreenPtr pScreen; pScreen = pWin->drawable.pScreen; pSib = pWin->nextSib; while (pSib) { if ((pSib->mapped) && ((* pScreen->RectIn)(pSib->borderSize, box) != rgnOUT)) return(pSib); pSib = pSib->nextSib; } return((WindowPtr )NULL); } static WindowPtr WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode, above) WindowPtr pWin, pSib; short x, y, w, h; int smode; int *above; /* return value: if Above, put pWin before pSib, if Below, put pSib before pWin */ { BoxRec box; register ScreenPtr pScreen; *above = smode; if ((pWin == pWin->parent->firstChild) && (pWin == pWin->parent->lastChild)) return((WindowPtr ) NULL); pScreen = pWin->drawable.pScreen; box.x1 = x; box.y1 = y; box.x2= x + w; box.y2 = y + h; switch (smode) { case Above: if (pSib) return(pSib); else if (pWin == pWin->parent->firstChild) return(pWin->nextSib); else return(pWin->parent->firstChild); break; case Below: if (pSib) return(pSib); else return((WindowPtr )NULL); break; case TopIf: case Opposite: if (pSib) { WhereIsSiblingWithRespectToMe(pWin, pSib, above); if ((*above == Above) && ((* pScreen->RectIn)(pSib->borderSize, &box) != rgnOUT)) return(pSib); else if ((smode == Opposite) && ((*above == Below)&& ((* pScreen->RectIn)(pSib->borderSize, &box) != rgnOUT))) return(pSib); else { *above = Above; return(pSib->nextSib); } } else if (AnyWindowOverlapsMe(pWin, &box)) { *above = Above; return(pWin->parent->firstChild); } else if (smode == TopIf) { *above = Above; return(pWin->nextSib); } case BottomIf: if (pSib) { WhereIsSiblingWithRespectToMe(pWin, pSib, above); if ((*above == Below) && ((* pScreen->RectIn)(pSib->borderSize, &box) != rgnOUT)) return(pSib); else return(pWin->nextSib); } else if (IOverlapAnyWindow(pWin, &box)) { *above = Above; return((WindowPtr )NULL); } else { *above = Below; return(pWin->nextSib); } break; } return((WindowPtr)NULL); } static void ReflectStackChange(pWin, pSib, above) WindowPtr pWin, pSib; int above; { /* Note that pSib might be NULL */ Bool doValidation = (Bool)pWin->realized; WindowPtr pParent; int anyMarked; BoxPtr box; /* if this is a root window, can't be restacked */ if (!(pParent = pWin->parent)) return ; if (doValidation) { box = (* pWin->drawable.pScreen->RegionExtents)(pWin->borderSize); anyMarked = MarkChildren(pParent, box, FALSE); } if (!pSib || (above == Above)) MoveWindowInStack(pWin, pSib); else MoveWindowInStack(pSib, pWin); if (doValidation) { (* pWin->drawable.pScreen->ValidateTree)(pParent, (anyMarked ? (WindowPtr)NULL : pWin), TRUE, anyMarked); DoObscures(pParent); HandleExposures(pParent); } } int ConfigureWindow(pWin, mask, vlist, client) WindowPtr pWin; unsigned long mask; long *vlist; ClientPtr client; { WindowPtr pSib = (WindowPtr )NULL; Window sibwid; long index, tmask; long *pVlist; short x, y; unsigned short w = pWin->clientWinSize.width, h = pWin->clientWinSize.height, bw = pWin->borderWidth; int action, above, smode = Above; xEvent event; if ((pWin->class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) return(BadMatch); if ((mask & CWSibling) && !(mask & CWStackMode)) return(BadWindow); pVlist = vlist; if (pWin->parent) { x = pWin->absCorner.x - pWin->parent->absCorner.x - bw; y = pWin->absCorner.y - pWin->parent->absCorner.y - bw; } else { x = pWin->absCorner.x; y = pWin->absCorner.y; } action = 0; if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) { GET_INT16(CWX, x); GET_INT16(CWY, y); action = 1; } /* or should be resized */ else if (mask & (CWX | CWY | CWWidth | CWHeight)) { GET_INT16(CWX, x); GET_INT16(CWY, y); GET_CARD16(CWWidth, w); GET_CARD16 (CWHeight, h); if (!w || !h) return BadValue; action = 2; } tmask = mask & ~ChangeMask; while (tmask) { index = ffs(tmask) - 1; tmask &= ~(index = (1 << index)); switch (index) { case CWBorderWidth: GET_CARD16(CWBorderWidth, bw); break; case CWSibling: sibwid = (Window ) *pVlist; pVlist++; pSib = (WindowPtr )LookupID(sibwid, RT_WINDOW, RC_CORE); if (!pSib) return(BadWindow); if (pSib->parent != pWin->parent) return(BadMatch); break; case CWStackMode: GET_CARD8(CWStackMode, smode); if ((smode != TopIf) && (smode != BottomIf) && (smode != Opposite) && (smode != Above) && (smode != Below)) return(BadMatch); break; default: return(BadMatch); } } /* then figure out if the window should be moved. Doesnt make the changes to the window if event sent */ if (mask & CWStackMode) pSib = WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode, &above); else { above = Above; pSib = pWin->nextSib; } if ((!pWin->overrideRedirect) && (pWin->parent->allEventMasks & SubstructureRedirectMask)) { event.u.u.type = ConfigureRequest; event.u.configureRequest.window = pWin->wid; event.u.configureRequest.parent = pWin->parent->wid; if (pSib) event.u.configureRequest.aboveSibling = pSib->wid; else event.u.configureRequest.aboveSibling = None; event.u.configureRequest.x = x; event.u.configureRequest.y = y; event.u.configureRequest.width = w; event.u.configureRequest.height = h; event.u.configureRequest.borderWidth = bw; if (MaybeDeliverEventsToClient(pWin->parent, &event, 1, SubstructureRedirectMask, client) == 1) return(Success); } if ((action == 2) && (pWin->allEventMasks & ResizeRedirectMask)) { xEvent event; event.u.u.type = ResizeRequest; event.u.resizeRequest.window = pWin->wid; event.u.resizeRequest.width = w; event.u.resizeRequest.height = h; if (MaybeDeliverEventsToClient(pWin, &event, 1, ResizeRedirectMask, client) == 1) { w = pWin->clientWinSize.width; h = pWin->clientWinSize.height; if (mask & (CWX | CWY)) action = 1; else action = 0; } } event.u.u.type = ConfigureNotify; event.u.configureNotify.window = pWin->wid; if (pSib) event.u.configureNotify.aboveSibling = pSib->wid; else event.u.configureNotify.aboveSibling = None; event.u.configureNotify.x = x; event.u.configureNotify.y = y; event.u.configureNotify.width = w; event.u.configureNotify.height = h; event.u.configureNotify.borderWidth = bw; event.u.configureNotify.override = pWin->overrideRedirect; DeliverEvents(pWin, &event, 1, NullWindow); if (mask & CWBorderWidth) { if (action == 0) ChangeBorderWidth(pWin, (int)bw); else pWin->borderWidth = bw; } if (action == 1) MoveWindow(pWin, x, y, pSib, above); else if (action == 2) SlideAndSizeWindow(pWin, x, y, w, h, pSib, above); else if (mask & CWStackMode) ReflectStackChange(pWin, pSib, above); return(Success); } /****** * * CirculateWindow * For RaiseLowest, raises the lowest mapped child (if any) that is * obscured by another child to the top of the stack. For LowerHighest, * lowers the highest mapped child (if any) that is obscuring another * child to the bottom of the stack. Exposure processing is performed * ******/ /* XXX shouldn't this be a case for the stack mode stuff?? */ int CirculateWindow(pParent, direction, client) WindowPtr pParent; int direction; ClientPtr client; { WindowPtr pChild, pSib; xEvent event; register ScreenPtr pScreen; if (pParent->firstChild == pParent->lastChild) return(Success) ; pScreen = pParent->drawable.pScreen; if (direction == RaiseLowest) { pChild = pParent->lastChild; while (pChild) { if (pChild->mapped && (pChild->visibility != VisibilityUnobscured)) { if (pParent->firstChild != pChild) { if (pParent->lastChild == pChild) pParent->lastChild = pChild->prevSib; if (pChild->nextSib) pChild->nextSib->prevSib = pChild->prevSib; if (pChild->prevSib) pChild->prevSib->nextSib = pChild->nextSib; pChild->nextSib = pParent->firstChild; pChild->prevSib = (WindowPtr ) NULL; pParent->firstChild->prevSib = pChild; pParent->firstChild = pChild; pChild->mapped = 0; /* to fool MapWindow */ pSib = pChild; break; } return Success; } pChild = pChild->prevSib; } } else if (direction == LowerHighest) { BoxPtr pBox; pChild = pParent->firstChild; while (pChild) { if (pChild->mapped && (pChild->visibility == VisibilityUnobscured)) { int result; /* HACK -- this search is n squared */ pSib = pChild->nextSib; /* find a sibling that pChild overlaps */ pBox = (* pScreen->RegionExtents)(pChild->borderSize); while (pSib) { if (pSib->realized && (pSib->visibility != VisibilityUnobscured)) { result = (* pScreen->RectIn)(pSib->borderSize, &pBox); if (result != rgnOUT) break; } pSib = pSib->nextSib; } if (pSib) { WindowPtr pNext; pNext = pChild->nextSib; if (pParent->firstChild == pChild) pParent->firstChild = pNext; pNext->prevSib = pChild->prevSib; if (pChild->prevSib) pChild->prevSib->nextSib = pNext; pChild->nextSib = (WindowPtr ) NULL; pChild->prevSib = pParent->lastChild; pParent->lastChild->nextSib = pChild; pParent->lastChild = pChild; pSib->mapped = 0; /* to fool mapWindow */ break; } } pChild = pChild->nextSib; } } if (!pChild) return(Success) ; event.u.circulate.window = pChild->wid; event.u.circulate.parent = pParent->wid; event.u.circulate.event = pParent->wid; if (direction == RaiseLowest) event.u.circulate.place = PlaceOnTop; else event.u.circulate.place = PlaceOnBottom; if ((!pParent->overrideRedirect) && (pParent->allEventMasks & SubstructureRedirectMask)) { event.u.u.type = CirculateRequest; if (MaybeDeliverEventsToClient(pParent, &event, 1, SubstructureRedirectMask, client) == 1) return(Success); } if (pParent->realized) MapWindow(pSib, HANDLE_EXPOSURES, BITS_DISCARDED, DONT_SEND_NOTIFICATION, client); event.u.u.type = CirculateNotify; DeliverEvents(pParent, &event, 1, NullWindow); return(Success); } /***** * ReparentWindow *****/ static int CompareWIDs(pWin, wid) WindowPtr pWin; int *wid; { if (pWin->wid == *wid) return(WT_STOPWALKING); else return(WT_WALKCHILDREN); } int ReparentWindow(pWin, pParent, x, y, client) WindowPtr pWin, pParent; short x,y; ClientPtr client; { WindowPtr pPrev; Bool WasMapped = (Bool)(pWin->realized); BoxRec box; xEvent event; short oldx, oldy; int bw; register ScreenPtr pScreen; if (pWin == pParent) return(BadWindow); if (TraverseTree(pWin, CompareWIDs, &pParent->wid) == WT_STOPWALKING) return(BadWindow); pScreen = pWin->drawable.pScreen; event.u.u.type = ReparentNotify; event.u.reparent.window = pWin->wid; event.u.reparent.parent = pParent->wid; event.u.reparent.x = x; event.u.reparent.y = y; event.u.reparent.override = pWin->overrideRedirect; DeliverEvents(pWin, &event, 1, pParent); oldx = pWin->absCorner.x; oldy = pWin->absCorner.y; if (WasMapped) UnmapWindow(pWin, HANDLE_EXPOSURES, SEND_NOTIFICATION, FALSE); /* take out of sibling chain */ pPrev = pWin->parent; if (pPrev->firstChild == pWin) pPrev->firstChild = pWin->nextSib; if (pPrev->lastChild == pWin) pPrev->lastChild = pWin->prevSib; if (pWin->nextSib) pWin->nextSib->prevSib = pWin->prevSib; if (pWin->prevSib) pWin->prevSib->nextSib = pWin->nextSib; /* insert at begining of pParent */ pWin->parent = pParent; pWin->nextSib = pParent->firstChild; pWin->prevSib = (WindowPtr )NULL; if (pParent->firstChild) pParent->firstChild->prevSib = pWin; else pParent->lastChild = pWin; pParent->firstChild = pWin; /* clip to parent */ box.x1 = x + pParent->absCorner.x; box.y1 = y + pParent->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); pWin->clientWinSize.x = x; pWin->clientWinSize.y = y; pWin->oldAbsCorner.x = oldx; pWin->oldAbsCorner.y = oldy; pWin->absCorner.x = box.x1; pWin->absCorner.y = box.y1; if (bw = pWin->borderWidth) { 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); fixChildrenWinSize(pWin); if (WasMapped) { (*pScreen->Union)(pParent->clipList, pWin->borderSize, pParent->clipList); (*pScreen->Union)(pPrev->clipList, pWin->borderSize, pPrev->clipList); (* pScreen->RegionCopy)(pPrev->exposed, pWin->borderSize); MapWindow(pWin, HANDLE_EXPOSURES, BITS_DISCARDED, SEND_NOTIFICATION, client); } RecalculateDeliverableEvents(pParent); return(Success); } static int MarkChildren(pWin, box, unionParent) WindowPtr pWin; BoxPtr box; Bool unionParent; { WindowPtr pChild; int anyMarked=0; register ScreenPtr pScreen; pScreen = pWin->drawable.pScreen; pChild = pWin->firstChild; while (pChild) { if (pChild->mapped && ((* pScreen->RectIn)(pChild->borderSize, box))) { if (!pChild->marked) { (*pScreen->Union)(pWin->clipList, pChild->borderClip, pWin->clipList); if (unionParent) (*pScreen->Union)(pWin->exposed, pWin->exposed, pChild->borderClip); } anyMarked++; pChild->marked = 1; anyMarked += MarkChildren(pChild, box, unionParent); } pChild = pChild->nextSib; } return(anyMarked); } int MarkSiblingsBelowMe(pWin, box, unionParent) WindowPtr pWin; BoxPtr box; Bool unionParent; { WindowPtr pSib, pParent; int anyMarked = 0; register ScreenPtr pScreen; pScreen = pWin->drawable.pScreen; pParent = pWin->parent; pSib = pWin; while (pSib) { if (pSib->mapped && ((* pScreen->RectIn)(pSib->borderSize, box))) { if (pParent && (!pSib->marked)) { (*pScreen->Union)(pParent->clipList, pSib->borderClip, pParent->clipList); if (unionParent) (* pScreen->Union)(pParent->exposed, pParent->exposed, pSib->borderClip); } pSib->marked = 1; anyMarked++; if (pSib->firstChild) anyMarked += MarkChildren(pSib, box, unionParent); } pSib = pSib->nextSib; } return(anyMarked); } /***** * MapWindow * If some other client has selected SubStructureReDirect on the parent * and override-redirect is xFalse, then a MapRequest event is generated, * but the window remains unmapped. Otherwise, the window is mapped and a * MapNotify event is generated. *****/ static void RealizeChildren(pWin, client) WindowPtr pWin; ClientPtr client; { WindowPtr pSib; Bool (* Realize)(); pSib = pWin; if (pWin) Realize = pSib->drawable.pScreen->RealizeWindow; while (pSib) { if (pSib->mapped) { pSib->realized = TRUE; pSib->viewable = pSib->class == InputOutput; (* Realize)(pSib); FlushClientCaches(pSib->wid); if (pSib->firstChild) RealizeChildren(pSib->firstChild, client); } pSib = pSib->nextSib; } } int MapWindow(pWin, SendExposures, BitsAvailable, SendNotification, client) WindowPtr pWin; Bool SendExposures; Bool BitsAvailable; ClientPtr client; { register ScreenPtr pScreen; WindowPtr pParent; Bool anyMarked; if (pWin->mapped) return(Success); pScreen = pWin->drawable.pScreen; if (pParent = pWin->parent) { xEvent event; BoxPtr box; if (SendNotification && (!pWin->overrideRedirect) && (pParent->allEventMasks & SubstructureRedirectMask)) { event.u.u.type = MapRequest; event.u.mapRequest.window = pWin->wid; event.u.mapRequest.parent = pParent->wid; if (MaybeDeliverEventsToClient(pParent, &event, 1, SubstructureRedirectMask, client) == 1) return(Success); } pWin->mapped = 1; if (SendNotification) { event.u.u.type = MapNotify; event.u.mapNotify.window = pWin->wid; event.u.mapNotify.override = pWin->overrideRedirect; DeliverEvents(pWin, &event, 1, NullWindow); } pWin->marked = 0; /* so siblings get mapped correctly */ if (!pParent->realized) return(Success); pWin->realized = TRUE; pWin->viewable = pWin->class == InputOutput; (* pScreen->RealizeWindow)(pWin); if (pWin->firstChild) RealizeChildren(pWin->firstChild, client); box = (* pScreen->RegionExtents)(pWin->borderSize); anyMarked = MarkSiblingsBelowMe(pWin, box, FALSE); (* pScreen->ValidateTree)(pParent, pWin, TRUE, anyMarked); if (SendExposures) { if (!BitsAvailable) { (* pScreen->RegionCopy)(pWin->exposed, pWin->clipList); DoObscures(pParent); HandleExposures(pWin); } else { (* pScreen->Subtract)(pParent->exposed, pParent->exposed, pWin->borderSize); (* pScreen->RegionEmpty)(pWin->exposed); DoObscures(pParent); HandleExposures(pWin); } } } else { pWin->mapped = 1; pWin->realized = TRUE; /* for roots */ pWin->viewable = pWin->class == InputOutput; (* pScreen->RealizeWindow)(pWin); } return(Success); } /***** * MapSubwindows * Performs a MapWindow all unmapped children of the window, in top * to bottom stacking order. *****/ MapSubwindows(pWin, SendExposures, client) WindowPtr pWin; Bool SendExposures; ClientPtr client; { WindowPtr pChild; pChild = pWin->firstChild; while (pChild) { if (!pChild->mapped) MapWindow(pChild, SendExposures, BITS_DISCARDED, SEND_NOTIFICATION, client); pChild = pChild->nextSib; } } /***** * UnmapWindow * If the window is already unmapped, this request has no effect. * Otherwise, the window is unmapped and an UnMapNotify event is * generated. Cannot unmap a root window. *****/ static void UnrealizeChildren(pWin) WindowPtr pWin; { WindowPtr pSib; void (*RegionEmpty)(); Bool (*Unrealize)(); pSib = pWin; if (pWin) { RegionEmpty = pWin->drawable.pScreen->RegionEmpty; Unrealize = pWin->drawable.pScreen->UnrealizeWindow; } while (pSib) { pSib->realized = pSib->viewable = FALSE; (* Unrealize)(pSib); /* to force exposures later */ (* RegionEmpty)(pSib->clipList); (* RegionEmpty)(pSib->borderClip); (* RegionEmpty)(pSib->exposed); pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; DeleteWindowFromAnyEvents(pSib, FALSE); if (pSib->firstChild) UnrealizeChildren(pSib->firstChild); pSib = pSib->nextSib; } } UnmapWindow(pWin, SendExposures, SendNotification, fromConfigure) WindowPtr pWin; Bool SendExposures, fromConfigure; { WindowPtr pParent; xEvent event; Bool anyMarked; Bool wasMapped = (Bool)pWin->realized; BoxPtr box; if ((!pWin->mapped) || (!(pParent = pWin->parent))) return(Success); if (SendNotification) { event.u.u.type = UnmapNotify; event.u.unmapNotify.window = pWin->wid; event.u.unmapNotify.fromConfigure = fromConfigure; DeliverEvents(pWin, &event, 1, NullWindow); } if (wasMapped) { box = (* pWin->drawable.pScreen->RegionExtents)(pWin->borderSize); anyMarked = MarkSiblingsBelowMe(pWin, box, TRUE); } pWin->mapped = 0; pWin->realized = pWin->viewable = FALSE; if (wasMapped) { (* pWin->drawable.pScreen->UnrealizeWindow)(pWin); DeleteWindowFromAnyEvents(pWin, FALSE); if (pWin->firstChild) UnrealizeChildren(pWin->firstChild); (* pWin->drawable.pScreen->ValidateTree)(pParent, pWin, TRUE, anyMarked); if (SendExposures) { void (* RegionEmpty)(); RegionEmpty = pWin->drawable.pScreen->RegionEmpty; (* RegionEmpty)(pWin->clipList); /* to force expsoures later */ (* RegionEmpty)(pWin->borderClip); (* RegionEmpty)(pWin->borderExposed); (* RegionEmpty)(pWin->exposed); pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; HandleExposures(pParent); } } return(Success); } /***** * UnmapSubwindows * Performs an UnMapWindow request with the specified mode on all mapped * children of the window, in bottom to top stacking order. *****/ UnmapSubwindows(pWin, sendExposures) WindowPtr pWin; Bool sendExposures; { WindowPtr pChild; xEvent event; Bool anyMarked = TRUE; void (*RegionEmpty)(); Bool (*UnrealizeWindow)(); Bool wasMapped = (Bool)pWin->realized; pChild = pWin->lastChild; event.u.u.type = UnmapNotify; event.u.unmapNotify.fromConfigure = xFalse; RegionEmpty = pWin->drawable.pScreen->RegionEmpty; UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; while (pChild) { if (pChild->mapped) { event.u.unmapNotify.window = pChild->wid; event.u.unmapNotify.fromConfigure = xFalse; DeliverEvents(pWin, &event, 1, NullWindow); pChild->mapped = 0; if (wasMapped) { pChild->realized = pChild->viewable = FALSE; (* UnrealizeWindow)(pChild); if (pChild->firstChild) UnrealizeChildren(pChild->firstChild); DeleteWindowFromAnyEvents(pChild, FALSE); (* RegionEmpty)(pChild->clipList);/* to force expsoures later*/ (* RegionEmpty)(pChild->borderClip); (* RegionEmpty)(pChild->borderExposed); (* RegionEmpty)(pChild->exposed); pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; } } pChild = pChild->prevSib; } if ((pWin->lastChild) && wasMapped) { /* (* pWin->drawable.pScreen->ValidateTree)(pWin, NULL, TRUE, anyMarked); */ (* pWin->drawable.pScreen->Intersect)(pWin->clipList, pWin->winSize, pWin->borderClip); (* pWin->drawable.pScreen->RegionCopy)(pWin->exposed, pWin->clipList); HandleExposures(pWin); } } void HandleSaveSet(client) ClientPtr client; { WindowPtr pParent, pWin; int j; for (j=0; jnumSaved; j++) { pWin = (WindowPtr)client->saveSet[j]; pParent = pWin->parent; while (pParent && (pParent->client == client)) pParent = pParent->parent; if (pParent) { ReparentWindow(pWin, pParent, pWin->absCorner.x, pWin->absCorner.y, client); if(!pWin->realized && pWin->mapped) pWin->mapped = FALSE; MapWindow(pWin, HANDLE_EXPOSURES, BITS_DISCARDED, SEND_NOTIFICATION, client); } } } Bool VisibleBoundingBoxFromPoint(pWin, x, y, box) WindowPtr pWin; int x, y; /* in root */ BoxPtr box; /* "return" value */ { if (!pWin->realized) return (FALSE); if ((* pWin->drawable.pScreen->PointInRegion)(pWin->clipList, x, y, box)) return(TRUE); return(FALSE); } Bool PointInWindowIsVisible(pWin, x, y) WindowPtr pWin; int x, y; /* in root */ { BoxRec box; if (!pWin->realized) return (FALSE); if ((* pWin->drawable.pScreen->PointInRegion)(pWin->clipList, x, y, &box)) return(TRUE); return(FALSE); } RegionPtr NotClippedByChildren(pWin) WindowPtr pWin; { register ScreenPtr pScreen; RegionPtr pReg; pScreen = pWin->drawable.pScreen; pReg = (* pScreen->RegionCreate)((BoxPtr)NULL, 1); if (pWin->firstChild) (* pScreen->Intersect)(pReg, pWin->winSize, pWin->borderClip); else (* pScreen->RegionCopy)(pReg, pWin->clipList); return(pReg); } void SendVisibilityNotify(pWin) WindowPtr pWin; { xEvent event; event.u.u.type = VisibilityNotify; event.u.visibility.window = pWin->wid; event.u.visibility.state = pWin->visibility; DeliverEvents(pWin, &event, 1, NullWindow); } #define RANDOM_WIDTH 32 void SaveScreens(on, mode) int on; int mode; { int i, j; int what; unsigned char *srcbits, *mskbits; if (on == SCREEN_SAVER_FORCER) { if (mode == ScreenSaverReset) what = SCREEN_SAVER_OFF; else what = SCREEN_SAVER_ON; if (what == screenIsSaved) return ; } else what = on; for (i = 0; i < screenInfo.numScreens; i++) { if (on == SCREEN_SAVER_FORCER) { (* screenInfo.screen[i].SaveScreen) (&screenInfo.screen[i], on); } if (what == SCREEN_SAVER_OFF) { if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) { (* screenInfo.screen[i].SaveScreen) (&screenInfo.screen[i], on); } else if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) { FreeResource((long)savedScreenInfo[i].wid, RC_NONE); savedScreenInfo[i].pWindow = (WindowPtr)NULL; } continue; } else if (what == SCREEN_SAVER_ON) { if (screenIsSaved == SCREEN_SAVER_ON) /* rotate pattern */ { int new_x, new_y; if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) { new_x = random() % RANDOM_WIDTH; new_y = random() % RANDOM_WIDTH; MoveWindow(savedScreenInfo[i].pWindow, -new_x, -new_y, savedScreenInfo[i].pWindow->nextSib, Above); } continue; } if (ScreenSaverBlanking != DontPreferBlanking) { if ((* screenInfo.screen[i].SaveScreen) (&screenInfo.screen[i], what)) { savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; continue; } } if (ScreenSaverAllowExposures != DontAllowExposures) { int result; long attributes[1]; int mask = CWBackPixmap; WindowPtr pWin; CursorMetricRec cm; if (WindowTable[i].backgroundTile == (PixmapPtr)USE_BACKGROUND_PIXEL) { attributes[0] = WindowTable[i].backgroundPixel; mask = CWBackPixel; } else attributes[0] = None; pWin = savedScreenInfo[i].pWindow = CreateWindow(savedScreenInfo[i].wid, &WindowTable[i], -RANDOM_WIDTH, -RANDOM_WIDTH, (unsigned short)screenInfo.screen[i].width + RANDOM_WIDTH, (unsigned short)screenInfo.screen[i].height + RANDOM_WIDTH, 0, InputOutput, mask, attributes, 0, 0, WindowTable[i].visual, &result); if (attributes[0] == None) { pWin->backgroundTile = pWin->parent->backgroundTile; pWin->backgroundTile->refcnt++; (* screenInfo.screen[i].ChangeWindowAttributes) (pWin, CWBackPixmap); } AddResource(pWin->wid, RT_WINDOW, (pointer)savedScreenInfo[i].pWindow, DeleteWindow, RC_CORE); 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 (j=0; jcursor = AllocCursor( srcbits, mskbits, &cm, ~0, ~0, ~0, 0, 0, 0); AddResource(savedScreenInfo[i].cid, RT_CURSOR, (pointer)pWin->cursor, FreeCursor, RC_CORE); pWin->overrideRedirect = TRUE; MapWindow(pWin, TRUE, FALSE, FALSE, (ClientPtr)0); savedScreenInfo[i].blanked = SCREEN_IS_TILED; } else savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; } } screenIsSaved = what; }