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