3363 lines
99 KiB
C
3363 lines
99 KiB
C
/*
|
|
|
|
Copyright (c) 2006, Red Hat, Inc.
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of Red Hat shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from Red Hat.
|
|
|
|
Copyright 1987, 1998 The Open Group
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
other dealings in this Software without prior written authorization
|
|
from The Open Group.
|
|
|
|
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include "misc.h"
|
|
#include "scrnintstr.h"
|
|
#include "os.h"
|
|
#include "regionstr.h"
|
|
#include "validate.h"
|
|
#include "windowstr.h"
|
|
#include "input.h"
|
|
#include "resource.h"
|
|
#include "colormapst.h"
|
|
#include "cursorstr.h"
|
|
#include "dixstruct.h"
|
|
#include "gcstruct.h"
|
|
#include "servermd.h"
|
|
#include "dixevents.h"
|
|
#include "globals.h"
|
|
|
|
|
|
/******
|
|
* Window stuff for server
|
|
*
|
|
* CreateRootWindow, CreateWindow, ChangeWindowAttributes,
|
|
* GetWindowAttributes, DeleteWindow, DestroySubWindows,
|
|
* HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
|
|
* UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
|
|
*
|
|
******/
|
|
|
|
static const unsigned char _back_lsb[4] = { 0x88, 0x22, 0x44, 0x11 };
|
|
static const unsigned char _back_msb[4] = { 0x11, 0x44, 0x22, 0x88 };
|
|
|
|
_X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF;
|
|
|
|
_X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
|
|
|
|
static Bool TileScreenSaver(int i, int kind);
|
|
|
|
#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
|
|
CWDontPropagate | CWOverrideRedirect | CWCursor )
|
|
|
|
#define BOXES_OVERLAP(b1, b2) \
|
|
(!( ((b1)->x2 <= (b2)->x1) || \
|
|
( ((b1)->x1 >= (b2)->x2)) || \
|
|
( ((b1)->y2 <= (b2)->y1)) || \
|
|
( ((b1)->y1 >= (b2)->y2)) ) )
|
|
|
|
#define RedirectSend(pWin) \
|
|
((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask)
|
|
|
|
#define SubSend(pWin) \
|
|
((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask)
|
|
|
|
#define StrSend(pWin) \
|
|
((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask)
|
|
|
|
#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
|
|
|
|
#ifdef DEBUG
|
|
/******
|
|
* PrintWindowTree
|
|
* For debugging only
|
|
******/
|
|
|
|
int
|
|
PrintChildren(WindowPtr p1, int indent)
|
|
{
|
|
WindowPtr p2;
|
|
|
|
int i;
|
|
|
|
while (p1) {
|
|
p2 = p1->firstChild;
|
|
for (i = 0; i < indent; i++)
|
|
ErrorF(" ");
|
|
ErrorF("%x\n", p1->drawable.id);
|
|
miPrintRegion(&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];
|
|
miPrintRegion(&pWin->clipList);
|
|
p1 = pWin->firstChild;
|
|
PrintChildren(p1, 4);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
_X_EXPORT int
|
|
TraverseTree(register WindowPtr pWin, VisitWindowProcPtr func, pointer data)
|
|
{
|
|
int result;
|
|
|
|
WindowPtr pChild;
|
|
|
|
if (!(pChild = pWin))
|
|
return (WT_NOMATCH);
|
|
while (1) {
|
|
result = (*func) (pChild, data);
|
|
if (result == WT_STOPWALKING)
|
|
return (WT_STOPWALKING);
|
|
if ((result == WT_WALKCHILDREN) && pChild->firstChild) {
|
|
pChild = pChild->firstChild;
|
|
continue;
|
|
}
|
|
while (!pChild->nextSib && (pChild != pWin))
|
|
pChild = pChild->parent;
|
|
if (pChild == pWin)
|
|
break;
|
|
pChild = pChild->nextSib;
|
|
}
|
|
return (WT_NOMATCH);
|
|
}
|
|
|
|
/*****
|
|
* 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.
|
|
*****/
|
|
|
|
_X_EXPORT int
|
|
WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data)
|
|
{
|
|
return (TraverseTree(WindowTable[pScreen->myNum], func, data));
|
|
}
|
|
|
|
/* hack for forcing backing store on all windows */
|
|
static const int defaultBackingStore = NotUseful;
|
|
|
|
static void
|
|
SetWindowToDefaults(register WindowPtr pWin)
|
|
{
|
|
pWin->prevSib = NullWindow;
|
|
pWin->firstChild = NullWindow;
|
|
pWin->lastChild = NullWindow;
|
|
|
|
pWin->valdata = (ValidatePtr) NULL;
|
|
pWin->optional = (WindowOptPtr) NULL;
|
|
pWin->cursorIsNone = TRUE;
|
|
|
|
pWin->backingStore = NotUseful;
|
|
pWin->DIXsaveUnder = FALSE;
|
|
pWin->backStorage = (pointer) NULL;
|
|
|
|
pWin->mapped = FALSE; /* off */
|
|
pWin->realized = FALSE; /* off */
|
|
pWin->viewable = FALSE;
|
|
pWin->visibility = VisibilityNotViewable;
|
|
pWin->overrideRedirect = FALSE;
|
|
pWin->saveUnder = FALSE;
|
|
|
|
pWin->bitGravity = ForgetGravity;
|
|
pWin->winGravity = NorthWestGravity;
|
|
|
|
pWin->eventMask = 0;
|
|
pWin->deliverableEvents = 0;
|
|
pWin->dontPropagate = 0;
|
|
pWin->forcedBS = FALSE;
|
|
#ifdef NEED_DBE_BUF_BITS
|
|
pWin->srcBuffer = DBE_FRONT_BUFFER;
|
|
pWin->dstBuffer = DBE_FRONT_BUFFER;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
MakeRootTile(WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
GCPtr pGC;
|
|
|
|
unsigned char back[128];
|
|
|
|
int len = BitmapBytePad(sizeof(long));
|
|
|
|
const unsigned char *from;
|
|
unsigned char *to;
|
|
|
|
int i, j;
|
|
|
|
pWin->background.pixmap = (*pScreen->CreatePixmap) (pScreen, 4, 4,
|
|
pScreen->rootDepth);
|
|
|
|
pWin->backgroundState = BackgroundPixmap;
|
|
pGC = GetScratchGC(pScreen->rootDepth, pScreen);
|
|
if (!pWin->background.pixmap || !pGC)
|
|
FatalError("could not create root tile");
|
|
|
|
{
|
|
CARD32 attributes[2];
|
|
|
|
attributes[0] = pScreen->whitePixel;
|
|
attributes[1] = pScreen->blackPixel;
|
|
|
|
(void) ChangeGC(pGC, GCForeground | GCBackground, attributes);
|
|
}
|
|
|
|
ValidateGC((DrawablePtr) pWin->background.pixmap, pGC);
|
|
|
|
from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
|
|
to = back;
|
|
|
|
for (i = 4; i > 0; i--, from++)
|
|
for (j = len; j > 0; j--)
|
|
*to++ = *from;
|
|
|
|
(*pGC->ops->PutImage) ((DrawablePtr) pWin->background.pixmap, pGC, 1,
|
|
0, 0, len, 4, 0, XYBitmap, (char *) back);
|
|
|
|
FreeScratchGC(pGC);
|
|
|
|
}
|
|
|
|
WindowPtr
|
|
AllocateWindow(ScreenPtr pScreen)
|
|
{
|
|
WindowPtr pWin;
|
|
|
|
char *ptr;
|
|
|
|
DevUnion *ppriv;
|
|
|
|
unsigned *sizes;
|
|
|
|
unsigned size;
|
|
|
|
int i;
|
|
|
|
pWin = malloc(pScreen->totalWindowSize);
|
|
if (pWin) {
|
|
ppriv = (DevUnion *) (pWin + 1);
|
|
pWin->devPrivates = ppriv;
|
|
sizes = pScreen->WindowPrivateSizes;
|
|
ptr = (char *) (ppriv + pScreen->WindowPrivateLen);
|
|
for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) {
|
|
if ((size = *sizes)) {
|
|
ppriv->ptr = (pointer) ptr;
|
|
ptr += size;
|
|
}
|
|
else
|
|
ppriv->ptr = (pointer) NULL;
|
|
}
|
|
#if _XSERVER64
|
|
pWin->drawable.pad0 = 0;
|
|
pWin->drawable.pad1 = 0;
|
|
#endif
|
|
}
|
|
return pWin;
|
|
}
|
|
|
|
/*****
|
|
* CreateRootWindow
|
|
* Makes a window at initialization time for specified screen
|
|
*****/
|
|
|
|
Bool
|
|
CreateRootWindow(ScreenPtr pScreen)
|
|
{
|
|
WindowPtr pWin;
|
|
|
|
BoxRec box;
|
|
|
|
PixmapFormatRec *format;
|
|
|
|
pWin = AllocateWindow(pScreen);
|
|
if (!pWin)
|
|
return FALSE;
|
|
|
|
savedScreenInfo[pScreen->myNum].pWindow = NULL;
|
|
savedScreenInfo[pScreen->myNum].wid = FakeClientID(0);
|
|
savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL;
|
|
screenIsSaved = SCREEN_SAVER_OFF;
|
|
|
|
WindowTable[pScreen->myNum] = pWin;
|
|
|
|
pWin->drawable.pScreen = pScreen;
|
|
pWin->drawable.type = DRAWABLE_WINDOW;
|
|
|
|
pWin->drawable.depth = pScreen->rootDepth;
|
|
for (format = screenInfo.formats;
|
|
format->depth != pScreen->rootDepth; format++);
|
|
pWin->drawable.bitsPerPixel = format->bitsPerPixel;
|
|
|
|
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
|
|
|
pWin->parent = NullWindow;
|
|
SetWindowToDefaults(pWin);
|
|
|
|
pWin->optional = malloc(sizeof(WindowOptRec));
|
|
if (!pWin->optional)
|
|
return FALSE;
|
|
|
|
pWin->optional->dontPropagateMask = 0;
|
|
pWin->optional->otherEventMasks = 0;
|
|
pWin->optional->otherClients = NULL;
|
|
pWin->optional->passiveGrabs = NULL;
|
|
pWin->optional->userProps = NULL;
|
|
pWin->optional->backingBitPlanes = ~0L;
|
|
pWin->optional->backingPixel = 0;
|
|
pWin->optional->boundingShape = NULL;
|
|
pWin->optional->clipShape = NULL;
|
|
pWin->optional->inputShape = NULL;
|
|
pWin->optional->colormap = pScreen->defColormap;
|
|
pWin->optional->visual = pScreen->rootVisual;
|
|
|
|
pWin->nextSib = NullWindow;
|
|
|
|
pWin->drawable.id = FakeClientID(0);
|
|
|
|
pWin->origin.x = pWin->origin.y = 0;
|
|
pWin->drawable.height = pScreen->height;
|
|
pWin->drawable.width = pScreen->width;
|
|
pWin->drawable.x = pWin->drawable.y = 0;
|
|
|
|
box.x1 = 0;
|
|
box.y1 = 0;
|
|
box.x2 = pScreen->width;
|
|
box.y2 = pScreen->height;
|
|
|
|
BoxRec *boxptr = &box;
|
|
|
|
REGION_INIT(&pWin->clipList, boxptr, 1);
|
|
REGION_INIT(&pWin->winSize, boxptr, 1);
|
|
REGION_INIT(&pWin->borderSize, boxptr, 1);
|
|
REGION_INIT(&pWin->borderClip, boxptr, 1);
|
|
|
|
pWin->drawable.class = InputOutput;
|
|
pWin->optional->visual = pScreen->rootVisual;
|
|
|
|
pWin->backgroundState = BackgroundPixel;
|
|
pWin->background.pixel = pScreen->whitePixel;
|
|
|
|
pWin->borderIsPixel = TRUE;
|
|
pWin->border.pixel = pScreen->blackPixel;
|
|
pWin->borderWidth = 0;
|
|
|
|
if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer) pWin))
|
|
return FALSE;
|
|
|
|
pScreen->saveUnderSupport = NotUseful;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
InitRootWindow(WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
int backFlag = CWBorderPixel | CWCursor | CWBackingStore;
|
|
|
|
if (!(*pScreen->CreateWindow) (pWin))
|
|
return; /* XXX */
|
|
(*pScreen->PositionWindow) (pWin, 0, 0);
|
|
|
|
pWin->cursorIsNone = FALSE;
|
|
pWin->optional->cursor = rootCursor;
|
|
rootCursor->refcnt++;
|
|
|
|
if (!blackRoot && !whiteRoot) {
|
|
MakeRootTile(pWin);
|
|
backFlag |= CWBackPixmap;
|
|
}
|
|
else {
|
|
if (blackRoot)
|
|
pWin->background.pixel = pScreen->blackPixel;
|
|
else
|
|
pWin->background.pixel = pScreen->whitePixel;
|
|
backFlag |= CWBackPixel;
|
|
}
|
|
|
|
pWin->backingStore = defaultBackingStore;
|
|
pWin->forcedBS = (defaultBackingStore != NotUseful);
|
|
/* We SHOULD check for an error value here XXX */
|
|
(*pScreen->ChangeWindowAttributes) (pWin, backFlag);
|
|
|
|
|
|
MapWindow(pWin, serverClient);
|
|
}
|
|
|
|
/* Set the region to the intersection of the rectangle and the
|
|
* window's winSize. The window is typically the parent of the
|
|
* window from which the region came.
|
|
*/
|
|
|
|
void
|
|
ClippedRegionFromBox(register WindowPtr pWin, RegionPtr Rgn,
|
|
register int x, register int y,
|
|
register int w, register int h)
|
|
{
|
|
BoxRec box;
|
|
|
|
box = *(REGION_EXTENTS(&pWin->winSize));
|
|
/* we do these calculations to avoid overflows */
|
|
if (x > box.x1)
|
|
box.x1 = x;
|
|
if (y > box.y1)
|
|
box.y1 = y;
|
|
x += w;
|
|
if (x < box.x2)
|
|
box.x2 = x;
|
|
y += h;
|
|
if (y < box.y2)
|
|
box.y2 = y;
|
|
if (box.x1 > box.x2)
|
|
box.x2 = box.x1;
|
|
if (box.y1 > box.y2)
|
|
box.y2 = box.y1;
|
|
REGION_RESET(Rgn, &box);
|
|
REGION_INTERSECT(Rgn, Rgn, &pWin->winSize);
|
|
}
|
|
|
|
static RealChildHeadProc realChildHeadProc = NULL;
|
|
|
|
void
|
|
RegisterRealChildHeadProc(RealChildHeadProc proc)
|
|
{
|
|
realChildHeadProc = proc;
|
|
}
|
|
|
|
WindowPtr
|
|
RealChildHead(register WindowPtr pWin)
|
|
{
|
|
if (realChildHeadProc) {
|
|
return realChildHeadProc(pWin);
|
|
}
|
|
|
|
if (!pWin->parent &&
|
|
(screenIsSaved == SCREEN_SAVER_ON) &&
|
|
(HasSaverWindow(pWin->drawable.pScreen->myNum)))
|
|
return (pWin->firstChild);
|
|
else
|
|
return (NullWindow);
|
|
}
|
|
|
|
/*****
|
|
* CreateWindow
|
|
* Makes a window in response to client request
|
|
*****/
|
|
|
|
_X_EXPORT WindowPtr
|
|
CreateWindow(Window wid, register WindowPtr pParent, int x, int y, unsigned w,
|
|
unsigned h, unsigned bw, unsigned class, register Mask vmask,
|
|
XID *vlist, int depth, ClientPtr client, VisualID visual,
|
|
int *error)
|
|
{
|
|
WindowPtr pWin;
|
|
|
|
WindowPtr pHead;
|
|
|
|
ScreenPtr pScreen;
|
|
|
|
xEvent event;
|
|
|
|
int idepth, ivisual;
|
|
|
|
Bool fOK;
|
|
|
|
DepthPtr pDepth;
|
|
|
|
PixmapFormatRec *format;
|
|
|
|
WindowOptPtr ancwopt;
|
|
|
|
if (class == CopyFromParent)
|
|
class = pParent->drawable.class;
|
|
|
|
if ((class != InputOutput) && (class != InputOnly)) {
|
|
*error = BadValue;
|
|
client->errorValue = class;
|
|
return NullWindow;
|
|
}
|
|
|
|
if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) {
|
|
*error = BadMatch;
|
|
return NullWindow;
|
|
}
|
|
|
|
if ((class == InputOnly) && ((bw != 0) || (depth != 0))) {
|
|
*error = BadMatch;
|
|
return NullWindow;
|
|
}
|
|
|
|
pScreen = pParent->drawable.pScreen;
|
|
if ((class == InputOutput) && (depth == 0))
|
|
depth = pParent->drawable.depth;
|
|
ancwopt = pParent->optional;
|
|
if (!ancwopt)
|
|
ancwopt = FindWindowWithOptional(pParent)->optional;
|
|
if (visual == CopyFromParent) {
|
|
visual = ancwopt->visual;
|
|
}
|
|
|
|
/* Find out if the depth and visual are acceptable for this Screen */
|
|
if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) {
|
|
fOK = FALSE;
|
|
for (idepth = 0; idepth < pScreen->numDepths; idepth++) {
|
|
pDepth = (DepthPtr) & pScreen->allowedDepths[idepth];
|
|
if ((depth == pDepth->depth) || (depth == 0)) {
|
|
for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) {
|
|
if (visual == pDepth->vids[ivisual]) {
|
|
fOK = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (fOK == FALSE) {
|
|
*error = BadMatch;
|
|
return NullWindow;
|
|
}
|
|
}
|
|
|
|
if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
|
|
(class != InputOnly) && (depth != pParent->drawable.depth)) {
|
|
*error = BadMatch;
|
|
return NullWindow;
|
|
}
|
|
|
|
if (((vmask & CWColormap) == 0) &&
|
|
(class != InputOnly) &&
|
|
((visual != ancwopt->visual) || (ancwopt->colormap == None))) {
|
|
*error = BadMatch;
|
|
return NullWindow;
|
|
}
|
|
|
|
pWin = AllocateWindow(pScreen);
|
|
if (!pWin) {
|
|
*error = BadAlloc;
|
|
return NullWindow;
|
|
}
|
|
pWin->drawable = pParent->drawable;
|
|
pWin->drawable.depth = depth;
|
|
if (depth == pParent->drawable.depth)
|
|
pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
|
|
else {
|
|
for (format = screenInfo.formats; format->depth != depth; format++);
|
|
pWin->drawable.bitsPerPixel = format->bitsPerPixel;
|
|
}
|
|
if (class == InputOnly)
|
|
pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
|
|
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
|
|
|
pWin->drawable.id = wid;
|
|
pWin->drawable.class = class;
|
|
|
|
pWin->parent = pParent;
|
|
SetWindowToDefaults(pWin);
|
|
|
|
if (visual != ancwopt->visual) {
|
|
if (!MakeWindowOptional(pWin)) {
|
|
free(pWin);
|
|
*error = BadAlloc;
|
|
return NullWindow;
|
|
}
|
|
pWin->optional->visual = visual;
|
|
pWin->optional->colormap = None;
|
|
}
|
|
|
|
pWin->borderWidth = bw;
|
|
pWin->backgroundState = None;
|
|
|
|
pWin->borderIsPixel = pParent->borderIsPixel;
|
|
pWin->border = pParent->border;
|
|
if (pWin->borderIsPixel == FALSE)
|
|
pWin->border.pixmap->refcnt++;
|
|
|
|
pWin->origin.x = x + (int) bw;
|
|
pWin->origin.y = y + (int) bw;
|
|
pWin->drawable.width = w;
|
|
pWin->drawable.height = h;
|
|
pWin->drawable.x = pParent->drawable.x + x + (int) bw;
|
|
pWin->drawable.y = pParent->drawable.y + y + (int) bw;
|
|
|
|
/* set up clip list correctly for unobscured WindowPtr */
|
|
REGION_NULL(&pWin->clipList);
|
|
REGION_NULL(&pWin->borderClip);
|
|
REGION_NULL(&pWin->winSize);
|
|
REGION_NULL(&pWin->borderSize);
|
|
|
|
|
|
pHead = RealChildHead(pParent);
|
|
if (pHead) {
|
|
pWin->nextSib = pHead->nextSib;
|
|
if (pHead->nextSib)
|
|
pHead->nextSib->prevSib = pWin;
|
|
else
|
|
pParent->lastChild = pWin;
|
|
pHead->nextSib = pWin;
|
|
pWin->prevSib = pHead;
|
|
}
|
|
else {
|
|
pWin->nextSib = pParent->firstChild;
|
|
if (pParent->firstChild)
|
|
pParent->firstChild->prevSib = pWin;
|
|
else
|
|
pParent->lastChild = pWin;
|
|
pParent->firstChild = pWin;
|
|
}
|
|
|
|
SetWinSize(pWin);
|
|
SetBorderSize(pWin);
|
|
|
|
/* We SHOULD check for an error value here XXX */
|
|
if (!(*pScreen->CreateWindow) (pWin)) {
|
|
*error = BadAlloc;
|
|
DeleteWindow(pWin, None);
|
|
return NullWindow;
|
|
}
|
|
/* We SHOULD check for an error value here XXX */
|
|
(*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
|
|
|
|
if (!(vmask & CWEventMask))
|
|
RecalculateDeliverableEvents(pWin);
|
|
|
|
if (vmask)
|
|
*error = ChangeWindowAttributes(pWin, vmask, vlist, wClient(pWin));
|
|
else
|
|
*error = Success;
|
|
|
|
if (*error != Success) {
|
|
DeleteWindow(pWin, None);
|
|
return NullWindow;
|
|
}
|
|
if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) {
|
|
XID value = defaultBackingStore;
|
|
|
|
(void) ChangeWindowAttributes(pWin, CWBackingStore, &value,
|
|
wClient(pWin));
|
|
pWin->forcedBS = TRUE;
|
|
}
|
|
|
|
if (SubSend(pParent)) {
|
|
event.u.u.type = CreateNotify;
|
|
event.u.createNotify.window = wid;
|
|
event.u.createNotify.parent = pParent->drawable.id;
|
|
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(pParent, &event, 1, NullWindow);
|
|
}
|
|
return pWin;
|
|
}
|
|
|
|
static void
|
|
FreeWindowResources(register WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
DeleteWindowFromAnySaveSet(pWin);
|
|
DeleteWindowFromAnySelections(pWin);
|
|
DeleteWindowFromAnyEvents(pWin, TRUE);
|
|
REGION_UNINIT(&pWin->clipList);
|
|
REGION_UNINIT(&pWin->winSize);
|
|
REGION_UNINIT(&pWin->borderClip);
|
|
REGION_UNINIT(&pWin->borderSize);
|
|
if (wBoundingShape(pWin))
|
|
REGION_DESTROY(wBoundingShape(pWin));
|
|
if (wClipShape(pWin))
|
|
REGION_DESTROY(wClipShape(pWin));
|
|
if (wInputShape(pWin))
|
|
REGION_DESTROY(wInputShape(pWin));
|
|
if (pWin->borderIsPixel == FALSE)
|
|
(*pScreen->DestroyPixmap) (pWin->border.pixmap);
|
|
if (pWin->backgroundState == BackgroundPixmap)
|
|
(*pScreen->DestroyPixmap) (pWin->background.pixmap);
|
|
|
|
DeleteAllWindowProperties(pWin);
|
|
/* We SHOULD check for an error value here XXX */
|
|
(*pScreen->DestroyWindow) (pWin);
|
|
DisposeWindowOptional(pWin);
|
|
}
|
|
|
|
static void
|
|
CrushTree(WindowPtr pWin)
|
|
{
|
|
WindowPtr pChild, pSib, pParent;
|
|
|
|
UnrealizeWindowProcPtr UnrealizeWindow;
|
|
|
|
xEvent event;
|
|
|
|
if (!(pChild = pWin->firstChild))
|
|
return;
|
|
UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
|
|
while (1) {
|
|
if (pChild->firstChild) {
|
|
pChild = pChild->firstChild;
|
|
continue;
|
|
}
|
|
while (1) {
|
|
pParent = pChild->parent;
|
|
if (SubStrSend(pChild, pParent)) {
|
|
event.u.u.type = DestroyNotify;
|
|
event.u.destroyNotify.window = pChild->drawable.id;
|
|
DeliverEvents(pChild, &event, 1, NullWindow);
|
|
}
|
|
FreeResource(pChild->drawable.id, RT_WINDOW);
|
|
pSib = pChild->nextSib;
|
|
pChild->viewable = FALSE;
|
|
if (pChild->realized) {
|
|
pChild->realized = FALSE;
|
|
(*UnrealizeWindow) (pChild);
|
|
}
|
|
FreeWindowResources(pChild);
|
|
free(pChild);
|
|
if ((pChild = pSib))
|
|
break;
|
|
pChild = pParent;
|
|
pChild->firstChild = NullWindow;
|
|
pChild->lastChild = NullWindow;
|
|
if (pChild == pWin)
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****
|
|
* DeleteWindow
|
|
* Deletes child of window then window itself
|
|
* If wid is None, don't send any events
|
|
*****/
|
|
|
|
int
|
|
DeleteWindow(pointer value, XID wid)
|
|
{
|
|
WindowPtr pParent;
|
|
|
|
WindowPtr pWin = (WindowPtr) value;
|
|
|
|
xEvent event;
|
|
|
|
UnmapWindow(pWin, FALSE);
|
|
|
|
CrushTree(pWin);
|
|
|
|
pParent = pWin->parent;
|
|
if (wid && pParent && SubStrSend(pWin, pParent)) {
|
|
event.u.u.type = DestroyNotify;
|
|
event.u.destroyNotify.window = pWin->drawable.id;
|
|
DeliverEvents(pWin, &event, 1, NullWindow);
|
|
}
|
|
|
|
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;
|
|
}
|
|
free(pWin);
|
|
return Success;
|
|
}
|
|
|
|
void
|
|
DestroySubwindows(register WindowPtr pWin, ClientPtr client)
|
|
{
|
|
/* XXX
|
|
* The protocol is quite clear that each window should be
|
|
* destroyed in turn, however, unmapping all of the first
|
|
* eliminates most of the calls to ValidateTree. So,
|
|
* this implementation is incorrect in that all of the
|
|
* UnmapNotifies occur before all of the DestroyNotifies.
|
|
* If you care, simply delete the call to UnmapSubwindows.
|
|
*/
|
|
UnmapSubwindows(pWin);
|
|
while (pWin->lastChild)
|
|
FreeResource(pWin->lastChild->drawable.id, RT_NONE);
|
|
}
|
|
|
|
#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \
|
|
ButtonReleaseMask | PointerMotionMask)
|
|
|
|
/*****
|
|
* 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.
|
|
*****/
|
|
|
|
_X_EXPORT int
|
|
ChangeWindowAttributes(register WindowPtr pWin, Mask vmask, XID *vlist,
|
|
ClientPtr client)
|
|
{
|
|
Mask index2;
|
|
|
|
XID *pVlist;
|
|
|
|
PixmapPtr pPixmap;
|
|
|
|
Pixmap pixID;
|
|
|
|
CursorPtr pCursor, pOldCursor;
|
|
|
|
Cursor cursorID;
|
|
|
|
WindowPtr pChild;
|
|
|
|
Colormap cmap;
|
|
|
|
ColormapPtr pCmap;
|
|
|
|
xEvent xE;
|
|
|
|
int result;
|
|
|
|
ScreenPtr pScreen;
|
|
|
|
Mask vmaskCopy = 0;
|
|
|
|
Mask tmask;
|
|
|
|
unsigned int val;
|
|
|
|
int error;
|
|
|
|
Bool checkOptional = FALSE;
|
|
|
|
Bool borderRelative = FALSE;
|
|
|
|
if ((pWin->drawable.class == InputOnly) &&
|
|
(vmask & (~INPUTONLY_LEGAL_MASK)))
|
|
return BadMatch;
|
|
|
|
error = Success;
|
|
pScreen = pWin->drawable.pScreen;
|
|
pVlist = vlist;
|
|
tmask = vmask;
|
|
while (tmask) {
|
|
index2 = (Mask) lowbit(tmask);
|
|
tmask &= ~index2;
|
|
switch (index2) {
|
|
case CWBackPixmap:
|
|
pixID = (Pixmap) * pVlist;
|
|
pVlist++;
|
|
if (pWin->backgroundState == ParentRelative)
|
|
borderRelative = TRUE;
|
|
if (pixID == None) {
|
|
if (pWin->backgroundState == BackgroundPixmap)
|
|
(*pScreen->DestroyPixmap) (pWin->background.pixmap);
|
|
if (!pWin->parent)
|
|
MakeRootTile(pWin);
|
|
else
|
|
pWin->backgroundState = None;
|
|
}
|
|
else if (pixID == ParentRelative) {
|
|
if (pWin->parent &&
|
|
pWin->drawable.depth != pWin->parent->drawable.depth) {
|
|
error = BadMatch;
|
|
goto PatchUp;
|
|
}
|
|
if (pWin->backgroundState == BackgroundPixmap)
|
|
(*pScreen->DestroyPixmap) (pWin->background.pixmap);
|
|
if (!pWin->parent)
|
|
MakeRootTile(pWin);
|
|
else
|
|
pWin->backgroundState = ParentRelative;
|
|
borderRelative = TRUE;
|
|
/* Note that the parent's backgroundTile's refcnt is NOT
|
|
* incremented. */
|
|
}
|
|
else {
|
|
pPixmap = (PixmapPtr) SecurityLookupIDByType(client, pixID,
|
|
RT_PIXMAP,
|
|
SecurityReadAccess);
|
|
if (pPixmap != (PixmapPtr) NULL) {
|
|
if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
|
|
(pPixmap->drawable.pScreen != pScreen)) {
|
|
error = BadMatch;
|
|
goto PatchUp;
|
|
}
|
|
if (pWin->backgroundState == BackgroundPixmap)
|
|
(*pScreen->DestroyPixmap) (pWin->background.pixmap);
|
|
pWin->backgroundState = BackgroundPixmap;
|
|
pWin->background.pixmap = pPixmap;
|
|
pPixmap->refcnt++;
|
|
}
|
|
else {
|
|
error = BadPixmap;
|
|
client->errorValue = pixID;
|
|
goto PatchUp;
|
|
}
|
|
}
|
|
break;
|
|
case CWBackPixel:
|
|
if (pWin->backgroundState == ParentRelative)
|
|
borderRelative = TRUE;
|
|
if (pWin->backgroundState == BackgroundPixmap)
|
|
(*pScreen->DestroyPixmap) (pWin->background.pixmap);
|
|
pWin->backgroundState = BackgroundPixel;
|
|
pWin->background.pixel = (CARD32) *pVlist;
|
|
/* background pixel overrides background pixmap,
|
|
so don't let the ddx layer see both bits */
|
|
vmaskCopy &= ~CWBackPixmap;
|
|
pVlist++;
|
|
break;
|
|
case CWBorderPixmap:
|
|
pixID = (Pixmap) * pVlist;
|
|
pVlist++;
|
|
if (pixID == CopyFromParent) {
|
|
if (!pWin->parent ||
|
|
(pWin->drawable.depth != pWin->parent->drawable.depth)) {
|
|
error = BadMatch;
|
|
goto PatchUp;
|
|
}
|
|
if (pWin->borderIsPixel == FALSE)
|
|
(*pScreen->DestroyPixmap) (pWin->border.pixmap);
|
|
pWin->border = pWin->parent->border;
|
|
if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) {
|
|
index2 = CWBorderPixel;
|
|
}
|
|
else {
|
|
pWin->parent->border.pixmap->refcnt++;
|
|
}
|
|
}
|
|
else {
|
|
pPixmap = (PixmapPtr) SecurityLookupIDByType(client, pixID,
|
|
RT_PIXMAP,
|
|
SecurityReadAccess);
|
|
if (pPixmap) {
|
|
if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
|
|
(pPixmap->drawable.pScreen != pScreen)) {
|
|
error = BadMatch;
|
|
goto PatchUp;
|
|
}
|
|
if (pWin->borderIsPixel == FALSE)
|
|
(*pScreen->DestroyPixmap) (pWin->border.pixmap);
|
|
pWin->borderIsPixel = FALSE;
|
|
pWin->border.pixmap = pPixmap;
|
|
pPixmap->refcnt++;
|
|
}
|
|
else {
|
|
error = BadPixmap;
|
|
client->errorValue = pixID;
|
|
goto PatchUp;
|
|
}
|
|
}
|
|
break;
|
|
case CWBorderPixel:
|
|
if (pWin->borderIsPixel == FALSE)
|
|
(*pScreen->DestroyPixmap) (pWin->border.pixmap);
|
|
pWin->borderIsPixel = TRUE;
|
|
pWin->border.pixel = (CARD32) *pVlist;
|
|
/* border pixel overrides border pixmap,
|
|
so don't let the ddx layer see both bits */
|
|
vmaskCopy &= ~CWBorderPixmap;
|
|
pVlist++;
|
|
break;
|
|
case CWBitGravity:
|
|
val = (CARD8) *pVlist;
|
|
pVlist++;
|
|
if (val > StaticGravity) {
|
|
error = BadValue;
|
|
client->errorValue = val;
|
|
goto PatchUp;
|
|
}
|
|
pWin->bitGravity = val;
|
|
break;
|
|
case CWWinGravity:
|
|
val = (CARD8) *pVlist;
|
|
pVlist++;
|
|
if (val > StaticGravity) {
|
|
error = BadValue;
|
|
client->errorValue = val;
|
|
goto PatchUp;
|
|
}
|
|
pWin->winGravity = val;
|
|
break;
|
|
case CWBackingStore:
|
|
val = (CARD8) *pVlist;
|
|
pVlist++;
|
|
if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) {
|
|
error = BadValue;
|
|
client->errorValue = val;
|
|
goto PatchUp;
|
|
}
|
|
pWin->backingStore = val;
|
|
pWin->forcedBS = FALSE;
|
|
break;
|
|
case CWBackingPlanes:
|
|
if (pWin->optional || ((CARD32) *pVlist != (CARD32) ~0L)) {
|
|
if (!pWin->optional && !MakeWindowOptional(pWin)) {
|
|
error = BadAlloc;
|
|
goto PatchUp;
|
|
}
|
|
pWin->optional->backingBitPlanes = (CARD32) *pVlist;
|
|
if ((CARD32) *pVlist == (CARD32) ~0L)
|
|
checkOptional = TRUE;
|
|
}
|
|
pVlist++;
|
|
break;
|
|
case CWBackingPixel:
|
|
if (pWin->optional || (CARD32) *pVlist) {
|
|
if (!pWin->optional && !MakeWindowOptional(pWin)) {
|
|
error = BadAlloc;
|
|
goto PatchUp;
|
|
}
|
|
pWin->optional->backingPixel = (CARD32) *pVlist;
|
|
if (!*pVlist)
|
|
checkOptional = TRUE;
|
|
}
|
|
pVlist++;
|
|
break;
|
|
case CWSaveUnder:
|
|
val = (BOOL) * pVlist;
|
|
pVlist++;
|
|
if ((val != xTrue) && (val != xFalse)) {
|
|
error = BadValue;
|
|
client->errorValue = val;
|
|
goto PatchUp;
|
|
}
|
|
pWin->saveUnder = val;
|
|
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,
|
|
&checkOptional);
|
|
if (result) {
|
|
error = result;
|
|
goto PatchUp;
|
|
}
|
|
pVlist++;
|
|
break;
|
|
case CWOverrideRedirect:
|
|
val = (BOOL) * pVlist;
|
|
pVlist++;
|
|
if ((val != xTrue) && (val != xFalse)) {
|
|
error = BadValue;
|
|
client->errorValue = val;
|
|
goto PatchUp;
|
|
}
|
|
pWin->overrideRedirect = val;
|
|
break;
|
|
case CWColormap:
|
|
cmap = (Colormap) * pVlist;
|
|
pVlist++;
|
|
if (cmap == CopyFromParent) {
|
|
if (pWin->parent &&
|
|
(!pWin->optional ||
|
|
pWin->optional->visual == wVisual(pWin->parent))) {
|
|
cmap = wColormap(pWin->parent);
|
|
}
|
|
else
|
|
cmap = None;
|
|
}
|
|
if (cmap == None) {
|
|
error = BadMatch;
|
|
goto PatchUp;
|
|
}
|
|
pCmap = (ColormapPtr) SecurityLookupIDByType(client, cmap,
|
|
RT_COLORMAP,
|
|
SecurityReadAccess);
|
|
if (!pCmap) {
|
|
error = BadColor;
|
|
client->errorValue = cmap;
|
|
goto PatchUp;
|
|
}
|
|
if (pCmap->pVisual->vid != wVisual(pWin) ||
|
|
pCmap->pScreen != pScreen) {
|
|
error = BadMatch;
|
|
goto PatchUp;
|
|
}
|
|
if (cmap != wColormap(pWin)) {
|
|
if (!pWin->optional) {
|
|
if (!MakeWindowOptional(pWin)) {
|
|
error = BadAlloc;
|
|
goto PatchUp;
|
|
}
|
|
}
|
|
else if (pWin->parent && cmap == wColormap(pWin->parent))
|
|
checkOptional = TRUE;
|
|
|
|
/*
|
|
* propagate the original colormap to any children
|
|
* inheriting it
|
|
*/
|
|
|
|
for (pChild = pWin->firstChild; pChild;
|
|
pChild = pChild->nextSib) {
|
|
if (!pChild->optional && !MakeWindowOptional(pChild)) {
|
|
error = BadAlloc;
|
|
goto PatchUp;
|
|
}
|
|
}
|
|
|
|
pWin->optional->colormap = cmap;
|
|
|
|
/*
|
|
* check on any children now matching the new colormap
|
|
*/
|
|
|
|
for (pChild = pWin->firstChild; pChild;
|
|
pChild = pChild->nextSib) {
|
|
if (pChild->optional->colormap == cmap)
|
|
CheckWindowOptionalNeed(pChild);
|
|
}
|
|
|
|
xE.u.u.type = ColormapNotify;
|
|
xE.u.colormap.window = pWin->drawable.id;
|
|
xE.u.colormap.colormap = cmap;
|
|
xE.u.colormap.new = xTrue;
|
|
xE.u.colormap.state = IsMapInstalled(cmap, pWin);
|
|
DeliverEvents(pWin, &xE, 1, NullWindow);
|
|
}
|
|
break;
|
|
case CWCursor:
|
|
cursorID = (Cursor) * pVlist;
|
|
pVlist++;
|
|
/*
|
|
* install the new
|
|
*/
|
|
if (cursorID == None) {
|
|
if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
|
|
pCursor = rootCursor;
|
|
else
|
|
pCursor = (CursorPtr) None;
|
|
}
|
|
else {
|
|
pCursor = (CursorPtr) SecurityLookupIDByType(client, cursorID,
|
|
RT_CURSOR,
|
|
SecurityReadAccess);
|
|
if (!pCursor) {
|
|
error = BadCursor;
|
|
client->errorValue = cursorID;
|
|
goto PatchUp;
|
|
}
|
|
}
|
|
|
|
if (pCursor != wCursor(pWin)) {
|
|
/*
|
|
* patch up child windows so they don't lose cursors.
|
|
*/
|
|
|
|
for (pChild = pWin->firstChild; pChild;
|
|
pChild = pChild->nextSib) {
|
|
if (!pChild->optional && !pChild->cursorIsNone &&
|
|
!MakeWindowOptional(pChild)) {
|
|
error = BadAlloc;
|
|
goto PatchUp;
|
|
}
|
|
}
|
|
|
|
pOldCursor = 0;
|
|
if (pCursor == (CursorPtr) None) {
|
|
pWin->cursorIsNone = TRUE;
|
|
if (pWin->optional) {
|
|
pOldCursor = pWin->optional->cursor;
|
|
pWin->optional->cursor = (CursorPtr) None;
|
|
checkOptional = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
if (!pWin->optional) {
|
|
if (!MakeWindowOptional(pWin)) {
|
|
error = BadAlloc;
|
|
goto PatchUp;
|
|
}
|
|
}
|
|
else if (pWin->parent && pCursor == wCursor(pWin->parent))
|
|
checkOptional = TRUE;
|
|
pOldCursor = pWin->optional->cursor;
|
|
pWin->optional->cursor = pCursor;
|
|
pCursor->refcnt++;
|
|
pWin->cursorIsNone = FALSE;
|
|
/*
|
|
* check on any children now matching the new cursor
|
|
*/
|
|
|
|
for (pChild = pWin->firstChild; pChild;
|
|
pChild = pChild->nextSib) {
|
|
if (pChild->optional &&
|
|
(pChild->optional->cursor == pCursor))
|
|
CheckWindowOptionalNeed(pChild);
|
|
}
|
|
}
|
|
|
|
if (pWin->realized)
|
|
WindowHasNewCursor(pWin);
|
|
|
|
/* Can't free cursor until here - old cursor
|
|
* is needed in WindowHasNewCursor
|
|
*/
|
|
if (pOldCursor)
|
|
FreeCursor(pOldCursor, (Cursor) 0);
|
|
}
|
|
break;
|
|
default:
|
|
error = BadValue;
|
|
client->errorValue = vmask;
|
|
goto PatchUp;
|
|
}
|
|
vmaskCopy |= index2;
|
|
}
|
|
PatchUp:
|
|
if (checkOptional)
|
|
CheckWindowOptionalNeed(pWin);
|
|
|
|
/* We SHOULD check for an error value here XXX */
|
|
(*pScreen->ChangeWindowAttributes) (pWin, vmaskCopy);
|
|
|
|
/*
|
|
If the border contents have 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)) || borderRelative)
|
|
&& pWin->viewable && HasBorder(pWin)) {
|
|
RegionRec exposed;
|
|
|
|
REGION_NULL(&exposed);
|
|
REGION_SUBTRACT(&exposed, &pWin->borderClip, &pWin->winSize);
|
|
(*pWin->drawable.pScreen->PaintWindowBorder) (pWin, &exposed,
|
|
PW_BORDER);
|
|
REGION_UNINIT(&exposed);
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/*****
|
|
* GetWindowAttributes
|
|
* Notice that this is different than ChangeWindowAttributes
|
|
*****/
|
|
|
|
void
|
|
GetWindowAttributes(register WindowPtr pWin, ClientPtr client,
|
|
xGetWindowAttributesReply * wa)
|
|
{
|
|
wa->type = X_Reply;
|
|
wa->bitGravity = pWin->bitGravity;
|
|
wa->winGravity = pWin->winGravity;
|
|
if (pWin->forcedBS && pWin->backingStore != Always)
|
|
wa->backingStore = NotUseful;
|
|
else
|
|
wa->backingStore = pWin->backingStore;
|
|
wa->length = (sizeof(xGetWindowAttributesReply) -
|
|
sizeof(xGenericReply)) >> 2;
|
|
wa->sequenceNumber = client->sequence;
|
|
wa->backingBitPlanes = wBackingBitPlanes(pWin);
|
|
wa->backingPixel = wBackingPixel(pWin);
|
|
wa->saveUnder = (BOOL) pWin->saveUnder;
|
|
wa->override = pWin->overrideRedirect;
|
|
if (!pWin->mapped)
|
|
wa->mapState = IsUnmapped;
|
|
else if (pWin->realized)
|
|
wa->mapState = IsViewable;
|
|
else
|
|
wa->mapState = IsUnviewable;
|
|
|
|
wa->colormap = wColormap(pWin);
|
|
wa->mapInstalled = (wa->colormap == None) ? xFalse
|
|
: IsMapInstalled(wa->colormap, pWin);
|
|
|
|
wa->yourEventMask = EventMaskForClient(pWin, client);
|
|
wa->allEventMasks = pWin->eventMask | wOtherEventMasks(pWin);
|
|
wa->doNotPropagateMask = wDontPropagateMask(pWin);
|
|
wa->class = pWin->drawable.class;
|
|
wa->visualID = wVisual(pWin);
|
|
}
|
|
|
|
_X_EXPORT WindowPtr
|
|
MoveWindowInStack(register WindowPtr pWin, register WindowPtr pNextSib)
|
|
{
|
|
WindowPtr pParent = pWin->parent;
|
|
|
|
WindowPtr pFirstChange = pWin; /* highest window where list changes */
|
|
|
|
if (pWin->nextSib != pNextSib) {
|
|
WindowPtr pOldNextSib = pWin->nextSib;
|
|
|
|
if (!pNextSib) { /* move to bottom */
|
|
if (pParent->firstChild == pWin)
|
|
pParent->firstChild = pWin->nextSib;
|
|
/* if (pWin->nextSib) *//* is always True: pNextSib == NULL
|
|
* and pWin->nextSib != pNextSib
|
|
* therefore pWin->nextSib != NULL */
|
|
pFirstChange = 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 = NullWindow;
|
|
pParent->lastChild = pWin;
|
|
}
|
|
else if (pParent->firstChild == pNextSib) { /* move to top */
|
|
pFirstChange = pWin;
|
|
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 { /* move in middle of list */
|
|
|
|
WindowPtr pOldNext = pWin->nextSib;
|
|
|
|
pFirstChange = NullWindow;
|
|
if (pParent->firstChild == pWin)
|
|
pFirstChange = pParent->firstChild = pWin->nextSib;
|
|
if (pParent->lastChild == pWin) {
|
|
pFirstChange = 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;
|
|
if (!pFirstChange) { /* do we know it yet? */
|
|
pFirstChange = pParent->firstChild; /* no, search from top */
|
|
while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
|
|
pFirstChange = pFirstChange->nextSib;
|
|
}
|
|
}
|
|
if (pWin->drawable.pScreen->RestackWindow)
|
|
(*pWin->drawable.pScreen->RestackWindow) (pWin, pOldNextSib);
|
|
}
|
|
|
|
|
|
return (pFirstChange);
|
|
}
|
|
|
|
_X_EXPORT void
|
|
SetWinSize(register WindowPtr pWin)
|
|
{
|
|
ClippedRegionFromBox(pWin->parent, &pWin->winSize,
|
|
pWin->drawable.x, pWin->drawable.y,
|
|
(int) pWin->drawable.width,
|
|
(int) pWin->drawable.height);
|
|
if (wBoundingShape(pWin) || wClipShape(pWin)) {
|
|
REGION_TRANSLATE(&pWin->winSize, -pWin->drawable.x,
|
|
-pWin->drawable.y);
|
|
if (wBoundingShape(pWin))
|
|
REGION_INTERSECT(&pWin->winSize, &pWin->winSize,
|
|
wBoundingShape(pWin));
|
|
if (wClipShape(pWin))
|
|
REGION_INTERSECT(&pWin->winSize, &pWin->winSize,
|
|
wClipShape(pWin));
|
|
REGION_TRANSLATE(&pWin->winSize, pWin->drawable.x,
|
|
pWin->drawable.y);
|
|
}
|
|
}
|
|
|
|
_X_EXPORT void
|
|
SetBorderSize(register WindowPtr pWin)
|
|
{
|
|
int bw;
|
|
|
|
if (HasBorder(pWin)) {
|
|
bw = wBorderWidth(pWin);
|
|
ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
|
|
pWin->drawable.x - bw, pWin->drawable.y - bw,
|
|
(int) (pWin->drawable.width + (bw << 1)),
|
|
(int) (pWin->drawable.height + (bw << 1)));
|
|
if (wBoundingShape(pWin)) {
|
|
REGION_TRANSLATE(&pWin->borderSize, -pWin->drawable.x,
|
|
-pWin->drawable.y);
|
|
REGION_INTERSECT(&pWin->borderSize, &pWin->borderSize,
|
|
wBoundingShape(pWin));
|
|
REGION_TRANSLATE(&pWin->borderSize, pWin->drawable.x,
|
|
pWin->drawable.y);
|
|
REGION_UNION(&pWin->borderSize, &pWin->borderSize,
|
|
&pWin->winSize);
|
|
}
|
|
}
|
|
else {
|
|
REGION_COPY(&pWin->borderSize, &pWin->winSize);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* \param x,y new window position
|
|
* \param oldx,oldy old window position
|
|
* \param destx,desty position relative to gravity
|
|
*/
|
|
|
|
_X_EXPORT void
|
|
GravityTranslate(register int x, register int y, int oldx, int oldy,
|
|
int dw, int dh, unsigned gravity,
|
|
register int *destx, register int *desty)
|
|
{
|
|
switch (gravity) {
|
|
case NorthGravity:
|
|
*destx = x + dw / 2;
|
|
*desty = y;
|
|
break;
|
|
case NorthEastGravity:
|
|
*destx = x + dw;
|
|
*desty = y;
|
|
break;
|
|
case WestGravity:
|
|
*destx = x;
|
|
*desty = y + dh / 2;
|
|
break;
|
|
case CenterGravity:
|
|
*destx = x + dw / 2;
|
|
*desty = y + dh / 2;
|
|
break;
|
|
case EastGravity:
|
|
*destx = x + dw;
|
|
*desty = y + dh / 2;
|
|
break;
|
|
case SouthWestGravity:
|
|
*destx = x;
|
|
*desty = y + dh;
|
|
break;
|
|
case SouthGravity:
|
|
*destx = x + dw / 2;
|
|
*desty = y + dh;
|
|
break;
|
|
case SouthEastGravity:
|
|
*destx = x + dw;
|
|
*desty = y + dh;
|
|
break;
|
|
case StaticGravity:
|
|
*destx = oldx;
|
|
*desty = oldy;
|
|
break;
|
|
default:
|
|
*destx = x;
|
|
*desty = y;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* XXX need to retile border on each window with ParentRelative origin */
|
|
_X_EXPORT void
|
|
ResizeChildrenWinSize(register WindowPtr pWin, int dx, int dy, int dw, int dh)
|
|
{
|
|
ScreenPtr pScreen;
|
|
|
|
WindowPtr pSib, pChild;
|
|
|
|
Bool resized = (dw || dh);
|
|
|
|
pScreen = pWin->drawable.pScreen;
|
|
|
|
for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) {
|
|
if (resized && (pSib->winGravity > NorthWestGravity)) {
|
|
int cwsx, cwsy;
|
|
|
|
cwsx = pSib->origin.x;
|
|
cwsy = pSib->origin.y;
|
|
GravityTranslate(cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
|
|
pSib->winGravity, &cwsx, &cwsy);
|
|
if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) {
|
|
xEvent event;
|
|
|
|
event.u.u.type = GravityNotify;
|
|
event.u.gravity.window = pSib->drawable.id;
|
|
event.u.gravity.x = cwsx - wBorderWidth(pSib);
|
|
event.u.gravity.y = cwsy - wBorderWidth(pSib);
|
|
DeliverEvents(pSib, &event, 1, NullWindow);
|
|
pSib->origin.x = cwsx;
|
|
pSib->origin.y = cwsy;
|
|
}
|
|
}
|
|
pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
|
|
pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
|
|
SetWinSize(pSib);
|
|
SetBorderSize(pSib);
|
|
(*pScreen->PositionWindow) (pSib, pSib->drawable.x, pSib->drawable.y);
|
|
|
|
if ((pChild = pSib->firstChild)) {
|
|
while (1) {
|
|
pChild->drawable.x = pChild->parent->drawable.x +
|
|
pChild->origin.x;
|
|
pChild->drawable.y = pChild->parent->drawable.y +
|
|
pChild->origin.y;
|
|
SetWinSize(pChild);
|
|
SetBorderSize(pChild);
|
|
(*pScreen->PositionWindow) (pChild,
|
|
pChild->drawable.x,
|
|
pChild->drawable.y);
|
|
if (pChild->firstChild) {
|
|
pChild = pChild->firstChild;
|
|
continue;
|
|
}
|
|
while (!pChild->nextSib && (pChild != pSib))
|
|
pChild = pChild->parent;
|
|
if (pChild == pSib)
|
|
break;
|
|
pChild = pChild->nextSib;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#define GET_INT16(m, f) \
|
|
if (m & mask) \
|
|
{ \
|
|
f = (INT16) *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 ((Mask)(CWX | CWY | CWWidth | CWHeight))
|
|
|
|
#define IllegalInputOnlyConfigureMask (CWBorderWidth)
|
|
|
|
/*
|
|
* IsSiblingAboveMe
|
|
* returns Above if pSib above pMe in stack or Below otherwise
|
|
*/
|
|
|
|
static int
|
|
IsSiblingAboveMe(register WindowPtr pMe, register WindowPtr pSib)
|
|
{
|
|
WindowPtr pWin;
|
|
|
|
pWin = pMe->parent->firstChild;
|
|
while (pWin) {
|
|
if (pWin == pSib)
|
|
return (Above);
|
|
else if (pWin == pMe)
|
|
return (Below);
|
|
pWin = pWin->nextSib;
|
|
}
|
|
return (Below);
|
|
}
|
|
|
|
static BoxPtr
|
|
WindowExtents(register WindowPtr pWin, register BoxPtr pBox)
|
|
{
|
|
pBox->x1 = pWin->drawable.x - wBorderWidth(pWin);
|
|
pBox->y1 = pWin->drawable.y - wBorderWidth(pWin);
|
|
pBox->x2 = pWin->drawable.x + (int) pWin->drawable.width
|
|
+ wBorderWidth(pWin);
|
|
pBox->y2 = pWin->drawable.y + (int) pWin->drawable.height
|
|
+ wBorderWidth(pWin);
|
|
return (pBox);
|
|
}
|
|
|
|
#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL)
|
|
|
|
static RegionPtr
|
|
MakeBoundingRegion(register WindowPtr pWin, BoxPtr pBox)
|
|
{
|
|
RegionPtr pRgn;
|
|
|
|
pRgn = REGION_CREATE(pBox, 1);
|
|
if (wBoundingShape(pWin)) {
|
|
REGION_TRANSLATE(pRgn, -pWin->origin.x, -pWin->origin.y);
|
|
REGION_INTERSECT(pRgn, pRgn, wBoundingShape(pWin));
|
|
REGION_TRANSLATE(pRgn, pWin->origin.x, pWin->origin.y);
|
|
}
|
|
return pRgn;
|
|
}
|
|
|
|
static Bool
|
|
ShapeOverlap(WindowPtr pWin, BoxPtr pWinBox, WindowPtr pSib, BoxPtr pSibBox)
|
|
{
|
|
RegionPtr pWinRgn, pSibRgn;
|
|
|
|
Bool ret;
|
|
|
|
if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
|
|
return TRUE;
|
|
pWinRgn = MakeBoundingRegion(pWin, pWinBox);
|
|
pSibRgn = MakeBoundingRegion(pSib, pSibBox);
|
|
REGION_INTERSECT(pWinRgn, pWinRgn, pSibRgn);
|
|
ret = REGION_NOTEMPTY(pWinRgn);
|
|
REGION_DESTROY(pWinRgn);
|
|
REGION_DESTROY(pSibRgn);
|
|
return ret;
|
|
}
|
|
|
|
static Bool
|
|
AnyWindowOverlapsMe(WindowPtr pWin, WindowPtr pHead, register BoxPtr box)
|
|
{
|
|
WindowPtr pSib;
|
|
|
|
BoxRec sboxrec;
|
|
|
|
BoxPtr sbox;
|
|
|
|
for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) {
|
|
if (pSib->mapped) {
|
|
sbox = WindowExtents(pSib, &sboxrec);
|
|
if (BOXES_OVERLAP(sbox, box)
|
|
&& ShapeOverlap(pWin, box, pSib, sbox)
|
|
)
|
|
return (TRUE);
|
|
}
|
|
}
|
|
return (FALSE);
|
|
}
|
|
|
|
static Bool
|
|
IOverlapAnyWindow(WindowPtr pWin, register BoxPtr box)
|
|
{
|
|
WindowPtr pSib;
|
|
|
|
BoxRec sboxrec;
|
|
|
|
BoxPtr sbox;
|
|
|
|
for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) {
|
|
if (pSib->mapped) {
|
|
sbox = WindowExtents(pSib, &sboxrec);
|
|
if (BOXES_OVERLAP(sbox, box)
|
|
&& ShapeOverlap(pWin, box, pSib, sbox)
|
|
)
|
|
return (TRUE);
|
|
}
|
|
}
|
|
return (FALSE);
|
|
}
|
|
|
|
/*
|
|
* WhereDoIGoInTheStack()
|
|
* Given pWin and pSib and the relationshipe smode, return
|
|
* the window that pWin should go ABOVE.
|
|
* If a pSib is specified:
|
|
* Above: pWin is placed just above pSib
|
|
* Below: pWin is placed just below pSib
|
|
* TopIf: if pSib occludes pWin, then pWin is placed
|
|
* at the top of the stack
|
|
* BottomIf: if pWin occludes pSib, then pWin is
|
|
* placed at the bottom of the stack
|
|
* Opposite: if pSib occludes pWin, then pWin is placed at the
|
|
* top of the stack, else if pWin occludes pSib, then
|
|
* pWin is placed at the bottom of the stack
|
|
*
|
|
* If pSib is NULL:
|
|
* Above: pWin is placed at the top of the stack
|
|
* Below: pWin is placed at the bottom of the stack
|
|
* TopIf: if any sibling occludes pWin, then pWin is placed at
|
|
* the top of the stack
|
|
* BottomIf: if pWin occludes any sibline, then pWin is placed at
|
|
* the bottom of the stack
|
|
* Opposite: if any sibling occludes pWin, then pWin is placed at
|
|
* the top of the stack, else if pWin occludes any
|
|
* sibling, then pWin is placed at the bottom of the stack
|
|
*
|
|
*/
|
|
|
|
static WindowPtr
|
|
WhereDoIGoInTheStack(register WindowPtr pWin,
|
|
register WindowPtr pSib,
|
|
short x,
|
|
short y, unsigned short w, unsigned short h, int smode)
|
|
{
|
|
BoxRec box;
|
|
|
|
WindowPtr pHead, pFirst;
|
|
|
|
if ((pWin == pWin->parent->firstChild) && (pWin == pWin->parent->lastChild))
|
|
return ((WindowPtr) NULL);
|
|
pHead = RealChildHead(pWin->parent);
|
|
pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
|
|
box.x1 = x;
|
|
box.y1 = y;
|
|
box.x2 = x + (int) w;
|
|
box.y2 = y + (int) h;
|
|
switch (smode) {
|
|
case Above:
|
|
if (pSib)
|
|
return (pSib);
|
|
else if (pWin == pFirst)
|
|
return (pWin->nextSib);
|
|
else
|
|
return (pFirst);
|
|
case Below:
|
|
if (pSib)
|
|
if (pSib->nextSib != pWin)
|
|
return (pSib->nextSib);
|
|
else
|
|
return (pWin->nextSib);
|
|
else
|
|
return NullWindow;
|
|
case TopIf:
|
|
if ((!pWin->mapped || (pSib && !pSib->mapped)))
|
|
return (pWin->nextSib);
|
|
else if (pSib) {
|
|
if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
|
|
(RECT_IN_REGION(&pSib->borderSize, &box) != rgnOUT))
|
|
return (pFirst);
|
|
else
|
|
return (pWin->nextSib);
|
|
}
|
|
else if (AnyWindowOverlapsMe(pWin, pHead, &box))
|
|
return (pFirst);
|
|
else
|
|
return (pWin->nextSib);
|
|
case BottomIf:
|
|
if ((!pWin->mapped || (pSib && !pSib->mapped)))
|
|
return (pWin->nextSib);
|
|
else if (pSib) {
|
|
if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
|
|
(RECT_IN_REGION(&pSib->borderSize, &box) != rgnOUT))
|
|
return NullWindow;
|
|
else
|
|
return (pWin->nextSib);
|
|
}
|
|
else if (IOverlapAnyWindow(pWin, &box))
|
|
return NullWindow;
|
|
else
|
|
return (pWin->nextSib);
|
|
case Opposite:
|
|
if ((!pWin->mapped || (pSib && !pSib->mapped)))
|
|
return (pWin->nextSib);
|
|
else if (pSib) {
|
|
if (RECT_IN_REGION(&pSib->borderSize, &box) != rgnOUT) {
|
|
if (IsSiblingAboveMe(pWin, pSib) == Above)
|
|
return (pFirst);
|
|
else
|
|
return NullWindow;
|
|
}
|
|
else
|
|
return (pWin->nextSib);
|
|
}
|
|
else if (AnyWindowOverlapsMe(pWin, pHead, &box)) {
|
|
/* If I'm occluded, I can't possibly be the first child
|
|
* if (pWin == pWin->parent->firstChild)
|
|
* return pWin->nextSib;
|
|
*/
|
|
return (pFirst);
|
|
}
|
|
else if (IOverlapAnyWindow(pWin, &box))
|
|
return NullWindow;
|
|
else
|
|
return pWin->nextSib;
|
|
default:
|
|
{
|
|
ErrorF("Internal error in ConfigureWindow, smode == %d\n", smode);
|
|
return pWin->nextSib;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
ReflectStackChange(register WindowPtr pWin,
|
|
register WindowPtr pSib, VTKind kind)
|
|
{
|
|
/* Note that pSib might be NULL */
|
|
|
|
Bool WasViewable = (Bool) pWin->viewable;
|
|
|
|
Bool anyMarked;
|
|
|
|
WindowPtr pFirstChange;
|
|
|
|
WindowPtr pLayerWin;
|
|
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
/* if this is a root window, can't be restacked */
|
|
if (!pWin->parent)
|
|
return;
|
|
|
|
pFirstChange = MoveWindowInStack(pWin, pSib);
|
|
|
|
if (WasViewable) {
|
|
anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
|
|
&pLayerWin);
|
|
if (pLayerWin != pWin)
|
|
pFirstChange = pLayerWin;
|
|
if (anyMarked) {
|
|
(*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, kind);
|
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
|
}
|
|
if (anyMarked && pWin->drawable.pScreen->PostValidateTree)
|
|
(*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange,
|
|
kind);
|
|
}
|
|
if (pWin->realized)
|
|
WindowsRestructured();
|
|
}
|
|
|
|
/*****
|
|
* ConfigureWindow
|
|
*****/
|
|
|
|
int
|
|
ConfigureWindow(register WindowPtr pWin, register Mask mask, XID *vlist,
|
|
ClientPtr client)
|
|
{
|
|
#define RESTACK_WIN 0
|
|
#define MOVE_WIN 1
|
|
#define RESIZE_WIN 2
|
|
#define REBORDER_WIN 3
|
|
WindowPtr pSib = NullWindow;
|
|
|
|
WindowPtr pParent = pWin->parent;
|
|
|
|
Window sibwid = 0;
|
|
|
|
Mask index2, tmask;
|
|
|
|
XID *pVlist;
|
|
|
|
short x, y, beforeX, beforeY;
|
|
|
|
unsigned short w = pWin->drawable.width,
|
|
h = pWin->drawable.height, bw = pWin->borderWidth;
|
|
int action, smode = Above;
|
|
|
|
xEvent event;
|
|
|
|
if ((pWin->drawable.class == InputOnly) &&
|
|
(mask & IllegalInputOnlyConfigureMask))
|
|
return (BadMatch);
|
|
|
|
if ((mask & CWSibling) && !(mask & CWStackMode))
|
|
return (BadMatch);
|
|
|
|
pVlist = vlist;
|
|
|
|
if (pParent) {
|
|
x = pWin->drawable.x - pParent->drawable.x - (int) bw;
|
|
y = pWin->drawable.y - pParent->drawable.y - (int) bw;
|
|
}
|
|
else {
|
|
x = pWin->drawable.x;
|
|
y = pWin->drawable.y;
|
|
}
|
|
beforeX = x;
|
|
beforeY = y;
|
|
action = RESTACK_WIN;
|
|
if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) {
|
|
GET_INT16(CWX, x);
|
|
GET_INT16(CWY, y);
|
|
action = MOVE_WIN;
|
|
}
|
|
/* 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) {
|
|
client->errorValue = 0;
|
|
return BadValue;
|
|
}
|
|
action = RESIZE_WIN;
|
|
}
|
|
tmask = mask & ~ChangeMask;
|
|
while (tmask) {
|
|
index2 = (Mask) lowbit(tmask);
|
|
tmask &= ~index2;
|
|
switch (index2) {
|
|
case CWBorderWidth:
|
|
GET_CARD16(CWBorderWidth, bw);
|
|
break;
|
|
case CWSibling:
|
|
sibwid = (Window) *pVlist;
|
|
pVlist++;
|
|
pSib = (WindowPtr) SecurityLookupIDByType(client, sibwid,
|
|
RT_WINDOW,
|
|
SecurityReadAccess);
|
|
if (!pSib) {
|
|
client->errorValue = sibwid;
|
|
return (BadWindow);
|
|
}
|
|
if (pSib->parent != pParent)
|
|
return (BadMatch);
|
|
if (pSib == pWin)
|
|
return (BadMatch);
|
|
break;
|
|
case CWStackMode:
|
|
GET_CARD8(CWStackMode, smode);
|
|
if ((smode != TopIf) && (smode != BottomIf) &&
|
|
(smode != Opposite) && (smode != Above) && (smode != Below)) {
|
|
client->errorValue = smode;
|
|
return (BadValue);
|
|
}
|
|
break;
|
|
default:
|
|
client->errorValue = mask;
|
|
return (BadValue);
|
|
}
|
|
}
|
|
/* root really can't be reconfigured, so just return */
|
|
if (!pParent)
|
|
return Success;
|
|
|
|
/* 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, pParent->drawable.x + x,
|
|
pParent->drawable.y + y,
|
|
w + (bw << 1), h + (bw << 1), smode);
|
|
else
|
|
pSib = pWin->nextSib;
|
|
|
|
|
|
if ((!pWin->overrideRedirect) && (RedirectSend(pParent)
|
|
)) {
|
|
event.u.u.type = ConfigureRequest;
|
|
event.u.configureRequest.window = pWin->drawable.id;
|
|
if (mask & CWSibling)
|
|
event.u.configureRequest.sibling = sibwid;
|
|
else
|
|
event.u.configureRequest.sibling = None;
|
|
if (mask & CWStackMode)
|
|
event.u.u.detail = smode;
|
|
else
|
|
event.u.u.detail = Above;
|
|
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;
|
|
event.u.configureRequest.valueMask = mask;
|
|
event.u.configureRequest.parent = pParent->drawable.id;
|
|
if (MaybeDeliverEventsToClient(pParent, &event, 1,
|
|
SubstructureRedirectMask, client) == 1)
|
|
return (Success);
|
|
}
|
|
if (action == RESIZE_WIN) {
|
|
Bool size_change = (w != pWin->drawable.width)
|
|
|| (h != pWin->drawable.height);
|
|
|
|
if (size_change &&
|
|
((pWin->eventMask | wOtherEventMasks(pWin)) & ResizeRedirectMask)) {
|
|
xEvent eventT;
|
|
|
|
eventT.u.u.type = ResizeRequest;
|
|
eventT.u.resizeRequest.window = pWin->drawable.id;
|
|
eventT.u.resizeRequest.width = w;
|
|
eventT.u.resizeRequest.height = h;
|
|
if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
|
|
ResizeRedirectMask, client) == 1) {
|
|
/* if event is delivered, leave the actual size alone. */
|
|
w = pWin->drawable.width;
|
|
h = pWin->drawable.height;
|
|
size_change = FALSE;
|
|
}
|
|
}
|
|
if (!size_change) {
|
|
if (mask & (CWX | CWY))
|
|
action = MOVE_WIN;
|
|
else if (mask & (CWStackMode | CWBorderWidth))
|
|
action = RESTACK_WIN;
|
|
else /* really nothing to do */
|
|
return (Success);
|
|
}
|
|
}
|
|
|
|
if (action == RESIZE_WIN)
|
|
/* we've already checked whether there's really a size change */
|
|
goto ActuallyDoSomething;
|
|
if ((mask & CWX) && (x != beforeX))
|
|
goto ActuallyDoSomething;
|
|
if ((mask & CWY) && (y != beforeY))
|
|
goto ActuallyDoSomething;
|
|
if ((mask & CWBorderWidth) && (bw != wBorderWidth(pWin)))
|
|
goto ActuallyDoSomething;
|
|
if (mask & CWStackMode) {
|
|
/* See above for why we always reorder in rootless mode. */
|
|
if (pWin->nextSib != pSib)
|
|
goto ActuallyDoSomething;
|
|
}
|
|
return (Success);
|
|
|
|
ActuallyDoSomething:
|
|
if (SubStrSend(pWin, pParent)) {
|
|
event.u.u.type = ConfigureNotify;
|
|
event.u.configureNotify.window = pWin->drawable.id;
|
|
if (pSib)
|
|
event.u.configureNotify.aboveSibling = pSib->drawable.id;
|
|
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 == RESTACK_WIN) {
|
|
action = MOVE_WIN;
|
|
pWin->borderWidth = bw;
|
|
}
|
|
else if ((action == MOVE_WIN) &&
|
|
(beforeX + wBorderWidth(pWin) == x + (int) bw) &&
|
|
(beforeY + wBorderWidth(pWin) == y + (int) bw)) {
|
|
action = REBORDER_WIN;
|
|
(*pWin->drawable.pScreen->ChangeBorderWidth) (pWin, bw);
|
|
}
|
|
else
|
|
pWin->borderWidth = bw;
|
|
}
|
|
if (action == MOVE_WIN)
|
|
(*pWin->drawable.pScreen->MoveWindow) (pWin, x, y, pSib,
|
|
(mask & CWBorderWidth) ? VTOther
|
|
: VTMove);
|
|
else if (action == RESIZE_WIN)
|
|
(*pWin->drawable.pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
|
|
else if (mask & CWStackMode)
|
|
ReflectStackChange(pWin, pSib, VTOther);
|
|
|
|
if (action != RESTACK_WIN)
|
|
CheckCursorConfinement(pWin);
|
|
return (Success);
|
|
#undef RESTACK_WIN
|
|
#undef MOVE_WIN
|
|
#undef RESIZE_WIN
|
|
#undef REBORDER_WIN
|
|
}
|
|
|
|
/******
|
|
*
|
|
* 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
|
|
*
|
|
******/
|
|
|
|
int
|
|
CirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
|
|
{
|
|
WindowPtr pWin, pHead, pFirst;
|
|
|
|
xEvent event;
|
|
|
|
BoxRec box;
|
|
|
|
pHead = RealChildHead(pParent);
|
|
pFirst = pHead ? pHead->nextSib : pParent->firstChild;
|
|
if (direction == RaiseLowest) {
|
|
for (pWin = pParent->lastChild;
|
|
(pWin != pHead) &&
|
|
!(pWin->mapped &&
|
|
AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
|
|
pWin = pWin->prevSib);
|
|
if (pWin == pHead)
|
|
return Success;
|
|
}
|
|
else {
|
|
for (pWin = pFirst;
|
|
pWin &&
|
|
!(pWin->mapped &&
|
|
IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
|
|
pWin = pWin->nextSib);
|
|
if (!pWin)
|
|
return Success;
|
|
}
|
|
|
|
event.u.circulate.window = pWin->drawable.id;
|
|
event.u.circulate.parent = pParent->drawable.id;
|
|
event.u.circulate.event = pParent->drawable.id;
|
|
if (direction == RaiseLowest)
|
|
event.u.circulate.place = PlaceOnTop;
|
|
else
|
|
event.u.circulate.place = PlaceOnBottom;
|
|
|
|
if (RedirectSend(pParent)) {
|
|
event.u.u.type = CirculateRequest;
|
|
if (MaybeDeliverEventsToClient(pParent, &event, 1,
|
|
SubstructureRedirectMask, client) == 1)
|
|
return (Success);
|
|
}
|
|
|
|
event.u.u.type = CirculateNotify;
|
|
DeliverEvents(pWin, &event, 1, NullWindow);
|
|
ReflectStackChange(pWin,
|
|
(direction == RaiseLowest) ? pFirst : NullWindow,
|
|
VTStack);
|
|
|
|
return (Success);
|
|
}
|
|
|
|
static int
|
|
CompareWIDs(WindowPtr pWin, pointer value)
|
|
{ /* must conform to VisitWindowProcPtr */
|
|
Window *wid = (Window *) value;
|
|
|
|
if (pWin->drawable.id == *wid)
|
|
return (WT_STOPWALKING);
|
|
else
|
|
return (WT_WALKCHILDREN);
|
|
}
|
|
|
|
/*****
|
|
* ReparentWindow
|
|
*****/
|
|
|
|
int
|
|
ReparentWindow(register WindowPtr pWin, register WindowPtr pParent,
|
|
int x, int y, ClientPtr client)
|
|
{
|
|
WindowPtr pPrev, pPriorParent;
|
|
|
|
Bool WasMapped = (Bool) (pWin->mapped);
|
|
|
|
xEvent event;
|
|
|
|
int bw = wBorderWidth(pWin);
|
|
|
|
ScreenPtr pScreen;
|
|
|
|
pScreen = pWin->drawable.pScreen;
|
|
if (TraverseTree(pWin, CompareWIDs, (pointer) &pParent->drawable.id) ==
|
|
WT_STOPWALKING)
|
|
return (BadMatch);
|
|
if (!MakeWindowOptional(pWin))
|
|
return (BadAlloc);
|
|
|
|
if (WasMapped)
|
|
UnmapWindow(pWin, FALSE);
|
|
|
|
event.u.u.type = ReparentNotify;
|
|
event.u.reparent.window = pWin->drawable.id;
|
|
event.u.reparent.parent = pParent->drawable.id;
|
|
event.u.reparent.x = x;
|
|
event.u.reparent.y = y;
|
|
event.u.reparent.override = pWin->overrideRedirect;
|
|
DeliverEvents(pWin, &event, 1, pParent);
|
|
|
|
/* take out of sibling chain */
|
|
|
|
pPriorParent = 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;
|
|
pPrev = RealChildHead(pParent);
|
|
if (pPrev) {
|
|
pWin->nextSib = pPrev->nextSib;
|
|
if (pPrev->nextSib)
|
|
pPrev->nextSib->prevSib = pWin;
|
|
else
|
|
pParent->lastChild = pWin;
|
|
pPrev->nextSib = pWin;
|
|
pWin->prevSib = pPrev;
|
|
}
|
|
else {
|
|
pWin->nextSib = pParent->firstChild;
|
|
pWin->prevSib = NullWindow;
|
|
if (pParent->firstChild)
|
|
pParent->firstChild->prevSib = pWin;
|
|
else
|
|
pParent->lastChild = pWin;
|
|
pParent->firstChild = pWin;
|
|
}
|
|
|
|
pWin->origin.x = x + bw;
|
|
pWin->origin.y = y + bw;
|
|
pWin->drawable.x = x + bw + pParent->drawable.x;
|
|
pWin->drawable.y = y + bw + pParent->drawable.y;
|
|
|
|
/* clip to parent */
|
|
SetWinSize(pWin);
|
|
SetBorderSize(pWin);
|
|
|
|
if (pScreen->ReparentWindow)
|
|
(*pScreen->ReparentWindow) (pWin, pPriorParent);
|
|
(*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
|
|
ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
|
|
|
|
CheckWindowOptionalNeed(pWin);
|
|
|
|
if (WasMapped)
|
|
MapWindow(pWin, client);
|
|
RecalculateDeliverableEvents(pWin);
|
|
return (Success);
|
|
}
|
|
|
|
static void
|
|
RealizeTree(WindowPtr pWin)
|
|
{
|
|
WindowPtr pChild;
|
|
|
|
RealizeWindowProcPtr Realize;
|
|
|
|
Realize = pWin->drawable.pScreen->RealizeWindow;
|
|
pChild = pWin;
|
|
while (1) {
|
|
if (pChild->mapped) {
|
|
pChild->realized = TRUE;
|
|
pChild->viewable = (pChild->drawable.class == InputOutput);
|
|
(*Realize) (pChild);
|
|
if (pChild->firstChild) {
|
|
pChild = pChild->firstChild;
|
|
continue;
|
|
}
|
|
}
|
|
while (!pChild->nextSib && (pChild != pWin))
|
|
pChild = pChild->parent;
|
|
if (pChild == pWin)
|
|
return;
|
|
pChild = pChild->nextSib;
|
|
}
|
|
}
|
|
|
|
/*****
|
|
* 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.
|
|
*****/
|
|
|
|
_X_EXPORT int
|
|
MapWindow(register WindowPtr pWin, ClientPtr client)
|
|
{
|
|
ScreenPtr pScreen;
|
|
|
|
WindowPtr pParent;
|
|
|
|
WindowPtr pLayerWin;
|
|
|
|
if (pWin->mapped)
|
|
return (Success);
|
|
|
|
|
|
pScreen = pWin->drawable.pScreen;
|
|
if ((pParent = pWin->parent)) {
|
|
xEvent event;
|
|
|
|
Bool anyMarked;
|
|
|
|
|
|
if ((!pWin->overrideRedirect) && (RedirectSend(pParent)
|
|
)) {
|
|
event.u.u.type = MapRequest;
|
|
event.u.mapRequest.window = pWin->drawable.id;
|
|
event.u.mapRequest.parent = pParent->drawable.id;
|
|
|
|
if (MaybeDeliverEventsToClient(pParent, &event, 1,
|
|
SubstructureRedirectMask,
|
|
client) == 1)
|
|
return (Success);
|
|
}
|
|
|
|
pWin->mapped = TRUE;
|
|
if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin)) {
|
|
event.u.u.type = MapNotify;
|
|
event.u.mapNotify.window = pWin->drawable.id;
|
|
event.u.mapNotify.override = pWin->overrideRedirect;
|
|
DeliverEvents(pWin, &event, 1, NullWindow);
|
|
}
|
|
|
|
if (!pParent->realized)
|
|
return (Success);
|
|
RealizeTree(pWin);
|
|
if (pWin->viewable) {
|
|
anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
|
|
&pLayerWin);
|
|
if (anyMarked) {
|
|
(*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTMap);
|
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
|
}
|
|
if (anyMarked && pScreen->PostValidateTree)
|
|
(*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin,
|
|
VTMap);
|
|
}
|
|
WindowsRestructured();
|
|
}
|
|
else {
|
|
RegionRec temp;
|
|
|
|
pWin->mapped = TRUE;
|
|
pWin->realized = TRUE; /* for roots */
|
|
pWin->viewable = pWin->drawable.class == InputOutput;
|
|
/* We SHOULD check for an error value here XXX */
|
|
(*pScreen->RealizeWindow) (pWin);
|
|
if (pScreen->ClipNotify)
|
|
(*pScreen->ClipNotify) (pWin, 0, 0);
|
|
if (pScreen->PostValidateTree)
|
|
(*pScreen->PostValidateTree) (NullWindow, pWin, VTMap);
|
|
REGION_NULL(&temp);
|
|
REGION_COPY(&temp, &pWin->clipList);
|
|
(*pScreen->WindowExposures) (pWin, &temp, NullRegion);
|
|
REGION_UNINIT(&temp);
|
|
}
|
|
|
|
return (Success);
|
|
}
|
|
|
|
/*****
|
|
* MapSubwindows
|
|
* Performs a MapWindow all unmapped children of the window, in top
|
|
* to bottom stacking order.
|
|
*****/
|
|
|
|
void
|
|
MapSubwindows(register WindowPtr pParent, ClientPtr client)
|
|
{
|
|
WindowPtr pWin;
|
|
|
|
WindowPtr pFirstMapped = NullWindow;
|
|
|
|
ScreenPtr pScreen;
|
|
|
|
Mask parentRedirect;
|
|
|
|
Mask parentNotify;
|
|
|
|
xEvent event;
|
|
|
|
Bool anyMarked;
|
|
|
|
WindowPtr pLayerWin;
|
|
|
|
pScreen = pParent->drawable.pScreen;
|
|
parentRedirect = RedirectSend(pParent);
|
|
parentNotify = SubSend(pParent);
|
|
anyMarked = FALSE;
|
|
for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) {
|
|
if (!pWin->mapped) {
|
|
if (parentRedirect && !pWin->overrideRedirect) {
|
|
event.u.u.type = MapRequest;
|
|
event.u.mapRequest.window = pWin->drawable.id;
|
|
event.u.mapRequest.parent = pParent->drawable.id;
|
|
|
|
if (MaybeDeliverEventsToClient(pParent, &event, 1,
|
|
SubstructureRedirectMask,
|
|
client) == 1)
|
|
continue;
|
|
}
|
|
|
|
pWin->mapped = TRUE;
|
|
if (parentNotify || StrSend(pWin)) {
|
|
event.u.u.type = MapNotify;
|
|
event.u.mapNotify.window = pWin->drawable.id;
|
|
event.u.mapNotify.override = pWin->overrideRedirect;
|
|
DeliverEvents(pWin, &event, 1, NullWindow);
|
|
}
|
|
|
|
if (!pFirstMapped)
|
|
pFirstMapped = pWin;
|
|
if (pParent->realized) {
|
|
RealizeTree(pWin);
|
|
if (pWin->viewable) {
|
|
anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin,
|
|
(WindowPtr
|
|
*) NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pFirstMapped) {
|
|
pLayerWin = (*pScreen->GetLayerWindow) (pParent);
|
|
if (pLayerWin->parent != pParent) {
|
|
anyMarked |= (*pScreen->MarkOverlappedWindows) (pLayerWin,
|
|
pLayerWin,
|
|
(WindowPtr *) NULL);
|
|
pFirstMapped = pLayerWin;
|
|
}
|
|
if (anyMarked) {
|
|
(*pScreen->ValidateTree) (pLayerWin->parent, pFirstMapped, VTMap);
|
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
|
}
|
|
if (anyMarked && pScreen->PostValidateTree)
|
|
(*pScreen->PostValidateTree) (pLayerWin->parent, pFirstMapped,
|
|
VTMap);
|
|
WindowsRestructured();
|
|
}
|
|
}
|
|
|
|
static void
|
|
UnrealizeTree(WindowPtr pWin, Bool fromConfigure)
|
|
{
|
|
WindowPtr pChild;
|
|
|
|
UnrealizeWindowProcPtr Unrealize;
|
|
|
|
MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
|
|
|
|
Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
|
|
MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow;
|
|
pChild = pWin;
|
|
while (1) {
|
|
if (pChild->realized) {
|
|
pChild->realized = FALSE;
|
|
pChild->visibility = VisibilityNotViewable;
|
|
(*Unrealize) (pChild);
|
|
DeleteWindowFromAnyEvents(pChild, FALSE);
|
|
if (pChild->viewable) {
|
|
pChild->viewable = FALSE;
|
|
(*MarkUnrealizedWindow) (pChild, pWin, fromConfigure);
|
|
pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
|
}
|
|
if (pChild->firstChild) {
|
|
pChild = pChild->firstChild;
|
|
continue;
|
|
}
|
|
}
|
|
while (!pChild->nextSib && (pChild != pWin))
|
|
pChild = pChild->parent;
|
|
if (pChild == pWin)
|
|
return;
|
|
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.
|
|
*****/
|
|
|
|
_X_EXPORT int
|
|
UnmapWindow(register WindowPtr pWin, Bool fromConfigure)
|
|
{
|
|
WindowPtr pParent;
|
|
|
|
xEvent event;
|
|
|
|
Bool wasRealized = (Bool) pWin->realized;
|
|
|
|
Bool wasViewable = (Bool) pWin->viewable;
|
|
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
WindowPtr pLayerWin = pWin;
|
|
|
|
if ((!pWin->mapped) || (!(pParent = pWin->parent)))
|
|
return (Success);
|
|
if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin)) {
|
|
event.u.u.type = UnmapNotify;
|
|
event.u.unmapNotify.window = pWin->drawable.id;
|
|
event.u.unmapNotify.fromConfigure = fromConfigure;
|
|
DeliverEvents(pWin, &event, 1, NullWindow);
|
|
}
|
|
if (wasViewable && !fromConfigure) {
|
|
pWin->valdata = UnmapValData;
|
|
(*pScreen->MarkOverlappedWindows) (pWin, pWin->nextSib, &pLayerWin);
|
|
(*pScreen->MarkWindow) (pLayerWin->parent);
|
|
}
|
|
pWin->mapped = FALSE;
|
|
if (wasRealized)
|
|
UnrealizeTree(pWin, fromConfigure);
|
|
if (wasViewable) {
|
|
if (!fromConfigure) {
|
|
(*pScreen->ValidateTree) (pLayerWin->parent, pWin, VTUnmap);
|
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
|
}
|
|
if (!fromConfigure && pScreen->PostValidateTree)
|
|
(*pScreen->PostValidateTree) (pLayerWin->parent, pWin, VTUnmap);
|
|
}
|
|
if (wasRealized && !fromConfigure)
|
|
WindowsRestructured();
|
|
return (Success);
|
|
}
|
|
|
|
/*****
|
|
* UnmapSubwindows
|
|
* Performs an UnmapWindow request with the specified mode on all mapped
|
|
* children of the window, in bottom to top stacking order.
|
|
*****/
|
|
|
|
void
|
|
UnmapSubwindows(register WindowPtr pWin)
|
|
{
|
|
WindowPtr pChild, pHead;
|
|
|
|
xEvent event;
|
|
|
|
Bool wasRealized = (Bool) pWin->realized;
|
|
|
|
Bool wasViewable = (Bool) pWin->viewable;
|
|
|
|
Bool anyMarked = FALSE;
|
|
|
|
Mask parentNotify;
|
|
|
|
WindowPtr pLayerWin = NULL;
|
|
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
if (!pWin->firstChild)
|
|
return;
|
|
parentNotify = SubSend(pWin);
|
|
pHead = RealChildHead(pWin);
|
|
|
|
if (wasViewable)
|
|
pLayerWin = (*pScreen->GetLayerWindow) (pWin);
|
|
|
|
for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) {
|
|
if (pChild->mapped) {
|
|
if (parentNotify || StrSend(pChild)) {
|
|
event.u.u.type = UnmapNotify;
|
|
event.u.unmapNotify.window = pChild->drawable.id;
|
|
event.u.unmapNotify.fromConfigure = xFalse;
|
|
DeliverEvents(pChild, &event, 1, NullWindow);
|
|
}
|
|
if (pChild->viewable) {
|
|
pChild->valdata = UnmapValData;
|
|
anyMarked = TRUE;
|
|
}
|
|
pChild->mapped = FALSE;
|
|
if (pChild->realized)
|
|
UnrealizeTree(pChild, FALSE);
|
|
if (wasViewable) {
|
|
}
|
|
}
|
|
}
|
|
if (wasViewable) {
|
|
if (anyMarked) {
|
|
if (pLayerWin->parent == pWin)
|
|
(*pScreen->MarkWindow) (pWin);
|
|
else {
|
|
WindowPtr ptmp;
|
|
|
|
(*pScreen->MarkOverlappedWindows) (pWin, pLayerWin,
|
|
(WindowPtr *) NULL);
|
|
(*pScreen->MarkWindow) (pLayerWin->parent);
|
|
|
|
/* Windows between pWin and pLayerWin may not have been marked */
|
|
ptmp = pWin;
|
|
|
|
while (ptmp != pLayerWin->parent) {
|
|
(*pScreen->MarkWindow) (ptmp);
|
|
ptmp = ptmp->parent;
|
|
}
|
|
pHead = pWin->firstChild;
|
|
}
|
|
(*pScreen->ValidateTree) (pLayerWin->parent, pHead, VTUnmap);
|
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
|
}
|
|
if (anyMarked && pScreen->PostValidateTree)
|
|
(*pScreen->PostValidateTree) (pLayerWin->parent, pHead, VTUnmap);
|
|
}
|
|
if (wasRealized)
|
|
WindowsRestructured();
|
|
}
|
|
|
|
void
|
|
HandleSaveSet(register ClientPtr client)
|
|
{
|
|
WindowPtr pParent, pWin;
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < client->numSaved; j++) {
|
|
pWin = SaveSetWindow(client->saveSet[j]);
|
|
if (SaveSetToRoot(client->saveSet[j]))
|
|
pParent = WindowTable[pWin->drawable.pScreen->myNum];
|
|
else
|
|
{
|
|
pParent = pWin->parent;
|
|
while (pParent && (wClient(pParent) == client))
|
|
pParent = pParent->parent;
|
|
}
|
|
if (pParent) {
|
|
if (pParent != pWin->parent) {
|
|
ReparentWindow(pWin, pParent,
|
|
pWin->drawable.x - wBorderWidth(pWin) -
|
|
pParent->drawable.x,
|
|
pWin->drawable.y - wBorderWidth(pWin) -
|
|