First import
[xorg_rtime.git] / xorg-server-1.4 / dix / window.c
blobbe4ea2c97976f450f1a081ef7bd5b50a05f54b22
1 /*
3 Copyright (c) 2006, Red Hat, Inc.
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of Red Hat shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from Red Hat.
25 Copyright 1987, 1998 The Open Group
27 Permission to use, copy, modify, distribute, and sell this software and its
28 documentation for any purpose is hereby granted without fee, provided that
29 the above copyright notice appear in all copies and that both that
30 copyright notice and this permission notice appear in supporting
31 documentation.
33 The above copyright notice and this permission notice shall be included
34 in all copies or substantial portions of the Software.
36 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
37 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
38 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
39 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
40 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
41 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
42 OTHER DEALINGS IN THE SOFTWARE.
44 Except as contained in this notice, the name of The Open Group shall
45 not be used in advertising or otherwise to promote the sale, use or
46 other dealings in this Software without prior written authorization
47 from The Open Group.
50 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
52 All Rights Reserved
54 Permission to use, copy, modify, and distribute this software and its
55 documentation for any purpose and without fee is hereby granted,
56 provided that the above copyright notice appear in all copies and that
57 both that copyright notice and this permission notice appear in
58 supporting documentation, and that the name of Digital not be
59 used in advertising or publicity pertaining to distribution of the
60 software without specific, written prior permission.
62 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
63 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
64 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
65 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
66 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
67 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
68 SOFTWARE.
72 /* The panoramix components contained the following notice */
73 /*****************************************************************
75 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
77 Permission is hereby granted, free of charge, to any person obtaining a copy
78 of this software and associated documentation files (the "Software"), to deal
79 in the Software without restriction, including without limitation the rights
80 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
81 copies of the Software.
83 The above copyright notice and this permission notice shall be included in
84 all copies or substantial portions of the Software.
86 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
87 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
88 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
89 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
90 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
91 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
92 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
94 Except as contained in this notice, the name of Digital Equipment Corporation
95 shall not be used in advertising or otherwise to promote the sale, use or other
96 dealings in this Software without prior written authorization from Digital
97 Equipment Corporation.
99 ******************************************************************/
102 #ifdef HAVE_DIX_CONFIG_H
103 #include <dix-config.h>
104 #endif
106 #include "misc.h"
107 #include "scrnintstr.h"
108 #include "os.h"
109 #include "regionstr.h"
110 #include "validate.h"
111 #include "windowstr.h"
112 #include "input.h"
113 #include "resource.h"
114 #include "colormapst.h"
115 #include "cursorstr.h"
116 #include "dixstruct.h"
117 #include "gcstruct.h"
118 #include "servermd.h"
119 #ifdef PANORAMIX
120 #include "panoramiX.h"
121 #include "panoramiXsrv.h"
122 #endif
123 #include "dixevents.h"
124 #include "globals.h"
126 #ifdef XAPPGROUP
127 #include "appgroup.h"
128 #endif
129 #include "xace.h"
131 /******
132 * Window stuff for server
134 * CreateRootWindow, CreateWindow, ChangeWindowAttributes,
135 * GetWindowAttributes, DeleteWindow, DestroySubWindows,
136 * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
137 * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
139 ******/
141 static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11};
142 static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88};
144 _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF;
146 _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
148 #if 0
149 extern void DeleteWindowFromAnyEvents();
150 extern Mask EventMaskForClient();
151 extern void WindowHasNewCursor();
152 extern void RecalculateDeliverableEvents();
153 #endif
155 static Bool TileScreenSaver(int i, int kind);
158 #define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
159 CWDontPropagate | CWOverrideRedirect | CWCursor )
161 #define BOXES_OVERLAP(b1, b2) \
162 (!( ((b1)->x2 <= (b2)->x1) || \
163 ( ((b1)->x1 >= (b2)->x2)) || \
164 ( ((b1)->y2 <= (b2)->y1)) || \
165 ( ((b1)->y1 >= (b2)->y2)) ) )
167 #define RedirectSend(pWin) \
168 ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask)
170 #define SubSend(pWin) \
171 ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask)
173 #define StrSend(pWin) \
174 ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask)
176 #define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
179 _X_EXPORT int numSaveUndersViewable = 0;
180 _X_EXPORT int deltaSaveUndersViewable = 0;
182 #ifdef DEBUG
183 /******
184 * PrintWindowTree
185 * For debugging only
186 ******/
188 static void
189 PrintChildren(WindowPtr p1, int indent)
191 WindowPtr p2;
192 int i;
194 while (p1)
196 p2 = p1->firstChild;
197 for (i=0; i<indent; i++) ErrorF( " ");
198 ErrorF( "%lx\n", p1->drawable.id);
199 miPrintRegion(&p1->clipList);
200 PrintChildren(p2, indent+4);
201 p1 = p1->nextSib;
205 static void
206 PrintWindowTree(void)
208 int i;
209 WindowPtr pWin, p1;
211 for (i=0; i<screenInfo.numScreens; i++)
213 ErrorF( "WINDOW %d\n", i);
214 pWin = WindowTable[i];
215 miPrintRegion(&pWin->clipList);
216 p1 = pWin->firstChild;
217 PrintChildren(p1, 4);
220 #endif
222 _X_EXPORT int
223 TraverseTree(WindowPtr pWin, VisitWindowProcPtr func, pointer data)
225 int result;
226 WindowPtr pChild;
228 if (!(pChild = pWin))
229 return(WT_NOMATCH);
230 while (1)
232 result = (* func)(pChild, data);
233 if (result == WT_STOPWALKING)
234 return(WT_STOPWALKING);
235 if ((result == WT_WALKCHILDREN) && pChild->firstChild)
237 pChild = pChild->firstChild;
238 continue;
240 while (!pChild->nextSib && (pChild != pWin))
241 pChild = pChild->parent;
242 if (pChild == pWin)
243 break;
244 pChild = pChild->nextSib;
246 return(WT_NOMATCH);
249 /*****
250 * WalkTree
251 * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on
252 * each window. If FUNC returns WT_WALKCHILDREN, traverse the children,
253 * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING
254 * exit WalkTree. Does depth-first traverse.
255 *****/
257 _X_EXPORT int
258 WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data)
260 return(TraverseTree(WindowTable[pScreen->myNum], func, data));
263 /* hack for forcing backing store on all windows */
264 int defaultBackingStore = NotUseful;
265 /* hack to force no backing store */
266 Bool disableBackingStore = FALSE;
267 Bool enableBackingStore = FALSE;
268 /* hack to force no save unders */
269 Bool disableSaveUnders = FALSE;
271 static void
272 SetWindowToDefaults(WindowPtr pWin)
274 pWin->prevSib = NullWindow;
275 pWin->firstChild = NullWindow;
276 pWin->lastChild = NullWindow;
278 pWin->valdata = (ValidatePtr)NULL;
279 pWin->optional = (WindowOptPtr)NULL;
280 pWin->cursorIsNone = TRUE;
282 pWin->backingStore = NotUseful;
283 pWin->DIXsaveUnder = FALSE;
284 pWin->backStorage = (pointer) NULL;
286 pWin->mapped = FALSE; /* off */
287 pWin->realized = FALSE; /* off */
288 pWin->viewable = FALSE;
289 pWin->visibility = VisibilityNotViewable;
290 pWin->overrideRedirect = FALSE;
291 pWin->saveUnder = FALSE;
293 pWin->bitGravity = ForgetGravity;
294 pWin->winGravity = NorthWestGravity;
296 pWin->eventMask = 0;
297 pWin->deliverableEvents = 0;
298 pWin->dontPropagate = 0;
299 pWin->forcedBS = FALSE;
300 #ifdef COMPOSITE
301 pWin->redirectDraw = RedirectDrawNone;
302 #endif
305 static void
306 MakeRootTile(WindowPtr pWin)
308 ScreenPtr pScreen = pWin->drawable.pScreen;
309 GCPtr pGC;
310 unsigned char back[128];
311 int len = BitmapBytePad(sizeof(long));
312 unsigned char *from, *to;
313 int i, j;
315 pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4,
316 pScreen->rootDepth);
318 pWin->backgroundState = BackgroundPixmap;
319 pGC = GetScratchGC(pScreen->rootDepth, pScreen);
320 if (!pWin->background.pixmap || !pGC)
321 FatalError("could not create root tile");
324 CARD32 attributes[2];
326 attributes[0] = pScreen->whitePixel;
327 attributes[1] = pScreen->blackPixel;
329 (void)ChangeGC(pGC, GCForeground | GCBackground, attributes);
332 ValidateGC((DrawablePtr)pWin->background.pixmap, pGC);
334 from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
335 to = back;
337 for (i = 4; i > 0; i--, from++)
338 for (j = len; j > 0; j--)
339 *to++ = *from;
341 (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1,
342 0, 0, len, 4, 0, XYBitmap, (char *)back);
344 FreeScratchGC(pGC);
348 WindowPtr
349 AllocateWindow(ScreenPtr pScreen)
351 WindowPtr pWin;
352 char *ptr;
353 DevUnion *ppriv;
354 unsigned *sizes;
355 unsigned size;
356 int i;
358 pWin = (WindowPtr)xalloc(pScreen->totalWindowSize);
359 if (pWin)
361 ppriv = (DevUnion *)(pWin + 1);
362 pWin->devPrivates = ppriv;
363 sizes = pScreen->WindowPrivateSizes;
364 ptr = (char *)(ppriv + pScreen->WindowPrivateLen);
365 for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++)
367 if ( (size = *sizes) )
369 ppriv->ptr = (pointer)ptr;
370 ptr += size;
372 else
373 ppriv->ptr = (pointer)NULL;
375 #if _XSERVER64
376 pWin->drawable.pad0 = 0;
377 pWin->drawable.pad1 = 0;
378 #endif
380 return pWin;
383 /*****
384 * CreateRootWindow
385 * Makes a window at initialization time for specified screen
386 *****/
388 Bool
389 CreateRootWindow(ScreenPtr pScreen)
391 WindowPtr pWin;
392 BoxRec box;
393 PixmapFormatRec *format;
395 pWin = AllocateWindow(pScreen);
396 if (!pWin)
397 return FALSE;
399 savedScreenInfo[pScreen->myNum].pWindow = NULL;
400 savedScreenInfo[pScreen->myNum].wid = FakeClientID(0);
401 savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL;
402 screenIsSaved = SCREEN_SAVER_OFF;
404 WindowTable[pScreen->myNum] = pWin;
406 pWin->drawable.pScreen = pScreen;
407 pWin->drawable.type = DRAWABLE_WINDOW;
409 pWin->drawable.depth = pScreen->rootDepth;
410 for (format = screenInfo.formats;
411 format->depth != pScreen->rootDepth;
412 format++)
414 pWin->drawable.bitsPerPixel = format->bitsPerPixel;
416 pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
418 pWin->parent = NullWindow;
419 SetWindowToDefaults(pWin);
421 pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec));
422 if (!pWin->optional)
423 return FALSE;
425 pWin->optional->dontPropagateMask = 0;
426 pWin->optional->otherEventMasks = 0;
427 pWin->optional->otherClients = NULL;
428 pWin->optional->passiveGrabs = NULL;
429 pWin->optional->userProps = NULL;
430 pWin->optional->backingBitPlanes = ~0L;
431 pWin->optional->backingPixel = 0;
432 #ifdef SHAPE
433 pWin->optional->boundingShape = NULL;
434 pWin->optional->clipShape = NULL;
435 pWin->optional->inputShape = NULL;
436 #endif
437 #ifdef XINPUT
438 pWin->optional->inputMasks = NULL;
439 #endif
440 pWin->optional->colormap = pScreen->defColormap;
441 pWin->optional->visual = pScreen->rootVisual;
443 pWin->nextSib = NullWindow;
445 pWin->drawable.id = FakeClientID(0);
447 pWin->origin.x = pWin->origin.y = 0;
448 pWin->drawable.height = pScreen->height;
449 pWin->drawable.width = pScreen->width;
450 pWin->drawable.x = pWin->drawable.y = 0;
452 box.x1 = 0;
453 box.y1 = 0;
454 box.x2 = pScreen->width;
455 box.y2 = pScreen->height;
456 REGION_INIT(pScreen, &pWin->clipList, &box, 1);
457 REGION_INIT(pScreen, &pWin->winSize, &box, 1);
458 REGION_INIT(pScreen, &pWin->borderSize, &box, 1);
459 REGION_INIT(pScreen, &pWin->borderClip, &box, 1);
461 pWin->drawable.class = InputOutput;
462 pWin->optional->visual = pScreen->rootVisual;
464 pWin->backgroundState = BackgroundPixel;
465 pWin->background.pixel = pScreen->whitePixel;
467 pWin->borderIsPixel = TRUE;
468 pWin->border.pixel = pScreen->blackPixel;
469 pWin->borderWidth = 0;
471 if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin))
472 return FALSE;
474 if (disableBackingStore)
475 pScreen->backingStoreSupport = NotUseful;
476 if (enableBackingStore)
477 pScreen->backingStoreSupport = Always;
479 #ifdef DO_SAVE_UNDERS
480 if ((pScreen->backingStoreSupport != NotUseful) &&
481 (pScreen->saveUnderSupport == NotUseful))
484 * If the screen has backing-store but no save-unders, let the
485 * clients know we can support save-unders using backing-store.
487 pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS;
489 #endif /* DO_SAVE_UNDERS */
491 if (disableSaveUnders)
492 pScreen->saveUnderSupport = NotUseful;
494 return TRUE;
497 void
498 InitRootWindow(WindowPtr pWin)
500 ScreenPtr pScreen = pWin->drawable.pScreen;
501 int backFlag = CWBorderPixel | CWCursor | CWBackingStore;
503 if (!(*pScreen->CreateWindow)(pWin))
504 return; /* XXX */
505 (*pScreen->PositionWindow)(pWin, 0, 0);
507 pWin->cursorIsNone = FALSE;
508 pWin->optional->cursor = rootCursor;
509 rootCursor->refcnt++;
511 if (!blackRoot && !whiteRoot) {
512 MakeRootTile(pWin);
513 backFlag |= CWBackPixmap;
515 else {
516 if (blackRoot)
517 pWin->background.pixel = pScreen->blackPixel;
518 else
519 pWin->background.pixel = pScreen->whitePixel;
520 backFlag |= CWBackPixel;
523 pWin->backingStore = defaultBackingStore;
524 pWin->forcedBS = (defaultBackingStore != NotUseful);
525 /* We SHOULD check for an error value here XXX */
526 (*pScreen->ChangeWindowAttributes)(pWin, backFlag);
528 XaceHook(XACE_WINDOW_INIT, serverClient, pWin);
530 MapWindow(pWin, serverClient);
533 /* Set the region to the intersection of the rectangle and the
534 * window's winSize. The window is typically the parent of the
535 * window from which the region came.
538 static void
539 ClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn,
540 int x, int y,
541 int w, int h)
543 ScreenPtr pScreen;
544 BoxRec box;
546 pScreen = pWin->drawable.pScreen;
548 box = *(REGION_EXTENTS(pScreen, &pWin->winSize));
549 /* we do these calculations to avoid overflows */
550 if (x > box.x1)
551 box.x1 = x;
552 if (y > box.y1)
553 box.y1 = y;
554 x += w;
555 if (x < box.x2)
556 box.x2 = x;
557 y += h;
558 if (y < box.y2)
559 box.y2 = y;
560 if (box.x1 > box.x2)
561 box.x2 = box.x1;
562 if (box.y1 > box.y2)
563 box.y2 = box.y1;
564 REGION_RESET(pScreen, Rgn, &box);
565 REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize);
568 static RealChildHeadProc realChildHeadProc = NULL;
570 void
571 RegisterRealChildHeadProc (RealChildHeadProc proc)
573 realChildHeadProc = proc;
577 WindowPtr
578 RealChildHead(WindowPtr pWin)
580 if (realChildHeadProc) {
581 return realChildHeadProc (pWin);
584 if (!pWin->parent &&
585 (screenIsSaved == SCREEN_SAVER_ON) &&
586 (HasSaverWindow (pWin->drawable.pScreen->myNum)))
587 return (pWin->firstChild);
588 else
589 return (NullWindow);
592 /*****
593 * CreateWindow
594 * Makes a window in response to client request
595 *****/
597 _X_EXPORT WindowPtr
598 CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
599 unsigned h, unsigned bw, unsigned class, Mask vmask, XID *vlist,
600 int depth, ClientPtr client, VisualID visual, int *error)
602 WindowPtr pWin;
603 WindowPtr pHead;
604 ScreenPtr pScreen;
605 xEvent event;
606 int idepth, ivisual;
607 Bool fOK;
608 DepthPtr pDepth;
609 PixmapFormatRec *format;
610 WindowOptPtr ancwopt;
612 if (class == CopyFromParent)
613 class = pParent->drawable.class;
615 if ((class != InputOutput) && (class != InputOnly))
617 *error = BadValue;
618 client->errorValue = class;
619 return NullWindow;
622 if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
624 *error = BadMatch;
625 return NullWindow;
628 if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
630 *error = BadMatch;
631 return NullWindow;
634 pScreen = pParent->drawable.pScreen;
635 if ((class == InputOutput) && (depth == 0))
636 depth = pParent->drawable.depth;
637 ancwopt = pParent->optional;
638 if (!ancwopt)
639 ancwopt = FindWindowWithOptional(pParent)->optional;
640 if (visual == CopyFromParent) {
641 #ifdef XAPPGROUP
642 VisualID ag_visual;
644 if (client->appgroup && !pParent->parent &&
645 (ag_visual = XagRootVisual (client)))
646 visual = ag_visual;
647 else
648 #endif
649 visual = ancwopt->visual;
652 /* Find out if the depth and visual are acceptable for this Screen */
653 if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
655 fOK = FALSE;
656 for(idepth = 0; idepth < pScreen->numDepths; idepth++)
658 pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
659 if ((depth == pDepth->depth) || (depth == 0))
661 for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
663 if (visual == pDepth->vids[ivisual])
665 fOK = TRUE;
666 break;
671 if (fOK == FALSE)
673 *error = BadMatch;
674 return NullWindow;
678 if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
679 (class != InputOnly) &&
680 (depth != pParent->drawable.depth))
682 *error = BadMatch;
683 return NullWindow;
686 if (((vmask & CWColormap) == 0) &&
687 (class != InputOnly) &&
688 ((visual != ancwopt->visual) || (ancwopt->colormap == None)))
690 *error = BadMatch;
691 return NullWindow;
694 pWin = AllocateWindow(pScreen);
695 if (!pWin)
697 *error = BadAlloc;
698 return NullWindow;
700 pWin->drawable = pParent->drawable;
701 pWin->drawable.depth = depth;
702 if (depth == pParent->drawable.depth)
703 pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
704 else
706 for (format = screenInfo.formats; format->depth != depth; format++)
708 pWin->drawable.bitsPerPixel = format->bitsPerPixel;
710 if (class == InputOnly)
711 pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
712 pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
714 pWin->drawable.id = wid;
715 pWin->drawable.class = class;
717 pWin->parent = pParent;
718 SetWindowToDefaults(pWin);
720 if (visual != ancwopt->visual)
722 if (!MakeWindowOptional (pWin))
724 xfree (pWin);
725 *error = BadAlloc;
726 return NullWindow;
728 pWin->optional->visual = visual;
729 pWin->optional->colormap = None;
732 pWin->borderWidth = bw;
734 /* can't let untrusted clients have background None windows;
735 * they make it too easy to steal window contents
737 if (XaceHook(XACE_BACKGRND_ACCESS, client, pWin))
738 pWin->backgroundState = None;
739 else {
740 pWin->backgroundState = BackgroundPixel;
741 pWin->background.pixel = 0;
744 pWin->borderIsPixel = pParent->borderIsPixel;
745 pWin->border = pParent->border;
746 if (pWin->borderIsPixel == FALSE)
747 pWin->border.pixmap->refcnt++;
749 pWin->origin.x = x + (int)bw;
750 pWin->origin.y = y + (int)bw;
751 pWin->drawable.width = w;
752 pWin->drawable.height = h;
753 pWin->drawable.x = pParent->drawable.x + x + (int)bw;
754 pWin->drawable.y = pParent->drawable.y + y + (int)bw;
756 /* set up clip list correctly for unobscured WindowPtr */
757 REGION_NULL(pScreen, &pWin->clipList);
758 REGION_NULL(pScreen, &pWin->borderClip);
759 REGION_NULL(pScreen, &pWin->winSize);
760 REGION_NULL(pScreen, &pWin->borderSize);
762 XaceHook(XACE_WINDOW_INIT, client, pWin);
764 pHead = RealChildHead(pParent);
765 if (pHead)
767 pWin->nextSib = pHead->nextSib;
768 if (pHead->nextSib)
769 pHead->nextSib->prevSib = pWin;
770 else
771 pParent->lastChild = pWin;
772 pHead->nextSib = pWin;
773 pWin->prevSib = pHead;
775 else
777 pWin->nextSib = pParent->firstChild;
778 if (pParent->firstChild)
779 pParent->firstChild->prevSib = pWin;
780 else
781 pParent->lastChild = pWin;
782 pParent->firstChild = pWin;
785 SetWinSize (pWin);
786 SetBorderSize (pWin);
788 /* We SHOULD check for an error value here XXX */
789 if (!(*pScreen->CreateWindow)(pWin))
791 *error = BadAlloc;
792 DeleteWindow(pWin, None);
793 return NullWindow;
795 /* We SHOULD check for an error value here XXX */
796 (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
798 if (!(vmask & CWEventMask))
799 RecalculateDeliverableEvents(pWin);
801 if (vmask)
802 *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin));
803 else
804 *error = Success;
806 if (*error != Success)
808 DeleteWindow(pWin, None);
809 return NullWindow;
811 if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful))
813 XID value = defaultBackingStore;
814 (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin));
815 pWin->forcedBS = TRUE;
818 if (SubSend(pParent))
820 event.u.u.type = CreateNotify;
821 event.u.createNotify.window = wid;
822 event.u.createNotify.parent = pParent->drawable.id;
823 event.u.createNotify.x = x;
824 event.u.createNotify.y = y;
825 event.u.createNotify.width = w;
826 event.u.createNotify.height = h;
827 event.u.createNotify.borderWidth = bw;
828 event.u.createNotify.override = pWin->overrideRedirect;
829 DeliverEvents(pParent, &event, 1, NullWindow);
831 return pWin;
834 static void
835 DisposeWindowOptional (WindowPtr pWin)
837 if (!pWin->optional)
838 return;
840 * everything is peachy. Delete the optional record
841 * and clean up
843 if (pWin->optional->cursor)
845 FreeCursor (pWin->optional->cursor, (Cursor)0);
846 pWin->cursorIsNone = FALSE;
848 else
849 pWin->cursorIsNone = TRUE;
850 xfree (pWin->optional);
851 pWin->optional = NULL;
854 static void
855 FreeWindowResources(WindowPtr pWin)
857 ScreenPtr pScreen = pWin->drawable.pScreen;
859 DeleteWindowFromAnySaveSet(pWin);
860 DeleteWindowFromAnySelections(pWin);
861 DeleteWindowFromAnyEvents(pWin, TRUE);
862 REGION_UNINIT(pScreen, &pWin->clipList);
863 REGION_UNINIT(pScreen, &pWin->winSize);
864 REGION_UNINIT(pScreen, &pWin->borderClip);
865 REGION_UNINIT(pScreen, &pWin->borderSize);
866 #ifdef SHAPE
867 if (wBoundingShape (pWin))
868 REGION_DESTROY(pScreen, wBoundingShape (pWin));
869 if (wClipShape (pWin))
870 REGION_DESTROY(pScreen, wClipShape (pWin));
871 if (wInputShape (pWin))
872 REGION_DESTROY(pScreen, wInputShape (pWin));
873 #endif
874 if (pWin->borderIsPixel == FALSE)
875 (*pScreen->DestroyPixmap)(pWin->border.pixmap);
876 if (pWin->backgroundState == BackgroundPixmap)
877 (*pScreen->DestroyPixmap)(pWin->background.pixmap);
879 DeleteAllWindowProperties(pWin);
880 /* We SHOULD check for an error value here XXX */
881 (*pScreen->DestroyWindow)(pWin);
882 DisposeWindowOptional (pWin);
885 static void
886 CrushTree(WindowPtr pWin)
888 WindowPtr pChild, pSib, pParent;
889 UnrealizeWindowProcPtr UnrealizeWindow;
890 xEvent event;
892 if (!(pChild = pWin->firstChild))
893 return;
894 UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
895 while (1)
897 if (pChild->firstChild)
899 pChild = pChild->firstChild;
900 continue;
902 while (1)
904 pParent = pChild->parent;
905 if (SubStrSend(pChild, pParent))
907 event.u.u.type = DestroyNotify;
908 event.u.destroyNotify.window = pChild->drawable.id;
909 DeliverEvents(pChild, &event, 1, NullWindow);
911 FreeResource(pChild->drawable.id, RT_WINDOW);
912 pSib = pChild->nextSib;
913 #ifdef DO_SAVE_UNDERS
914 if (pChild->saveUnder && pChild->viewable)
915 deltaSaveUndersViewable--;
916 #endif
917 pChild->viewable = FALSE;
918 if (pChild->realized)
920 pChild->realized = FALSE;
921 (*UnrealizeWindow)(pChild);
923 FreeWindowResources(pChild);
924 xfree(pChild);
925 if ( (pChild = pSib) )
926 break;
927 pChild = pParent;
928 pChild->firstChild = NullWindow;
929 pChild->lastChild = NullWindow;
930 if (pChild == pWin)
931 return;
936 /*****
937 * DeleteWindow
938 * Deletes child of window then window itself
939 * If wid is None, don't send any events
940 *****/
943 DeleteWindow(pointer value, XID wid)
945 WindowPtr pParent;
946 WindowPtr pWin = (WindowPtr)value;
947 xEvent event;
949 UnmapWindow(pWin, FALSE);
951 CrushTree(pWin);
953 pParent = pWin->parent;
954 if (wid && pParent && SubStrSend(pWin, pParent))
956 event.u.u.type = DestroyNotify;
957 event.u.destroyNotify.window = pWin->drawable.id;
958 DeliverEvents(pWin, &event, 1, NullWindow);
961 FreeWindowResources(pWin);
962 if (pParent)
964 if (pParent->firstChild == pWin)
965 pParent->firstChild = pWin->nextSib;
966 if (pParent->lastChild == pWin)
967 pParent->lastChild = pWin->prevSib;
968 if (pWin->nextSib)
969 pWin->nextSib->prevSib = pWin->prevSib;
970 if (pWin->prevSib)
971 pWin->prevSib->nextSib = pWin->nextSib;
973 xfree(pWin);
974 return Success;
977 void
978 DestroySubwindows(WindowPtr pWin, ClientPtr client)
980 /* XXX
981 * The protocol is quite clear that each window should be
982 * destroyed in turn, however, unmapping all of the first
983 * eliminates most of the calls to ValidateTree. So,
984 * this implementation is incorrect in that all of the
985 * UnmapNotifies occur before all of the DestroyNotifies.
986 * If you care, simply delete the call to UnmapSubwindows.
988 UnmapSubwindows(pWin);
989 while (pWin->lastChild)
990 FreeResource(pWin->lastChild->drawable.id, RT_NONE);
993 #define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \
994 ButtonReleaseMask | PointerMotionMask)
996 /*****
997 * ChangeWindowAttributes
999 * The value-mask specifies which attributes are to be changed; the
1000 * value-list contains one value for each one bit in the mask, from least
1001 * to most significant bit in the mask.
1002 *****/
1004 _X_EXPORT int
1005 ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
1007 Mask index2;
1008 XID *pVlist;
1009 PixmapPtr pPixmap;
1010 Pixmap pixID;
1011 CursorPtr pCursor, pOldCursor;
1012 Cursor cursorID;
1013 WindowPtr pChild;
1014 Colormap cmap;
1015 ColormapPtr pCmap;
1016 xEvent xE;
1017 int result;
1018 ScreenPtr pScreen;
1019 Mask vmaskCopy = 0;
1020 Mask tmask;
1021 unsigned int val;
1022 int error;
1023 Bool checkOptional = FALSE;
1024 Bool borderRelative = FALSE;
1025 WindowPtr pLayerWin;
1027 if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK)))
1028 return BadMatch;
1030 error = Success;
1031 pScreen = pWin->drawable.pScreen;
1032 pVlist = vlist;
1033 tmask = vmask;
1034 while (tmask)
1036 index2 = (Mask) lowbit (tmask);
1037 tmask &= ~index2;
1038 switch (index2)
1040 case CWBackPixmap:
1041 pixID = (Pixmap )*pVlist;
1042 pVlist++;
1043 if (pWin->backgroundState == ParentRelative)
1044 borderRelative = TRUE;
1045 if (pixID == None)
1047 /* can't let untrusted clients have background None windows */
1048 if (XaceHook(XACE_BACKGRND_ACCESS, client, pWin)) {
1049 if (pWin->backgroundState == BackgroundPixmap)
1050 (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1051 if (!pWin->parent)
1052 MakeRootTile(pWin);
1053 else
1054 pWin->backgroundState = None;
1055 } else {
1056 /* didn't change the backgrnd to None, so don't tell ddx */
1057 index2 = 0;
1060 else if (pixID == ParentRelative)
1062 if (pWin->parent &&
1063 pWin->drawable.depth != pWin->parent->drawable.depth)
1065 error = BadMatch;
1066 goto PatchUp;
1068 if (pWin->backgroundState == BackgroundPixmap)
1069 (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1070 if (!pWin->parent)
1071 MakeRootTile(pWin);
1072 else
1073 pWin->backgroundState = ParentRelative;
1074 borderRelative = TRUE;
1075 /* Note that the parent's backgroundTile's refcnt is NOT
1076 * incremented. */
1078 else
1080 pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID,
1081 RT_PIXMAP, DixReadAccess);
1082 if (pPixmap != (PixmapPtr) NULL)
1084 if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1085 (pPixmap->drawable.pScreen != pScreen))
1087 error = BadMatch;
1088 goto PatchUp;
1090 if (pWin->backgroundState == BackgroundPixmap)
1091 (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1092 pWin->backgroundState = BackgroundPixmap;
1093 pWin->background.pixmap = pPixmap;
1094 pPixmap->refcnt++;
1096 else
1098 error = BadPixmap;
1099 client->errorValue = pixID;
1100 goto PatchUp;
1103 break;
1104 case CWBackPixel:
1105 if (pWin->backgroundState == ParentRelative)
1106 borderRelative = TRUE;
1107 if (pWin->backgroundState == BackgroundPixmap)
1108 (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1109 pWin->backgroundState = BackgroundPixel;
1110 pWin->background.pixel = (CARD32 ) *pVlist;
1111 /* background pixel overrides background pixmap,
1112 so don't let the ddx layer see both bits */
1113 vmaskCopy &= ~CWBackPixmap;
1114 pVlist++;
1115 break;
1116 case CWBorderPixmap:
1117 pixID = (Pixmap ) *pVlist;
1118 pVlist++;
1119 if (pixID == CopyFromParent)
1121 if (!pWin->parent ||
1122 (pWin->drawable.depth != pWin->parent->drawable.depth))
1124 error = BadMatch;
1125 goto PatchUp;
1127 if (pWin->borderIsPixel == FALSE)
1128 (*pScreen->DestroyPixmap)(pWin->border.pixmap);
1129 pWin->border = pWin->parent->border;
1130 if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE)
1132 index2 = CWBorderPixel;
1134 else
1136 pWin->parent->border.pixmap->refcnt++;
1139 else
1141 pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID,
1142 RT_PIXMAP, DixReadAccess);
1143 if (pPixmap)
1145 if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1146 (pPixmap->drawable.pScreen != pScreen))
1148 error = BadMatch;
1149 goto PatchUp;
1151 if (pWin->borderIsPixel == FALSE)
1152 (*pScreen->DestroyPixmap)(pWin->border.pixmap);
1153 pWin->borderIsPixel = FALSE;
1154 pWin->border.pixmap = pPixmap;
1155 pPixmap->refcnt++;
1157 else
1159 error = BadPixmap;
1160 client->errorValue = pixID;
1161 goto PatchUp;
1164 break;
1165 case CWBorderPixel:
1166 if (pWin->borderIsPixel == FALSE)
1167 (*pScreen->DestroyPixmap)(pWin->border.pixmap);
1168 pWin->borderIsPixel = TRUE;
1169 pWin->border.pixel = (CARD32) *pVlist;
1170 /* border pixel overrides border pixmap,
1171 so don't let the ddx layer see both bits */
1172 vmaskCopy &= ~CWBorderPixmap;
1173 pVlist++;
1174 break;
1175 case CWBitGravity:
1176 val = (CARD8 )*pVlist;
1177 pVlist++;
1178 if (val > StaticGravity)
1180 error = BadValue;
1181 client->errorValue = val;
1182 goto PatchUp;
1184 pWin->bitGravity = val;
1185 break;
1186 case CWWinGravity:
1187 val = (CARD8 )*pVlist;
1188 pVlist++;
1189 if (val > StaticGravity)
1191 error = BadValue;
1192 client->errorValue = val;
1193 goto PatchUp;
1195 pWin->winGravity = val;
1196 break;
1197 case CWBackingStore:
1198 val = (CARD8 )*pVlist;
1199 pVlist++;
1200 if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
1202 error = BadValue;
1203 client->errorValue = val;
1204 goto PatchUp;
1206 pWin->backingStore = val;
1207 pWin->forcedBS = FALSE;
1208 break;
1209 case CWBackingPlanes:
1210 if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) {
1211 if (!pWin->optional && !MakeWindowOptional (pWin))
1213 error = BadAlloc;
1214 goto PatchUp;
1216 pWin->optional->backingBitPlanes = (CARD32) *pVlist;
1217 if ((CARD32)*pVlist == (CARD32)~0L)
1218 checkOptional = TRUE;
1220 pVlist++;
1221 break;
1222 case CWBackingPixel:
1223 if (pWin->optional || (CARD32) *pVlist) {
1224 if (!pWin->optional && !MakeWindowOptional (pWin))
1226 error = BadAlloc;
1227 goto PatchUp;
1229 pWin->optional->backingPixel = (CARD32) *pVlist;
1230 if (!*pVlist)
1231 checkOptional = TRUE;
1233 pVlist++;
1234 break;
1235 case CWSaveUnder:
1236 val = (BOOL) *pVlist;
1237 pVlist++;
1238 if ((val != xTrue) && (val != xFalse))
1240 error = BadValue;
1241 client->errorValue = val;
1242 goto PatchUp;
1244 #ifdef DO_SAVE_UNDERS
1245 if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) &&
1246 DO_SAVE_UNDERS(pWin))
1249 * Re-check all siblings and inferiors for obscurity or
1250 * exposition (hee hee).
1252 if (pWin->saveUnder)
1253 deltaSaveUndersViewable--;
1254 else
1255 deltaSaveUndersViewable++;
1256 pWin->saveUnder = val;
1258 if (pWin->firstChild)
1260 pLayerWin = (*pScreen->GetLayerWindow)(pWin);
1261 if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib))
1262 (*pScreen->PostChangeSaveUnder)(pLayerWin->parent,
1263 pWin->nextSib);
1265 else
1267 if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib))
1268 (*pScreen->PostChangeSaveUnder)(pWin,
1269 pWin->nextSib);
1272 else
1274 /* If we're changing the saveUnder attribute of the root
1275 * window, all we do is set pWin->saveUnder so that
1276 * GetWindowAttributes returns the right value. We don't
1277 * do the "normal" save-under processing (as above).
1278 * Hope that doesn't cause any problems.
1280 pWin->saveUnder = val;
1282 #else
1283 pWin->saveUnder = val;
1284 #endif /* DO_SAVE_UNDERS */
1285 break;
1286 case CWEventMask:
1287 result = EventSelectForWindow(pWin, client, (Mask )*pVlist);
1288 if (result)
1290 error = result;
1291 goto PatchUp;
1293 pVlist++;
1294 break;
1295 case CWDontPropagate:
1296 result = EventSuppressForWindow(pWin, client, (Mask )*pVlist,
1297 &checkOptional);
1298 if (result)
1300 error = result;
1301 goto PatchUp;
1303 pVlist++;
1304 break;
1305 case CWOverrideRedirect:
1306 val = (BOOL ) *pVlist;
1307 pVlist++;
1308 if ((val != xTrue) && (val != xFalse))
1310 error = BadValue;
1311 client->errorValue = val;
1312 goto PatchUp;
1314 pWin->overrideRedirect = val;
1315 break;
1316 case CWColormap:
1317 cmap = (Colormap) *pVlist;
1318 pVlist++;
1319 if (cmap == CopyFromParent)
1321 #ifdef XAPPGROUP
1322 Colormap ag_colormap;
1323 ClientPtr win_owner;
1326 * win_owner == client for CreateWindow, other clients
1327 * can ChangeWindowAttributes
1329 win_owner = clients[CLIENT_ID(pWin->drawable.id)];
1331 if ( win_owner && win_owner->appgroup &&
1332 !pWin->parent->parent &&
1333 (ag_colormap = XagDefaultColormap (win_owner)))
1334 cmap = ag_colormap;
1335 else
1336 #endif
1337 if (pWin->parent &&
1338 (!pWin->optional ||
1339 pWin->optional->visual == wVisual (pWin->parent)))
1341 cmap = wColormap (pWin->parent);
1343 else
1344 cmap = None;
1346 if (cmap == None)
1348 error = BadMatch;
1349 goto PatchUp;
1351 pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap,
1352 RT_COLORMAP, DixReadAccess);
1353 if (!pCmap)
1355 error = BadColor;
1356 client->errorValue = cmap;
1357 goto PatchUp;
1359 if (pCmap->pVisual->vid != wVisual (pWin) ||
1360 pCmap->pScreen != pScreen)
1362 error = BadMatch;
1363 goto PatchUp;
1365 if (cmap != wColormap (pWin))
1367 if (!pWin->optional)
1369 if (!MakeWindowOptional (pWin))
1371 error = BadAlloc;
1372 goto PatchUp;
1375 else if (pWin->parent && cmap == wColormap (pWin->parent))
1376 checkOptional = TRUE;
1379 * propagate the original colormap to any children
1380 * inheriting it
1383 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1385 if (!pChild->optional && !MakeWindowOptional (pChild))
1387 error = BadAlloc;
1388 goto PatchUp;
1392 pWin->optional->colormap = cmap;
1395 * check on any children now matching the new colormap
1398 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1400 if (pChild->optional->colormap == cmap)
1401 CheckWindowOptionalNeed (pChild);
1404 xE.u.u.type = ColormapNotify;
1405 xE.u.colormap.window = pWin->drawable.id;
1406 xE.u.colormap.colormap = cmap;
1407 xE.u.colormap.new = xTrue;
1408 xE.u.colormap.state = IsMapInstalled(cmap, pWin);
1409 DeliverEvents(pWin, &xE, 1, NullWindow);
1411 break;
1412 case CWCursor:
1413 cursorID = (Cursor ) *pVlist;
1414 pVlist++;
1416 * install the new
1418 if ( cursorID == None)
1420 if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
1421 pCursor = rootCursor;
1422 else
1423 pCursor = (CursorPtr) None;
1425 else
1427 pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID,
1428 RT_CURSOR, DixReadAccess);
1429 if (!pCursor)
1431 error = BadCursor;
1432 client->errorValue = cursorID;
1433 goto PatchUp;
1437 if (pCursor != wCursor (pWin))
1440 * patch up child windows so they don't lose cursors.
1443 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1445 if (!pChild->optional && !pChild->cursorIsNone &&
1446 !MakeWindowOptional (pChild))
1448 error = BadAlloc;
1449 goto PatchUp;
1453 pOldCursor = 0;
1454 if (pCursor == (CursorPtr) None)
1456 pWin->cursorIsNone = TRUE;
1457 if (pWin->optional)
1459 pOldCursor = pWin->optional->cursor;
1460 pWin->optional->cursor = (CursorPtr) None;
1461 checkOptional = TRUE;
1463 } else {
1464 if (!pWin->optional)
1466 if (!MakeWindowOptional (pWin))
1468 error = BadAlloc;
1469 goto PatchUp;
1472 else if (pWin->parent && pCursor == wCursor (pWin->parent))
1473 checkOptional = TRUE;
1474 pOldCursor = pWin->optional->cursor;
1475 pWin->optional->cursor = pCursor;
1476 pCursor->refcnt++;
1477 pWin->cursorIsNone = FALSE;
1479 * check on any children now matching the new cursor
1482 for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib)
1484 if (pChild->optional &&
1485 (pChild->optional->cursor == pCursor))
1486 CheckWindowOptionalNeed (pChild);
1490 if (pWin->realized)
1491 WindowHasNewCursor( pWin);
1493 /* Can't free cursor until here - old cursor
1494 * is needed in WindowHasNewCursor
1496 if (pOldCursor)
1497 FreeCursor (pOldCursor, (Cursor)0);
1499 break;
1500 default:
1501 error = BadValue;
1502 client->errorValue = vmask;
1503 goto PatchUp;
1505 vmaskCopy |= index2;
1507 PatchUp:
1508 if (checkOptional)
1509 CheckWindowOptionalNeed (pWin);
1511 /* We SHOULD check for an error value here XXX */
1512 (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy);
1515 If the border contents have changed, redraw the border.
1516 Note that this has to be done AFTER pScreen->ChangeWindowAttributes
1517 for the tile to be rotated, and the correct function selected.
1519 if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative)
1520 && pWin->viewable && HasBorder (pWin))
1522 RegionRec exposed;
1524 REGION_NULL(pScreen, &exposed);
1525 REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize);
1526 (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER);
1527 REGION_UNINIT(pScreen, &exposed);
1529 return error;
1533 /*****
1534 * GetWindowAttributes
1535 * Notice that this is different than ChangeWindowAttributes
1536 *****/
1538 void
1539 GetWindowAttributes(WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply *wa)
1541 wa->type = X_Reply;
1542 wa->bitGravity = pWin->bitGravity;
1543 wa->winGravity = pWin->winGravity;
1544 if (pWin->forcedBS && pWin->backingStore != Always)
1545 wa->backingStore = NotUseful;
1546 else
1547 wa->backingStore = pWin->backingStore;
1548 wa->length = (sizeof(xGetWindowAttributesReply) -
1549 sizeof(xGenericReply)) >> 2;
1550 wa->sequenceNumber = client->sequence;
1551 wa->backingBitPlanes = wBackingBitPlanes (pWin);
1552 wa->backingPixel = wBackingPixel (pWin);
1553 wa->saveUnder = (BOOL)pWin->saveUnder;
1554 wa->override = pWin->overrideRedirect;
1555 if (!pWin->mapped)
1556 wa->mapState = IsUnmapped;
1557 else if (pWin->realized)
1558 wa->mapState = IsViewable;
1559 else
1560 wa->mapState = IsUnviewable;
1562 wa->colormap = wColormap (pWin);
1563 wa->mapInstalled = (wa->colormap == None) ? xFalse
1564 : IsMapInstalled(wa->colormap, pWin);
1566 wa->yourEventMask = EventMaskForClient(pWin, client);
1567 wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin);
1568 wa->doNotPropagateMask = wDontPropagateMask (pWin);
1569 wa->class = pWin->drawable.class;
1570 wa->visualID = wVisual (pWin);
1574 _X_EXPORT WindowPtr
1575 MoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib)
1577 WindowPtr pParent = pWin->parent;
1578 WindowPtr pFirstChange = pWin; /* highest window where list changes */
1580 if (pWin->nextSib != pNextSib)
1582 WindowPtr pOldNextSib = pWin->nextSib;
1584 if (!pNextSib) /* move to bottom */
1586 if (pParent->firstChild == pWin)
1587 pParent->firstChild = pWin->nextSib;
1588 /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL
1589 * and pWin->nextSib != pNextSib
1590 * therefore pWin->nextSib != NULL */
1591 pFirstChange = pWin->nextSib;
1592 pWin->nextSib->prevSib = pWin->prevSib;
1593 if (pWin->prevSib)
1594 pWin->prevSib->nextSib = pWin->nextSib;
1595 pParent->lastChild->nextSib = pWin;
1596 pWin->prevSib = pParent->lastChild;
1597 pWin->nextSib = NullWindow;
1598 pParent->lastChild = pWin;
1600 else if (pParent->firstChild == pNextSib) /* move to top */
1602 pFirstChange = pWin;
1603 if (pParent->lastChild == pWin)
1604 pParent->lastChild = pWin->prevSib;
1605 if (pWin->nextSib)
1606 pWin->nextSib->prevSib = pWin->prevSib;
1607 if (pWin->prevSib)
1608 pWin->prevSib->nextSib = pWin->nextSib;
1609 pWin->nextSib = pParent->firstChild;
1610 pWin->prevSib = (WindowPtr ) NULL;
1611 pNextSib->prevSib = pWin;
1612 pParent->firstChild = pWin;
1614 else /* move in middle of list */
1616 WindowPtr pOldNext = pWin->nextSib;
1618 pFirstChange = NullWindow;
1619 if (pParent->firstChild == pWin)
1620 pFirstChange = pParent->firstChild = pWin->nextSib;
1621 if (pParent->lastChild == pWin) {
1622 pFirstChange = pWin;
1623 pParent->lastChild = pWin->prevSib;
1625 if (pWin->nextSib)
1626 pWin->nextSib->prevSib = pWin->prevSib;
1627 if (pWin->prevSib)
1628 pWin->prevSib->nextSib = pWin->nextSib;
1629 pWin->nextSib = pNextSib;
1630 pWin->prevSib = pNextSib->prevSib;
1631 if (pNextSib->prevSib)
1632 pNextSib->prevSib->nextSib = pWin;
1633 pNextSib->prevSib = pWin;
1634 if (!pFirstChange) { /* do we know it yet? */
1635 pFirstChange = pParent->firstChild; /* no, search from top */
1636 while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
1637 pFirstChange = pFirstChange->nextSib;
1640 if(pWin->drawable.pScreen->RestackWindow)
1641 (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib);
1644 #ifdef ROOTLESS
1646 * In rootless mode we can't optimize away window restacks.
1647 * There may be non-X windows around, so even if the window
1648 * is in the correct position from X's point of view,
1649 * the underlying window system may want to reorder it.
1651 else if (pWin->drawable.pScreen->RestackWindow)
1652 (*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib);
1653 #endif
1655 return( pFirstChange );
1658 _X_EXPORT RegionPtr
1659 CreateUnclippedWinSize (WindowPtr pWin)
1661 RegionPtr pRgn;
1662 BoxRec box;
1664 box.x1 = pWin->drawable.x;
1665 box.y1 = pWin->drawable.y;
1666 box.x2 = pWin->drawable.x + (int) pWin->drawable.width;
1667 box.y2 = pWin->drawable.y + (int) pWin->drawable.height;
1668 pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1);
1669 #ifdef SHAPE
1670 if (wBoundingShape (pWin) || wClipShape (pWin)) {
1671 ScreenPtr pScreen;
1672 pScreen = pWin->drawable.pScreen;
1674 REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x,
1675 - pWin->drawable.y);
1676 if (wBoundingShape (pWin))
1677 REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin));
1678 if (wClipShape (pWin))
1679 REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin));
1680 REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y);
1682 #endif
1683 return pRgn;
1686 _X_EXPORT void
1687 SetWinSize (WindowPtr pWin)
1689 #ifdef COMPOSITE
1690 if (pWin->redirectDraw != RedirectDrawNone)
1692 BoxRec box;
1695 * Redirected clients get clip list equal to their
1696 * own geometry, not clipped to their parent
1698 box.x1 = pWin->drawable.x;
1699 box.y1 = pWin->drawable.y;
1700 box.x2 = pWin->drawable.x + pWin->drawable.width;
1701 box.y2 = pWin->drawable.y + pWin->drawable.height;
1702 REGION_RESET (pScreen, &pWin->winSize, &box);
1704 else
1705 #endif
1706 ClippedRegionFromBox(pWin->parent, &pWin->winSize,
1707 pWin->drawable.x, pWin->drawable.y,
1708 (int)pWin->drawable.width,
1709 (int)pWin->drawable.height);
1710 #ifdef SHAPE
1711 if (wBoundingShape (pWin) || wClipShape (pWin)) {
1712 ScreenPtr pScreen;
1713 pScreen = pWin->drawable.pScreen;
1715 REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x,
1716 - pWin->drawable.y);
1717 if (wBoundingShape (pWin))
1718 REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize,
1719 wBoundingShape (pWin));
1720 if (wClipShape (pWin))
1721 REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize,
1722 wClipShape (pWin));
1723 REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x,
1724 pWin->drawable.y);
1726 #endif
1729 _X_EXPORT void
1730 SetBorderSize (WindowPtr pWin)
1732 int bw;
1734 if (HasBorder (pWin)) {
1735 bw = wBorderWidth (pWin);
1736 #ifdef COMPOSITE
1737 if (pWin->redirectDraw != RedirectDrawNone)
1739 BoxRec box;
1742 * Redirected clients get clip list equal to their
1743 * own geometry, not clipped to their parent
1745 box.x1 = pWin->drawable.x - bw;
1746 box.y1 = pWin->drawable.y - bw;
1747 box.x2 = pWin->drawable.x + pWin->drawable.width + bw;
1748 box.y2 = pWin->drawable.y + pWin->drawable.height + bw;
1749 REGION_RESET (pScreen, &pWin->borderSize, &box);
1751 else
1752 #endif
1753 ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
1754 pWin->drawable.x - bw, pWin->drawable.y - bw,
1755 (int)(pWin->drawable.width + (bw<<1)),
1756 (int)(pWin->drawable.height + (bw<<1)));
1757 #ifdef SHAPE
1758 if (wBoundingShape (pWin)) {
1759 ScreenPtr pScreen;
1760 pScreen = pWin->drawable.pScreen;
1762 REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x,
1763 - pWin->drawable.y);
1764 REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize,
1765 wBoundingShape (pWin));
1766 REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x,
1767 pWin->drawable.y);
1768 REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize,
1769 &pWin->winSize);
1771 #endif
1772 } else {
1773 REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize,
1774 &pWin->winSize);
1780 * \param x,y new window position
1781 * \param oldx,oldy old window position
1782 * \param destx,desty position relative to gravity
1785 _X_EXPORT void
1786 GravityTranslate (int x, int y, int oldx, int oldy,
1787 int dw, int dh, unsigned gravity,
1788 int *destx, int *desty)
1790 switch (gravity) {
1791 case NorthGravity:
1792 *destx = x + dw / 2;
1793 *desty = y;
1794 break;
1795 case NorthEastGravity:
1796 *destx = x + dw;
1797 *desty = y;
1798 break;
1799 case WestGravity:
1800 *destx = x;
1801 *desty = y + dh / 2;
1802 break;
1803 case CenterGravity:
1804 *destx = x + dw / 2;
1805 *desty = y + dh / 2;
1806 break;
1807 case EastGravity:
1808 *destx = x + dw;
1809 *desty = y + dh / 2;
1810 break;
1811 case SouthWestGravity:
1812 *destx = x;
1813 *desty = y + dh;
1814 break;
1815 case SouthGravity:
1816 *destx = x + dw / 2;
1817 *desty = y + dh;
1818 break;
1819 case SouthEastGravity:
1820 *destx = x + dw;
1821 *desty = y + dh;
1822 break;
1823 case StaticGravity:
1824 *destx = oldx;
1825 *desty = oldy;
1826 break;
1827 default:
1828 *destx = x;
1829 *desty = y;
1830 break;
1834 /* XXX need to retile border on each window with ParentRelative origin */
1835 _X_EXPORT void
1836 ResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh)
1838 ScreenPtr pScreen;
1839 WindowPtr pSib, pChild;
1840 Bool resized = (dw || dh);
1842 pScreen = pWin->drawable.pScreen;
1844 for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib)
1846 if (resized && (pSib->winGravity > NorthWestGravity))
1848 int cwsx, cwsy;
1850 cwsx = pSib->origin.x;
1851 cwsy = pSib->origin.y;
1852 GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
1853 pSib->winGravity, &cwsx, &cwsy);
1854 if (cwsx != pSib->origin.x || cwsy != pSib->origin.y)
1856 xEvent event;
1858 event.u.u.type = GravityNotify;
1859 event.u.gravity.window = pSib->drawable.id;
1860 event.u.gravity.x = cwsx - wBorderWidth (pSib);
1861 event.u.gravity.y = cwsy - wBorderWidth (pSib);
1862 DeliverEvents (pSib, &event, 1, NullWindow);
1863 pSib->origin.x = cwsx;
1864 pSib->origin.y = cwsy;
1867 pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
1868 pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
1869 SetWinSize (pSib);
1870 SetBorderSize (pSib);
1871 (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y);
1873 if ( (pChild = pSib->firstChild) )
1875 while (1)
1877 pChild->drawable.x = pChild->parent->drawable.x +
1878 pChild->origin.x;
1879 pChild->drawable.y = pChild->parent->drawable.y +
1880 pChild->origin.y;
1881 SetWinSize (pChild);
1882 SetBorderSize (pChild);
1883 (*pScreen->PositionWindow)(pChild,
1884 pChild->drawable.x, pChild->drawable.y);
1885 if (pChild->firstChild)
1887 pChild = pChild->firstChild;
1888 continue;
1890 while (!pChild->nextSib && (pChild != pSib))
1891 pChild = pChild->parent;
1892 if (pChild == pSib)
1893 break;
1894 pChild = pChild->nextSib;
1900 #define GET_INT16(m, f) \
1901 if (m & mask) \
1903 f = (INT16) *pVlist;\
1904 pVlist++; \
1906 #define GET_CARD16(m, f) \
1907 if (m & mask) \
1909 f = (CARD16) *pVlist;\
1910 pVlist++;\
1913 #define GET_CARD8(m, f) \
1914 if (m & mask) \
1916 f = (CARD8) *pVlist;\
1917 pVlist++;\
1920 #define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight))
1922 #define IllegalInputOnlyConfigureMask (CWBorderWidth)
1925 * IsSiblingAboveMe
1926 * returns Above if pSib above pMe in stack or Below otherwise
1929 static int
1930 IsSiblingAboveMe(
1931 WindowPtr pMe,
1932 WindowPtr pSib)
1934 WindowPtr pWin;
1936 pWin = pMe->parent->firstChild;
1937 while (pWin)
1939 if (pWin == pSib)
1940 return(Above);
1941 else if (pWin == pMe)
1942 return(Below);
1943 pWin = pWin->nextSib;
1945 return(Below);
1948 static BoxPtr
1949 WindowExtents(
1950 WindowPtr pWin,
1951 BoxPtr pBox)
1953 pBox->x1 = pWin->drawable.x - wBorderWidth (pWin);
1954 pBox->y1 = pWin->drawable.y - wBorderWidth (pWin);
1955 pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width
1956 + wBorderWidth (pWin);
1957 pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height
1958 + wBorderWidth (pWin);
1959 return(pBox);
1962 #ifdef SHAPE
1963 #define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL)
1965 static RegionPtr
1966 MakeBoundingRegion (
1967 WindowPtr pWin,
1968 BoxPtr pBox)
1970 RegionPtr pRgn;
1971 ScreenPtr pScreen;
1972 pScreen = pWin->drawable.pScreen;
1974 pRgn = REGION_CREATE(pScreen, pBox, 1);
1975 if (wBoundingShape (pWin)) {
1976 REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x,
1977 -pWin->origin.y);
1978 REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin));
1979 REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x,
1980 pWin->origin.y);
1982 return pRgn;
1985 static Bool
1986 ShapeOverlap (
1987 WindowPtr pWin,
1988 BoxPtr pWinBox,
1989 WindowPtr pSib,
1990 BoxPtr pSibBox)
1992 RegionPtr pWinRgn, pSibRgn;
1993 ScreenPtr pScreen;
1994 Bool ret;
1996 if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
1997 return TRUE;
1998 pScreen = pWin->drawable.pScreen;
1999 pWinRgn = MakeBoundingRegion (pWin, pWinBox);
2000 pSibRgn = MakeBoundingRegion (pSib, pSibBox);
2001 REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn);
2002 ret = REGION_NOTEMPTY(pScreen, pWinRgn);
2003 REGION_DESTROY(pScreen, pWinRgn);
2004 REGION_DESTROY(pScreen, pSibRgn);
2005 return ret;
2007 #endif
2009 static Bool
2010 AnyWindowOverlapsMe(
2011 WindowPtr pWin,
2012 WindowPtr pHead,
2013 BoxPtr box)
2015 WindowPtr pSib;
2016 BoxRec sboxrec;
2017 BoxPtr sbox;
2019 for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib)
2021 if (pSib->mapped)
2023 sbox = WindowExtents(pSib, &sboxrec);
2024 if (BOXES_OVERLAP(sbox, box)
2025 #ifdef SHAPE
2026 && ShapeOverlap (pWin, box, pSib, sbox)
2027 #endif
2029 return(TRUE);
2032 return(FALSE);
2035 static Bool
2036 IOverlapAnyWindow(
2037 WindowPtr pWin,
2038 BoxPtr box)
2040 WindowPtr pSib;
2041 BoxRec sboxrec;
2042 BoxPtr sbox;
2044 for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib)
2046 if (pSib->mapped)
2048 sbox = WindowExtents(pSib, &sboxrec);
2049 if (BOXES_OVERLAP(sbox, box)
2050 #ifdef SHAPE
2051 && ShapeOverlap (pWin, box, pSib, sbox)
2052 #endif
2054 return(TRUE);
2057 return(FALSE);
2061 * WhereDoIGoInTheStack()
2062 * Given pWin and pSib and the relationshipe smode, return
2063 * the window that pWin should go ABOVE.
2064 * If a pSib is specified:
2065 * Above: pWin is placed just above pSib
2066 * Below: pWin is placed just below pSib
2067 * TopIf: if pSib occludes pWin, then pWin is placed
2068 * at the top of the stack
2069 * BottomIf: if pWin occludes pSib, then pWin is
2070 * placed at the bottom of the stack
2071 * Opposite: if pSib occludes pWin, then pWin is placed at the
2072 * top of the stack, else if pWin occludes pSib, then
2073 * pWin is placed at the bottom of the stack
2075 * If pSib is NULL:
2076 * Above: pWin is placed at the top of the stack
2077 * Below: pWin is placed at the bottom of the stack
2078 * TopIf: if any sibling occludes pWin, then pWin is placed at
2079 * the top of the stack
2080 * BottomIf: if pWin occludes any sibline, then pWin is placed at
2081 * the bottom of the stack
2082 * Opposite: if any sibling occludes pWin, then pWin is placed at
2083 * the top of the stack, else if pWin occludes any
2084 * sibling, then pWin is placed at the bottom of the stack
2088 static WindowPtr
2089 WhereDoIGoInTheStack(
2090 WindowPtr pWin,
2091 WindowPtr pSib,
2092 short x,
2093 short y,
2094 unsigned short w,
2095 unsigned short h,
2096 int smode)
2098 BoxRec box;
2099 ScreenPtr pScreen;
2100 WindowPtr pHead, pFirst;
2102 if ((pWin == pWin->parent->firstChild) &&
2103 (pWin == pWin->parent->lastChild))
2104 return((WindowPtr ) NULL);
2105 pHead = RealChildHead(pWin->parent);
2106 pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
2107 pScreen = pWin->drawable.pScreen;
2108 box.x1 = x;
2109 box.y1 = y;
2110 box.x2 = x + (int)w;
2111 box.y2 = y + (int)h;
2112 switch (smode)
2114 case Above:
2115 if (pSib)
2116 return(pSib);
2117 else if (pWin == pFirst)
2118 return(pWin->nextSib);
2119 else
2120 return(pFirst);
2121 case Below:
2122 if (pSib)
2123 if (pSib->nextSib != pWin)
2124 return(pSib->nextSib);
2125 else
2126 return(pWin->nextSib);
2127 else
2128 return NullWindow;
2129 case TopIf:
2130 if ((!pWin->mapped || (pSib && !pSib->mapped)))
2131 return(pWin->nextSib);
2132 else if (pSib)
2134 if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
2135 (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT))
2136 return(pFirst);
2137 else
2138 return(pWin->nextSib);
2140 else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2141 return(pFirst);
2142 else
2143 return(pWin->nextSib);
2144 case BottomIf:
2145 if ((!pWin->mapped || (pSib && !pSib->mapped)))
2146 return(pWin->nextSib);
2147 else if (pSib)
2149 if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
2150 (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT))
2151 return NullWindow;
2152 else
2153 return(pWin->nextSib);
2155 else if (IOverlapAnyWindow(pWin, &box))
2156 return NullWindow;
2157 else
2158 return(pWin->nextSib);
2159 case Opposite:
2160 if ((!pWin->mapped || (pSib && !pSib->mapped)))
2161 return(pWin->nextSib);
2162 else if (pSib)
2164 if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)
2166 if (IsSiblingAboveMe(pWin, pSib) == Above)
2167 return(pFirst);
2168 else
2169 return NullWindow;
2171 else
2172 return(pWin->nextSib);
2174 else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2176 /* If I'm occluded, I can't possibly be the first child
2177 * if (pWin == pWin->parent->firstChild)
2178 * return pWin->nextSib;
2180 return(pFirst);
2182 else if (IOverlapAnyWindow(pWin, &box))
2183 return NullWindow;
2184 else
2185 return pWin->nextSib;
2186 default:
2188 ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode );
2189 return pWin->nextSib;
2194 static void
2195 ReflectStackChange(
2196 WindowPtr pWin,
2197 WindowPtr pSib,
2198 VTKind kind)
2200 /* Note that pSib might be NULL */
2202 Bool WasViewable = (Bool)pWin->viewable;
2203 Bool anyMarked;
2204 WindowPtr pFirstChange;
2205 #ifdef DO_SAVE_UNDERS
2206 Bool dosave = FALSE;
2207 #endif
2208 WindowPtr pLayerWin;
2209 ScreenPtr pScreen = pWin->drawable.pScreen;
2211 /* if this is a root window, can't be restacked */
2212 if (!pWin->parent)
2213 return;
2215 pFirstChange = MoveWindowInStack(pWin, pSib);
2217 if (WasViewable)
2219 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
2220 &pLayerWin);
2221 if (pLayerWin != pWin) pFirstChange = pLayerWin;
2222 #ifdef DO_SAVE_UNDERS
2223 if (DO_SAVE_UNDERS(pWin))
2225 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange);
2227 #endif /* DO_SAVE_UNDERS */
2228 if (anyMarked)
2230 (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind);
2231 (*pScreen->HandleExposures)(pLayerWin->parent);
2233 #ifdef DO_SAVE_UNDERS
2234 if (dosave)
2235 (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange);
2236 #endif /* DO_SAVE_UNDERS */
2237 if (anyMarked && pWin->drawable.pScreen->PostValidateTree)
2238 (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind);
2240 if (pWin->realized)
2241 WindowsRestructured ();
2244 /*****
2245 * ConfigureWindow
2246 *****/
2249 ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
2251 #define RESTACK_WIN 0
2252 #define MOVE_WIN 1
2253 #define RESIZE_WIN 2
2254 #define REBORDER_WIN 3
2255 WindowPtr pSib = NullWindow;
2256 WindowPtr pParent = pWin->parent;
2257 Window sibwid = 0;
2258 Mask index2, tmask;
2259 XID *pVlist;
2260 short x, y, beforeX, beforeY;
2261 unsigned short w = pWin->drawable.width,
2262 h = pWin->drawable.height,
2263 bw = pWin->borderWidth;
2264 int action, smode = Above;
2265 #ifdef XAPPGROUP
2266 ClientPtr win_owner;
2267 ClientPtr ag_leader = NULL;
2268 #endif
2269 xEvent event;
2271 if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask))
2272 return(BadMatch);
2274 if ((mask & CWSibling) && !(mask & CWStackMode))
2275 return(BadMatch);
2277 pVlist = vlist;
2279 if (pParent)
2281 x = pWin->drawable.x - pParent->drawable.x - (int)bw;
2282 y = pWin->drawable.y - pParent->drawable.y - (int)bw;
2284 else
2286 x = pWin->drawable.x;
2287 y = pWin->drawable.y;
2289 beforeX = x;
2290 beforeY = y;
2291 action = RESTACK_WIN;
2292 if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth))))
2294 GET_INT16(CWX, x);
2295 GET_INT16(CWY, y);
2296 action = MOVE_WIN;
2298 /* or should be resized */
2299 else if (mask & (CWX | CWY | CWWidth | CWHeight))
2301 GET_INT16(CWX, x);
2302 GET_INT16(CWY, y);
2303 GET_CARD16(CWWidth, w);
2304 GET_CARD16 (CWHeight, h);
2305 if (!w || !h)
2307 client->errorValue = 0;
2308 return BadValue;
2310 action = RESIZE_WIN;
2312 tmask = mask & ~ChangeMask;
2313 while (tmask)
2315 index2 = (Mask)lowbit (tmask);
2316 tmask &= ~index2;
2317 switch (index2)
2319 case CWBorderWidth:
2320 GET_CARD16(CWBorderWidth, bw);
2321 break;
2322 case CWSibling:
2323 sibwid = (Window ) *pVlist;
2324 pVlist++;
2325 pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid,
2326 RT_WINDOW, DixReadAccess);
2327 if (!pSib)
2329 client->errorValue = sibwid;
2330 return(BadWindow);
2332 if (pSib->parent != pParent)
2333 return(BadMatch);
2334 if (pSib == pWin)
2335 return(BadMatch);
2336 break;
2337 case CWStackMode:
2338 GET_CARD8(CWStackMode, smode);
2339 if ((smode != TopIf) && (smode != BottomIf) &&
2340 (smode != Opposite) && (smode != Above) && (smode != Below))
2342 client->errorValue = smode;
2343 return(BadValue);
2345 break;
2346 default:
2347 client->errorValue = mask;
2348 return(BadValue);
2351 /* root really can't be reconfigured, so just return */
2352 if (!pParent)
2353 return Success;
2355 /* Figure out if the window should be moved. Doesnt
2356 make the changes to the window if event sent */
2358 if (mask & CWStackMode)
2359 pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
2360 pParent->drawable.y + y,
2361 w + (bw << 1), h + (bw << 1), smode);
2362 else
2363 pSib = pWin->nextSib;
2365 #ifdef XAPPGROUP
2366 win_owner = clients[CLIENT_ID(pWin->drawable.id)];
2367 ag_leader = XagLeader (win_owner);
2368 #endif
2370 if ((!pWin->overrideRedirect) &&
2371 (RedirectSend(pParent)
2372 #ifdef XAPPGROUP
2373 || (win_owner->appgroup && ag_leader &&
2374 XagIsControlledRoot (client, pParent))
2375 #endif
2378 event.u.u.type = ConfigureRequest;
2379 event.u.configureRequest.window = pWin->drawable.id;
2380 if (mask & CWSibling)
2381 event.u.configureRequest.sibling = sibwid;
2382 else
2383 event.u.configureRequest.sibling = None;
2384 if (mask & CWStackMode)
2385 event.u.u.detail = smode;
2386 else
2387 event.u.u.detail = Above;
2388 event.u.configureRequest.x = x;
2389 event.u.configureRequest.y = y;
2390 #ifdef PANORAMIX
2391 if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
2392 event.u.configureRequest.x += panoramiXdataPtr[0].x;
2393 event.u.configureRequest.y += panoramiXdataPtr[0].y;
2395 #endif
2396 event.u.configureRequest.width = w;
2397 event.u.configureRequest.height = h;
2398 event.u.configureRequest.borderWidth = bw;
2399 event.u.configureRequest.valueMask = mask;
2400 #ifdef XAPPGROUP
2401 /* make sure if the ag_leader maps the window it goes to the wm */
2402 if (ag_leader && ag_leader != client &&
2403 XagIsControlledRoot (client, pParent)) {
2404 event.u.configureRequest.parent = XagId (win_owner);
2405 (void) TryClientEvents (ag_leader, &event, 1,
2406 NoEventMask, NoEventMask, NullGrab);
2407 return Success;
2409 #endif
2410 event.u.configureRequest.parent = pParent->drawable.id;
2411 if (MaybeDeliverEventsToClient(pParent, &event, 1,
2412 SubstructureRedirectMask, client) == 1)
2413 return(Success);
2415 if (action == RESIZE_WIN)
2417 Bool size_change = (w != pWin->drawable.width)
2418 || (h != pWin->drawable.height);
2419 if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask))
2421 xEvent eventT;
2422 eventT.u.u.type = ResizeRequest;
2423 eventT.u.resizeRequest.window = pWin->drawable.id;
2424 eventT.u.resizeRequest.width = w;
2425 eventT.u.resizeRequest.height = h;
2426 if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
2427 ResizeRedirectMask, client) == 1)
2429 /* if event is delivered, leave the actual size alone. */
2430 w = pWin->drawable.width;
2431 h = pWin->drawable.height;
2432 size_change = FALSE;
2435 if (!size_change)
2437 if (mask & (CWX | CWY))
2438 action = MOVE_WIN;
2439 else if (mask & (CWStackMode | CWBorderWidth))
2440 action = RESTACK_WIN;
2441 else /* really nothing to do */
2442 return(Success) ;
2446 if (action == RESIZE_WIN)
2447 /* we've already checked whether there's really a size change */
2448 goto ActuallyDoSomething;
2449 if ((mask & CWX) && (x != beforeX))
2450 goto ActuallyDoSomething;
2451 if ((mask & CWY) && (y != beforeY))
2452 goto ActuallyDoSomething;
2453 if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin)))
2454 goto ActuallyDoSomething;
2455 if (mask & CWStackMode)
2457 #ifndef ROOTLESS
2458 /* See above for why we always reorder in rootless mode. */
2459 if (pWin->nextSib != pSib)
2460 #endif
2461 goto ActuallyDoSomething;
2463 return(Success);
2465 ActuallyDoSomething:
2466 if (SubStrSend(pWin, pParent))
2468 event.u.u.type = ConfigureNotify;
2469 event.u.configureNotify.window = pWin->drawable.id;
2470 if (pSib)
2471 event.u.configureNotify.aboveSibling = pSib->drawable.id;
2472 else
2473 event.u.configureNotify.aboveSibling = None;
2474 event.u.configureNotify.x = x;
2475 event.u.configureNotify.y = y;
2476 #ifdef PANORAMIX
2477 if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
2478 event.u.configureNotify.x += panoramiXdataPtr[0].x;
2479 event.u.configureNotify.y += panoramiXdataPtr[0].y;
2481 #endif
2482 event.u.configureNotify.width = w;
2483 event.u.configureNotify.height = h;
2484 event.u.configureNotify.borderWidth = bw;
2485 event.u.configureNotify.override = pWin->overrideRedirect;
2486 DeliverEvents(pWin, &event, 1, NullWindow);
2488 if (mask & CWBorderWidth)
2490 if (action == RESTACK_WIN)
2492 action = MOVE_WIN;
2493 pWin->borderWidth = bw;
2495 else if ((action == MOVE_WIN) &&
2496 (beforeX + wBorderWidth (pWin) == x + (int)bw) &&
2497 (beforeY + wBorderWidth (pWin) == y + (int)bw))
2499 action = REBORDER_WIN;
2500 (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw);
2502 else
2503 pWin->borderWidth = bw;
2505 if (action == MOVE_WIN)
2506 (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib,
2507 (mask & CWBorderWidth) ? VTOther : VTMove);
2508 else if (action == RESIZE_WIN)
2509 (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
2510 else if (mask & CWStackMode)
2511 ReflectStackChange(pWin, pSib, VTOther);
2513 if (action != RESTACK_WIN)
2514 CheckCursorConfinement(pWin);
2515 return(Success);
2516 #undef RESTACK_WIN
2517 #undef MOVE_WIN
2518 #undef RESIZE_WIN
2519 #undef REBORDER_WIN
2523 /******
2525 * CirculateWindow
2526 * For RaiseLowest, raises the lowest mapped child (if any) that is
2527 * obscured by another child to the top of the stack. For LowerHighest,
2528 * lowers the highest mapped child (if any) that is obscuring another
2529 * child to the bottom of the stack. Exposure processing is performed
2531 ******/
2534 CirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
2536 WindowPtr pWin, pHead, pFirst;
2537 xEvent event;
2538 BoxRec box;
2540 pHead = RealChildHead(pParent);
2541 pFirst = pHead ? pHead->nextSib : pParent->firstChild;
2542 if (direction == RaiseLowest)
2544 for (pWin = pParent->lastChild;
2545 (pWin != pHead) &&
2546 !(pWin->mapped &&
2547 AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
2548 pWin = pWin->prevSib) ;
2549 if (pWin == pHead)
2550 return Success;
2552 else
2554 for (pWin = pFirst;
2555 pWin &&
2556 !(pWin->mapped &&
2557 IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
2558 pWin = pWin->nextSib) ;
2559 if (!pWin)
2560 return Success;
2563 event.u.circulate.window = pWin->drawable.id;
2564 event.u.circulate.parent = pParent->drawable.id;
2565 event.u.circulate.event = pParent->drawable.id;
2566 if (direction == RaiseLowest)
2567 event.u.circulate.place = PlaceOnTop;
2568 else
2569 event.u.circulate.place = PlaceOnBottom;
2571 if (RedirectSend(pParent))
2573 event.u.u.type = CirculateRequest;
2574 if (MaybeDeliverEventsToClient(pParent, &event, 1,
2575 SubstructureRedirectMask, client) == 1)
2576 return(Success);
2579 event.u.u.type = CirculateNotify;
2580 DeliverEvents(pWin, &event, 1, NullWindow);
2581 ReflectStackChange(pWin,
2582 (direction == RaiseLowest) ? pFirst : NullWindow,
2583 VTStack);
2585 return(Success);
2588 static int
2589 CompareWIDs(
2590 WindowPtr pWin,
2591 pointer value) /* must conform to VisitWindowProcPtr */
2593 Window *wid = (Window *)value;
2595 if (pWin->drawable.id == *wid)
2596 return(WT_STOPWALKING);
2597 else
2598 return(WT_WALKCHILDREN);
2601 /*****
2602 * ReparentWindow
2603 *****/
2606 ReparentWindow(WindowPtr pWin, WindowPtr pParent,
2607 int x, int y, ClientPtr client)
2609 WindowPtr pPrev, pPriorParent;
2610 Bool WasMapped = (Bool)(pWin->mapped);
2611 xEvent event;
2612 int bw = wBorderWidth (pWin);
2613 ScreenPtr pScreen;
2615 pScreen = pWin->drawable.pScreen;
2616 if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING)
2617 return(BadMatch);
2618 if (!MakeWindowOptional(pWin))
2619 return(BadAlloc);
2621 if (WasMapped)
2622 UnmapWindow(pWin, FALSE);
2624 event.u.u.type = ReparentNotify;
2625 event.u.reparent.window = pWin->drawable.id;
2626 event.u.reparent.parent = pParent->drawable.id;
2627 event.u.reparent.x = x;
2628 event.u.reparent.y = y;
2629 #ifdef PANORAMIX
2630 if(!noPanoramiXExtension && !pParent->parent) {
2631 event.u.reparent.x += panoramiXdataPtr[0].x;
2632 event.u.reparent.y += panoramiXdataPtr[0].y;
2634 #endif
2635 event.u.reparent.override = pWin->overrideRedirect;
2636 DeliverEvents(pWin, &event, 1, pParent);
2638 /* take out of sibling chain */
2640 pPriorParent = pPrev = pWin->parent;
2641 if (pPrev->firstChild == pWin)
2642 pPrev->firstChild = pWin->nextSib;
2643 if (pPrev->lastChild == pWin)
2644 pPrev->lastChild = pWin->prevSib;
2646 if (pWin->nextSib)
2647 pWin->nextSib->prevSib = pWin->prevSib;
2648 if (pWin->prevSib)
2649 pWin->prevSib->nextSib = pWin->nextSib;
2651 /* insert at begining of pParent */
2652 pWin->parent = pParent;
2653 pPrev = RealChildHead(pParent);
2654 if (pPrev)
2656 pWin->nextSib = pPrev->nextSib;
2657 if (pPrev->nextSib)
2658 pPrev->nextSib->prevSib = pWin;
2659 else
2660 pParent->lastChild = pWin;
2661 pPrev->nextSib = pWin;
2662 pWin->prevSib = pPrev;
2664 else
2666 pWin->nextSib = pParent->firstChild;
2667 pWin->prevSib = NullWindow;
2668 if (pParent->firstChild)
2669 pParent->firstChild->prevSib = pWin;
2670 else
2671 pParent->lastChild = pWin;
2672 pParent->firstChild = pWin;
2675 pWin->origin.x = x + bw;
2676 pWin->origin.y = y + bw;
2677 pWin->drawable.x = x + bw + pParent->drawable.x;
2678 pWin->drawable.y = y + bw + pParent->drawable.y;
2680 /* clip to parent */
2681 SetWinSize (pWin);
2682 SetBorderSize (pWin);
2684 if (pScreen->ReparentWindow)
2685 (*pScreen->ReparentWindow)(pWin, pPriorParent);
2686 (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
2687 ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
2689 CheckWindowOptionalNeed(pWin);
2691 if (WasMapped)
2692 MapWindow(pWin, client);
2693 RecalculateDeliverableEvents(pWin);
2694 return(Success);
2697 static void
2698 RealizeTree(WindowPtr pWin)
2700 WindowPtr pChild;
2701 RealizeWindowProcPtr Realize;
2703 Realize = pWin->drawable.pScreen->RealizeWindow;
2704 pChild = pWin;
2705 while (1)
2707 if (pChild->mapped)
2709 pChild->realized = TRUE;
2710 #ifdef DO_SAVE_UNDERS
2711 if (pChild->saveUnder)
2712 deltaSaveUndersViewable++;
2713 #endif
2714 pChild->viewable = (pChild->drawable.class == InputOutput);
2715 (* Realize)(pChild);
2716 if (pChild->firstChild)
2718 pChild = pChild->firstChild;
2719 continue;
2722 while (!pChild->nextSib && (pChild != pWin))
2723 pChild = pChild->parent;
2724 if (pChild == pWin)
2725 return;
2726 pChild = pChild->nextSib;
2730 static WindowPtr windowDisableMapUnmapEvents;
2732 void
2733 DisableMapUnmapEvents(WindowPtr pWin)
2735 assert (windowDisableMapUnmapEvents == NULL);
2737 windowDisableMapUnmapEvents = pWin;
2740 void
2741 EnableMapUnmapEvents(WindowPtr pWin)
2743 assert (windowDisableMapUnmapEvents != NULL);
2745 windowDisableMapUnmapEvents = NULL;
2748 static Bool
2749 MapUnmapEventsEnabled(WindowPtr pWin)
2751 return pWin != windowDisableMapUnmapEvents;
2754 /*****
2755 * MapWindow
2756 * If some other client has selected SubStructureReDirect on the parent
2757 * and override-redirect is xFalse, then a MapRequest event is generated,
2758 * but the window remains unmapped. Otherwise, the window is mapped and a
2759 * MapNotify event is generated.
2760 *****/
2762 _X_EXPORT int
2763 MapWindow(WindowPtr pWin, ClientPtr client)
2765 ScreenPtr pScreen;
2767 WindowPtr pParent;
2768 #ifdef DO_SAVE_UNDERS
2769 Bool dosave = FALSE;
2770 #endif
2771 WindowPtr pLayerWin;
2773 if (pWin->mapped)
2774 return(Success);
2776 /* general check for permission to map window */
2777 if (!XaceHook(XACE_MAP_ACCESS, client, pWin))
2778 return Success;
2780 pScreen = pWin->drawable.pScreen;
2781 if ( (pParent = pWin->parent) )
2783 xEvent event;
2784 Bool anyMarked;
2785 #ifdef XAPPGROUP
2786 ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)];
2787 ClientPtr ag_leader = XagLeader (win_owner);
2788 #endif
2790 if ((!pWin->overrideRedirect) &&
2791 (RedirectSend(pParent)
2792 #ifdef XAPPGROUP
2793 || (win_owner->appgroup && ag_leader &&
2794 XagIsControlledRoot (client, pParent))
2795 #endif
2798 event.u.u.type = MapRequest;
2799 event.u.mapRequest.window = pWin->drawable.id;
2800 #ifdef XAPPGROUP
2801 /* make sure if the ag_leader maps the window it goes to the wm */
2802 if (ag_leader && ag_leader != client &&
2803 XagIsControlledRoot (client, pParent)) {
2804 event.u.mapRequest.parent = XagId (win_owner);
2805 (void) TryClientEvents (ag_leader, &event, 1,
2806 NoEventMask, NoEventMask, NullGrab);
2807 return Success;
2809 #endif
2810 event.u.mapRequest.parent = pParent->drawable.id;
2812 if (MaybeDeliverEventsToClient(pParent, &event, 1,
2813 SubstructureRedirectMask, client) == 1)
2814 return(Success);
2817 pWin->mapped = TRUE;
2818 if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin))
2820 event.u.u.type = MapNotify;
2821 event.u.mapNotify.window = pWin->drawable.id;
2822 event.u.mapNotify.override = pWin->overrideRedirect;
2823 DeliverEvents(pWin, &event, 1, NullWindow);
2826 if (!pParent->realized)
2827 return(Success);
2828 RealizeTree(pWin);
2829 if (pWin->viewable)
2831 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
2832 &pLayerWin);
2833 #ifdef DO_SAVE_UNDERS
2834 if (DO_SAVE_UNDERS(pWin))
2836 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib);
2838 #endif /* DO_SAVE_UNDERS */
2839 if (anyMarked)
2841 (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
2842 (*pScreen->HandleExposures)(pLayerWin->parent);
2844 #ifdef DO_SAVE_UNDERS
2845 if (dosave)
2846 (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
2847 #endif /* DO_SAVE_UNDERS */
2848 if (anyMarked && pScreen->PostValidateTree)
2849 (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
2851 WindowsRestructured ();
2853 else
2855 RegionRec temp;
2857 pWin->mapped = TRUE;
2858 pWin->realized = TRUE; /* for roots */
2859 pWin->viewable = pWin->drawable.class == InputOutput;
2860 /* We SHOULD check for an error value here XXX */
2861 (*pScreen->RealizeWindow)(pWin);
2862 if (pScreen->ClipNotify)
2863 (*pScreen->ClipNotify) (pWin, 0, 0);
2864 if (pScreen->PostValidateTree)
2865 (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap);
2866 REGION_NULL(pScreen, &temp);
2867 REGION_COPY(pScreen, &temp, &pWin->clipList);
2868 (*pScreen->WindowExposures) (pWin, &temp, NullRegion);
2869 REGION_UNINIT(pScreen, &temp);
2872 return(Success);
2876 /*****
2877 * MapSubwindows
2878 * Performs a MapWindow all unmapped children of the window, in top
2879 * to bottom stacking order.
2880 *****/
2882 void
2883 MapSubwindows(WindowPtr pParent, ClientPtr client)
2885 WindowPtr pWin;
2886 WindowPtr pFirstMapped = NullWindow;
2887 #ifdef DO_SAVE_UNDERS
2888 WindowPtr pFirstSaveUndered = NullWindow;
2889 #endif
2890 ScreenPtr pScreen;
2891 Mask parentRedirect;
2892 Mask parentNotify;
2893 xEvent event;
2894 Bool anyMarked;
2895 #ifdef DO_SAVE_UNDERS
2896 Bool dosave = FALSE;
2897 #endif
2898 WindowPtr pLayerWin;
2900 pScreen = pParent->drawable.pScreen;
2901 parentRedirect = RedirectSend(pParent);
2902 parentNotify = SubSend(pParent);
2903 anyMarked = FALSE;
2904 for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib)
2906 if (!pWin->mapped)
2908 if (parentRedirect && !pWin->overrideRedirect)
2910 event.u.u.type = MapRequest;
2911 event.u.mapRequest.window = pWin->drawable.id;
2912 event.u.mapRequest.parent = pParent->drawable.id;
2914 if (MaybeDeliverEventsToClient(pParent, &event, 1,
2915 SubstructureRedirectMask, client) == 1)
2916 continue;
2919 pWin->mapped = TRUE;
2920 if (parentNotify || StrSend(pWin))
2922 event.u.u.type = MapNotify;
2923 event.u.mapNotify.window = pWin->drawable.id;
2924 event.u.mapNotify.override = pWin->overrideRedirect;
2925 DeliverEvents(pWin, &event, 1, NullWindow);
2928 if (!pFirstMapped)
2929 pFirstMapped = pWin;
2930 if (pParent->realized)
2932 RealizeTree(pWin);
2933 if (pWin->viewable)
2935 anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
2936 (WindowPtr *)NULL);
2937 #ifdef DO_SAVE_UNDERS
2938 if (DO_SAVE_UNDERS(pWin))
2940 dosave = TRUE;
2942 #endif /* DO_SAVE_UNDERS */
2948 if (pFirstMapped)
2950 pLayerWin = (*pScreen->GetLayerWindow)(pParent);
2951 if (pLayerWin->parent != pParent) {
2952 anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin,
2953 pLayerWin,
2954 (WindowPtr *)NULL);
2955 pFirstMapped = pLayerWin;
2957 if (anyMarked)
2959 #ifdef DO_SAVE_UNDERS
2960 if (pLayerWin->parent != pParent)
2962 if (dosave || (DO_SAVE_UNDERS(pLayerWin)))
2964 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin,
2965 pLayerWin);
2968 else if (dosave)
2970 dosave = FALSE;
2971 for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib)
2973 if (DO_SAVE_UNDERS(pWin))
2975 dosave |= (*pScreen->ChangeSaveUnder)(pWin,
2976 pWin->nextSib);
2977 if (dosave && !pFirstSaveUndered)
2978 pFirstSaveUndered = pWin;
2982 #endif /* DO_SAVE_UNDERS */
2983 (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap);
2984 (*pScreen->HandleExposures)(pLayerWin->parent);
2986 #ifdef DO_SAVE_UNDERS
2987 if (dosave)
2988 (*pScreen->PostChangeSaveUnder)(pLayerWin,
2989 pFirstSaveUndered->nextSib);
2990 #endif /* DO_SAVE_UNDERS */
2991 if (anyMarked && pScreen->PostValidateTree)
2992 (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped,
2993 VTMap);
2994 WindowsRestructured ();
2998 static void
2999 UnrealizeTree(
3000 WindowPtr pWin,
3001 Bool fromConfigure)
3003 WindowPtr pChild;
3004 UnrealizeWindowProcPtr Unrealize;
3005 MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
3007 Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
3008 MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow;
3009 pChild = pWin;
3010 while (1)
3012 if (pChild->realized)
3014 pChild->realized = FALSE;
3015 pChild->visibility = VisibilityNotViewable;
3016 #ifdef PANORAMIX
3017 if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) {
3018 PanoramiXRes *win;
3019 win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id,
3020 XRT_WINDOW);
3021 if(win)
3022 win->u.win.visibility = VisibilityNotViewable;
3024 #endif
3025 (* Unrealize)(pChild);
3026 DeleteWindowFromAnyEvents(pChild, FALSE);
3027 if (pChild->viewable)
3029 #ifdef DO_SAVE_UNDERS
3030 if (pChild->saveUnder)
3031 deltaSaveUndersViewable--;
3032 #endif
3033 pChild->viewable = FALSE;
3034 if (pChild->backStorage)
3035 (*pChild->drawable.pScreen->SaveDoomedAreas)(
3036 pChild, &pChild->clipList, 0, 0);
3037 (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure);
3038 pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
3040 if (pChild->firstChild)
3042 pChild = pChild->firstChild;
3043 continue;
3046 while (!pChild->nextSib && (pChild != pWin))
3047 pChild = pChild->parent;
3048 if (pChild == pWin)
3049 return;
3050 pChild = pChild->nextSib;
3054 /*****
3055 * UnmapWindow
3056 * If the window is already unmapped, this request has no effect.
3057 * Otherwise, the window is unmapped and an UnMapNotify event is
3058 * generated. Cannot unmap a root window.
3059 *****/
3061 _X_EXPORT int
3062 UnmapWindow(WindowPtr pWin, Bool fromConfigure)
3064 WindowPtr pParent;
3065 xEvent event;
3066 Bool wasRealized = (Bool)pWin->realized;
3067 Bool wasViewable = (Bool)pWin->viewable;
3068 ScreenPtr pScreen = pWin->drawable.pScreen;
3069 WindowPtr pLayerWin = pWin;
3071 if ((!pWin->mapped) || (!(pParent = pWin->parent)))
3072 return(Success);
3073 if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin))
3075 event.u.u.type = UnmapNotify;
3076 event.u.unmapNotify.window = pWin->drawable.id;
3077 event.u.unmapNotify.fromConfigure = fromConfigure;
3078 DeliverEvents(pWin, &event, 1, NullWindow);
3080 if (wasViewable && !fromConfigure)
3082 pWin->valdata = UnmapValData;
3083 (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin);
3084 (*pScreen->MarkWindow)(pLayerWin->parent);
3086 pWin->mapped = FALSE;
3087 if (wasRealized)
3088 UnrealizeTree(pWin, fromConfigure);
3089 if (wasViewable)
3091 if (!fromConfigure)
3093 (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap);
3094 (*pScreen->HandleExposures)(pLayerWin->parent);
3096 #ifdef DO_SAVE_UNDERS
3097 if (DO_SAVE_UNDERS(pWin))
3099 if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) )
3101 (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
3104 pWin->DIXsaveUnder = FALSE;
3105 #endif /* DO_SAVE_UNDERS */
3106 if (!fromConfigure && pScreen->PostValidateTree)
3107 (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap);
3109 if (wasRealized && !fromConfigure)
3110 WindowsRestructured ();
3111 return(Success);
3114 /*****
3115 * UnmapSubwindows
3116 * Performs an UnmapWindow request with the specified mode on all mapped
3117 * children of the window, in bottom to top stacking order.
3118 *****/
3120 void
3121 UnmapSubwindows(WindowPtr pWin)
3123 WindowPtr pChild, pHead;
3124 xEvent event;
3125 Bool wasRealized = (Bool)pWin->realized;
3126 Bool wasViewable = (Bool)pWin->viewable;
3127 Bool anyMarked = FALSE;
3128 Mask parentNotify;
3129 WindowPtr pLayerWin = NULL;
3130 ScreenPtr pScreen = pWin->drawable.pScreen;
3132 if (!pWin->firstChild)
3133 return;
3134 parentNotify = SubSend(pWin);
3135 pHead = RealChildHead(pWin);
3137 if (wasViewable)
3138 pLayerWin = (*pScreen->GetLayerWindow)(pWin);
3140 for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
3142 if (pChild->mapped)
3144 if (parentNotify || StrSend(pChild))
3146 event.u.u.type = UnmapNotify;
3147 event.u.unmapNotify.window = pChild->drawable.id;
3148 event.u.unmapNotify.fromConfigure = xFalse;
3149 DeliverEvents(pChild, &event, 1, NullWindow);
3151 if (pChild->viewable)
3153 pChild->valdata = UnmapValData;
3154 anyMarked = TRUE;
3156 pChild->mapped = FALSE;
3157 if (pChild->realized)
3158 UnrealizeTree(pChild, FALSE);
3159 if (wasViewable)
3161 #ifdef DO_SAVE_UNDERS
3162 pChild->DIXsaveUnder = FALSE;
3163 #endif /* DO_SAVE_UNDERS */
3164 if (pChild->backStorage)
3165 (*pScreen->SaveDoomedAreas)(
3166 pChild, &pChild->clipList, 0, 0);
3170 if (wasViewable)
3172 if (anyMarked)
3174 if (pLayerWin->parent == pWin)
3175 (*pScreen->MarkWindow)(pWin);
3176 else
3178 WindowPtr ptmp;
3179 (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
3180 (WindowPtr *)NULL);
3181 (*pScreen->MarkWindow)(pLayerWin->parent);
3183 /* Windows between pWin and pLayerWin may not have been marked */
3184 ptmp = pWin;
3186 while (ptmp != pLayerWin->parent)
3188 (*pScreen->MarkWindow)(ptmp);
3189 ptmp = ptmp->parent;
3191 pHead = pWin->firstChild;
3193 (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap);
3194 (*pScreen->HandleExposures)(pLayerWin->parent);
3196 #ifdef DO_SAVE_UNDERS
3197 if (DO_SAVE_UNDERS(pWin))
3199 if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin))
3200 (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
3202 #endif /* DO_SAVE_UNDERS */
3203 if (anyMarked && pScreen->PostValidateTree)
3204 (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap);
3206 if (wasRealized)
3207 WindowsRestructured ();
3211 void
3212 HandleSaveSet(ClientPtr client)
3214 WindowPtr pParent, pWin;
3215 int j;
3217 for (j=0; j<client->numSaved; j++)
3219 pWin = SaveSetWindow(client->saveSet[j]);
3220 #ifdef XFIXES
3221 if (SaveSetToRoot(client->saveSet[j]))
3222 pParent = WindowTable[pWin->drawable.pScreen->myNum];
3223 else
3224 #endif
3226 pParent = pWin->parent;
3227 while (pParent && (wClient (pParent) == client))
3228 pParent = pParent->parent;
3230 if (pParent)
3232 if (pParent != pWin->parent)
3234 ReparentWindow(pWin, pParent,
3235 pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x,
3236 pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y,
3237 client);
3238 if(!pWin->realized && pWin->mapped)
3239 pWin->mapped = FALSE;
3241 #ifdef XFIXES
3242 if (SaveSetRemap (client->saveSet[j]))
3243 #endif
3244 MapWindow(pWin, client);
3247 xfree(client->saveSet);
3248 client->numSaved = 0;
3249 client->saveSet = (SaveSetElt *)NULL;
3254 * \param x,y in root
3256 Bool
3257 PointInWindowIsVisible(WindowPtr pWin, int x, int y)
3259 BoxRec box;
3261 if (!pWin->realized)
3262 return (FALSE);
3263 if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip,
3264 x, y, &box)
3265 && (!wInputShape(pWin) ||
3266 POINT_IN_REGION(pWin->drawable.pScreen,
3267 wInputShape(pWin),
3268 x - pWin->drawable.x,
3269 y - pWin->drawable.y, &box)))
3270 return(TRUE);
3271 return(FALSE);
3275 _X_EXPORT RegionPtr
3276 NotClippedByChildren(WindowPtr pWin)
3278 ScreenPtr pScreen;
3279 RegionPtr pReg;
3281 pScreen = pWin->drawable.pScreen;
3282 pReg = REGION_CREATE(pScreen, NullBox, 1);
3283 if (pWin->parent ||
3284 screenIsSaved != SCREEN_SAVER_ON ||
3285 !HasSaverWindow (pWin->drawable.pScreen->myNum))
3287 REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize);
3289 return(pReg);
3292 _X_EXPORT void
3293 SendVisibilityNotify(WindowPtr pWin)
3295 xEvent event;
3296 #ifndef NO_XINERAMA_PORT
3297 unsigned int visibility = pWin->visibility;
3298 #endif
3299 #ifdef PANORAMIX
3300 /* This is not quite correct yet, but it's close */
3301 if(!noPanoramiXExtension) {
3302 PanoramiXRes *win;
3303 WindowPtr pWin2;
3304 int i, Scrnum;
3306 Scrnum = pWin->drawable.pScreen->myNum;
3308 win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum);
3310 if(!win || (win->u.win.visibility == visibility))
3311 return;
3313 switch(visibility) {
3314 case VisibilityUnobscured:
3315 for(i = 0; i < PanoramiXNumScreens; i++) {
3316 if(i == Scrnum) continue;
3318 pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW);
3320 if (pWin2) {
3321 if(pWin2->visibility == VisibilityPartiallyObscured)
3322 return;
3324 if(!i) pWin = pWin2;
3327 break;
3328 case VisibilityPartiallyObscured:
3329 if(Scrnum) {
3330 pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW);
3331 if (pWin2) pWin = pWin2;
3333 break;
3334 case VisibilityFullyObscured:
3335 for(i = 0; i < PanoramiXNumScreens; i++) {
3336 if(i == Scrnum) continue;
3338 pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW);
3340 if (pWin2) {
3341 if(pWin2->visibility != VisibilityFullyObscured)
3342 return;
3344 if(!i) pWin = pWin2;
3347 break;
3350 win->u.win.visibility = visibility;
3352 #endif
3354 event.u.u.type = VisibilityNotify;
3355 event.u.visibility.window = pWin->drawable.id;
3356 event.u.visibility.state = visibility;
3357 DeliverEvents(pWin, &event, 1, NullWindow);
3360 #define RANDOM_WIDTH 32
3362 #ifndef NOLOGOHACK
3363 static void DrawLogo(
3364 WindowPtr pWin
3366 #endif
3368 _X_EXPORT void
3369 SaveScreens(int on, int mode)
3371 int i;
3372 int what;
3373 int type;
3375 if (on == SCREEN_SAVER_FORCER)
3377 UpdateCurrentTimeIf();
3378 lastDeviceEventTime = currentTime;
3379 if (mode == ScreenSaverReset)
3380 what = SCREEN_SAVER_OFF;
3381 else
3382 what = SCREEN_SAVER_ON;
3383 type = what;
3385 else
3387 what = on;
3388 type = what;
3389 if (what == screenIsSaved)
3390 type = SCREEN_SAVER_CYCLE;
3392 for (i = 0; i < screenInfo.numScreens; i++)
3394 if (on == SCREEN_SAVER_FORCER)
3395 (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on);
3396 if (savedScreenInfo[i].ExternalScreenSaver)
3398 if ((*savedScreenInfo[i].ExternalScreenSaver)
3399 (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER))
3400 continue;
3402 if (type == screenIsSaved)
3403 continue;
3404 switch (type) {
3405 case SCREEN_SAVER_OFF:
3406 if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
3408 (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
3409 what);
3411 else if (HasSaverWindow (i))
3413 savedScreenInfo[i].pWindow = NullWindow;
3414 FreeResource(savedScreenInfo[i].wid, RT_NONE);
3416 break;
3417 case SCREEN_SAVER_CYCLE:
3418 if (savedScreenInfo[i].blanked == SCREEN_IS_TILED)
3420 WindowPtr pWin = savedScreenInfo[i].pWindow;
3421 /* make it look like screen saver is off, so that
3422 * NotClippedByChildren will compute a clip list
3423 * for the root window, so miPaintWindow works
3425 screenIsSaved = SCREEN_SAVER_OFF;
3426 #ifndef NOLOGOHACK
3427 if (logoScreenSaver)
3428 (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE);
3429 #endif
3430 (*pWin->drawable.pScreen->MoveWindow)(pWin,
3431 (short)(-(rand() % RANDOM_WIDTH)),
3432 (short)(-(rand() % RANDOM_WIDTH)),
3433 pWin->nextSib, VTMove);
3434 #ifndef NOLOGOHACK
3435 if (logoScreenSaver)
3436 DrawLogo(pWin);
3437 #endif
3438 screenIsSaved = SCREEN_SAVER_ON;
3441 * Call the DDX saver in case it wants to do something
3442 * at cycle time
3444 else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
3446 (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
3447 type);
3449 break;
3450 case SCREEN_SAVER_ON:
3451 if (ScreenSaverBlanking != DontPreferBlanking)
3453 if ((* screenInfo.screens[i]->SaveScreen)
3454 (screenInfo.screens[i], what))
3456 savedScreenInfo[i].blanked = SCREEN_IS_BLANKED;
3457 continue;
3459 if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3460 TileScreenSaver(i, SCREEN_IS_BLACK))
3462 savedScreenInfo[i].blanked = SCREEN_IS_BLACK;
3463 continue;
3466 if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3467 TileScreenSaver(i, SCREEN_IS_TILED))
3469 savedScreenInfo[i].blanked = SCREEN_IS_TILED;
3471 else
3472 savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED;
3473 break;
3476 screenIsSaved = what;
3477 if (mode == ScreenSaverReset)
3478 SetScreenSaverTimer();
3481 static Bool
3482 TileScreenSaver(int i, int kind)
3484 int j;
3485 int result;
3486 XID attributes[3];
3487 Mask mask;
3488 WindowPtr pWin;
3489 CursorMetricRec cm;
3490 unsigned char *srcbits, *mskbits;
3491 CursorPtr cursor;
3492 XID cursorID = 0;
3493 int attri;
3495 mask = 0;
3496 attri = 0;
3497 switch (kind) {
3498 case SCREEN_IS_TILED:
3499 switch (WindowTable[i]->backgroundState) {
3500 case BackgroundPixel:
3501 attributes[attri++] = WindowTable[i]->background.pixel;
3502 mask |= CWBackPixel;
3503 break;
3504 case BackgroundPixmap:
3505 attributes[attri++] = None;
3506 mask |= CWBackPixmap;
3507 break;
3508 default:
3509 break;
3511 break;
3512 case SCREEN_IS_BLACK:
3513 attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel;
3514 mask |= CWBackPixel;
3515 break;
3517 mask |= CWOverrideRedirect;
3518 attributes[attri++] = xTrue;
3521 * create a blank cursor
3524 cm.width=16;
3525 cm.height=16;
3526 cm.xhot=8;
3527 cm.yhot=8;
3528 srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16);
3529 mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16);
3530 if (!srcbits || !mskbits)
3532 xfree(srcbits);
3533 xfree(mskbits);
3534 cursor = 0;
3536 else
3538 for (j=0; j<BitmapBytePad(32)*16; j++)
3539 srcbits[j] = mskbits[j] = 0x0;
3540 cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
3541 if (cursor)
3543 cursorID = FakeClientID(0);
3544 if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
3546 attributes[attri] = cursorID;
3547 mask |= CWCursor;
3549 else
3550 cursor = 0;
3552 else
3554 xfree (srcbits);
3555 xfree (mskbits);
3559 pWin = savedScreenInfo[i].pWindow =
3560 CreateWindow(savedScreenInfo[i].wid,
3561 WindowTable[i],
3562 -RANDOM_WIDTH, -RANDOM_WIDTH,
3563 (unsigned short)screenInfo.screens[i]->width + RANDOM_WIDTH,
3564 (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH,
3565 0, InputOutput, mask, attributes, 0, serverClient,
3566 wVisual (WindowTable[i]), &result);
3568 if (cursor)
3569 FreeResource (cursorID, RT_NONE);
3571 if (!pWin)
3572 return FALSE;
3574 if (!AddResource(pWin->drawable.id, RT_WINDOW,
3575 (pointer)savedScreenInfo[i].pWindow))
3576 return FALSE;
3578 if (mask & CWBackPixmap)
3580 MakeRootTile (pWin);
3581 (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap);
3583 MapWindow(pWin, serverClient);
3584 #ifndef NOLOGOHACK
3585 if (kind == SCREEN_IS_TILED && logoScreenSaver)
3586 DrawLogo(pWin);
3587 #endif
3588 return TRUE;
3592 * FindWindowWithOptional
3594 * search ancestors of the given window for an entry containing
3595 * a WindowOpt structure. Assumptions: some parent will
3596 * contain the structure.
3599 _X_EXPORT WindowPtr
3600 FindWindowWithOptional (WindowPtr w)
3603 w = w->parent;
3604 while (!w->optional);
3605 return w;
3609 * CheckWindowOptionalNeed
3611 * check each optional entry in the given window to see if
3612 * the value is satisfied by the default rules. If so,
3613 * release the optional record
3616 _X_EXPORT void
3617 CheckWindowOptionalNeed (WindowPtr w)
3619 WindowOptPtr optional;
3620 WindowOptPtr parentOptional;
3622 if (!w->parent)
3623 return;
3624 optional = w->optional;
3625 if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate])
3626 return;
3627 if (optional->otherEventMasks != 0)
3628 return;
3629 if (optional->otherClients != NULL)
3630 return;
3631 if (optional->passiveGrabs != NULL)
3632 return;
3633 if (optional->userProps != NULL)
3634 return;
3635 if (optional->backingBitPlanes != ~0L)
3636 return;
3637 if (optional->backingPixel != 0)
3638 return;
3639 #ifdef SHAPE
3640 if (optional->boundingShape != NULL)
3641 return;
3642 if (optional->clipShape != NULL)
3643 return;
3644 if (optional->inputShape != NULL)
3645 return;
3646 #endif
3647 #ifdef XINPUT
3648 if (optional->inputMasks != NULL)
3649 return;
3650 #endif
3651 parentOptional = FindWindowWithOptional(w)->optional;
3652 if (optional->visual != parentOptional->visual)
3653 return;
3654 if (optional->cursor != None &&
3655 (optional->cursor != parentOptional->cursor ||
3656 w->parent->cursorIsNone))
3657 return;
3658 if (optional->colormap != parentOptional->colormap)
3659 return;
3660 DisposeWindowOptional (w);
3664 * MakeWindowOptional
3666 * create an optional record and initialize it with the default
3667 * values.
3670 _X_EXPORT Bool
3671 MakeWindowOptional (WindowPtr pWin)
3673 WindowOptPtr optional;
3674 WindowOptPtr parentOptional;
3676 if (pWin->optional)
3677 return TRUE;
3678 optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec));
3679 if (!optional)
3680 return FALSE;
3681 optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate];
3682 optional->otherEventMasks = 0;
3683 optional->otherClients = NULL;
3684 optional->passiveGrabs = NULL;
3685 optional->userProps = NULL;
3686 optional->backingBitPlanes = ~0L;
3687 optional->backingPixel = 0;
3688 #ifdef SHAPE
3689 optional->boundingShape = NULL;
3690 optional->clipShape = NULL;
3691 optional->inputShape = NULL;
3692 #endif
3693 #ifdef XINPUT
3694 optional->inputMasks = NULL;
3695 #endif
3696 parentOptional = FindWindowWithOptional(pWin)->optional;
3697 optional->visual = parentOptional->visual;
3698 if (!pWin->cursorIsNone)
3700 optional->cursor = parentOptional->cursor;
3701 optional->cursor->refcnt++;
3703 else
3705 optional->cursor = None;
3707 optional->colormap = parentOptional->colormap;
3708 pWin->optional = optional;
3709 return TRUE;
3712 #ifndef NOLOGOHACK
3713 static void
3714 DrawLogo(WindowPtr pWin)
3716 DrawablePtr pDraw;
3717 ScreenPtr pScreen;
3718 int x, y;
3719 unsigned int width, height, size;
3720 GC *pGC;
3721 int thin, gap, d31;
3722 DDXPointRec poly[4];
3723 ChangeGCVal fore[2], back[2];
3724 xrgb rgb[2];
3725 BITS32 fmask, bmask;
3726 ColormapPtr cmap;
3728 pDraw = (DrawablePtr)pWin;
3729 pScreen = pDraw->pScreen;
3730 x = -pWin->origin.x;
3731 y = -pWin->origin.y;
3732 width = pScreen->width;
3733 height = pScreen->height;
3734 pGC = GetScratchGC(pScreen->rootDepth, pScreen);
3735 if (!pGC)
3736 return;
3738 if ((rand() % 100) <= 17) /* make the probability for white fairly low */
3739 fore[0].val = pScreen->whitePixel;
3740 else
3741 fore[0].val = pScreen->blackPixel;
3742 if ((pWin->backgroundState == BackgroundPixel) &&
3743 (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) {
3744 Pixel querypixels[2];
3746 querypixels[0] = fore[0].val;
3747 querypixels[1] = pWin->background.pixel;
3748 QueryColors(cmap, 2, querypixels, rgb);
3749 if ((rgb[0].red == rgb[1].red) &&
3750 (rgb[0].green == rgb[1].green) &&
3751 (rgb[0].blue == rgb[1].blue)) {
3752 if (fore[0].val == pScreen->blackPixel)
3753 fore[0].val = pScreen->whitePixel;
3754 else
3755 fore[0].val = pScreen->blackPixel;
3758 fore[1].val = FillSolid;
3759 fmask = GCForeground|GCFillStyle;
3760 if (pWin->backgroundState == BackgroundPixel) {
3761 back[0].val = pWin->background.pixel;
3762 back[1].val = FillSolid;
3763 bmask = GCForeground|GCFillStyle;
3764 } else {
3765 back[0].val = 0;
3766 back[1].val = 0;
3767 dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin,
3768 NULL, back);
3769 back[0].val = FillTiled;
3770 back[1].ptr = pWin->background.pixmap;
3771 bmask = GCFillStyle|GCTile;
3774 /* should be the same as the reference function XmuDrawLogo() */
3776 size = width;
3777 if (height < width)
3778 size = height;
3779 size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH);
3780 size &= ~1;
3781 x += rand() % (width - size);
3782 y += rand() % (height - size);
3785 * Draw what will be the thin strokes.
3787 * -----
3788 * / /
3789 * / /
3790 * / /
3791 * / /
3792 * /____/
3795 * Point d is 9/44 (~1/5) of the way across.
3798 thin = (size / 11);
3799 if (thin < 1) thin = 1;
3800 gap = (thin+3) / 4;
3801 d31 = thin + thin + gap;
3802 poly[0].x = x + size; poly[0].y = y;
3803 poly[1].x = x + size-d31; poly[1].y = y;
3804 poly[2].x = x + 0; poly[2].y = y + size;
3805 poly[3].x = x + d31; poly[3].y = y + size;
3806 dixChangeGC(NullClient, pGC, fmask, NULL, fore);
3807 ValidateGC(pDraw, pGC);
3808 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3811 * Erase area not needed for lower thin stroke.
3813 * ------
3814 * / /
3815 * / __ /
3816 * / / /
3817 * / / /
3818 * /__/__/
3821 poly[0].x = x + d31/2; poly[0].y = y + size;
3822 poly[1].x = x + size / 2; poly[1].y = y + size/2;
3823 poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2;
3824 poly[3].x = x + d31; poly[3].y = y + size;
3825 dixChangeGC(NullClient, pGC, bmask, NULL, back);
3826 ValidateGC(pDraw, pGC);
3827 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3830 * Erase area not needed for upper thin stroke.
3832 * ------
3833 * / / /
3834 * /--/ /
3835 * / /
3836 * / /
3837 * /_____/
3840 poly[0].x = x + size - d31/2; poly[0].y = y;
3841 poly[1].x = x + size / 2; poly[1].y = y + size/2;
3842 poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2;
3843 poly[3].x = x + size - d31; poly[3].y = y;
3844 ValidateGC(pDraw, pGC);
3845 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3848 * Draw thick stroke.
3849 * Point b is 1/4 of the way across.
3852 * -----
3853 * \ \
3854 * \ \
3855 * \ \
3856 * \ \
3857 * \____\
3860 poly[0].x = x; poly[0].y = y;
3861 poly[1].x = x + size/4; poly[1].y = y;
3862 poly[2].x = x + size; poly[2].y = y + size;
3863 poly[3].x = x + size - size/4; poly[3].y = y + size;
3864 dixChangeGC(NullClient, pGC, fmask, NULL, fore);
3865 ValidateGC(pDraw, pGC);
3866 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3869 * Erase to create gap.
3878 poly[0].x = x + size- thin; poly[0].y = y;
3879 poly[1].x = x + size-( thin+gap); poly[1].y = y;
3880 poly[2].x = x + thin; poly[2].y = y + size;
3881 poly[3].x = x + thin + gap; poly[3].y = y + size;
3882 dixChangeGC(NullClient, pGC, bmask, NULL, back);
3883 ValidateGC(pDraw, pGC);
3884 (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3886 FreeScratchGC(pGC);
3889 #endif