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