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