Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / dmxwindow.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28/*
29 * Authors:
30 * Kevin E. Martin <kem@redhat.com>
31 *
32 */
33
34/** \file
35 * This file provides support for window-related functions. */
36
37#ifdef HAVE_DMX_CONFIG_H
38#include <dmx-config.h>
39#endif
40
41#include "dmx.h"
42#include "dmxsync.h"
43#include "dmxwindow.h"
44#include "dmxpixmap.h"
45#include "dmxcmap.h"
46#include "dmxvisual.h"
47#include "dmxinput.h"
48#include "dmxextension.h"
49#include "dmxpict.h"
50
51#include "windowstr.h"
52
53static void dmxDoRestackWindow(WindowPtr pWindow);
54static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
55 unsigned long *mask,
56 XSetWindowAttributes * attribs);
57
58static void dmxDoSetShape(WindowPtr pWindow);
59
60/** Initialize the private area for the window functions. */
61Bool
62dmxInitWindow(ScreenPtr pScreen)
63{
64 if (!dixRegisterPrivateKey
65 (&dmxWinPrivateKeyRec, PRIVATE_WINDOW, sizeof(dmxWinPrivRec)))
66 return FALSE;
67
68 return TRUE;
69}
70
71Window
72dmxCreateRootWindow(WindowPtr pWindow)
73{
74 ScreenPtr pScreen = pWindow->drawable.pScreen;
75 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
76 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
77 Window parent;
78 Visual *visual;
79 unsigned long mask;
80 XSetWindowAttributes attribs;
81 ColormapPtr pCmap;
82 dmxColormapPrivPtr pCmapPriv;
83
84 /* Create root window */
85
86 parent = dmxScreen->scrnWin; /* This is our "Screen" window */
87 visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual;
88
89 dixLookupResourceByType((pointer *) &pCmap, wColormap(pWindow),
90 RT_COLORMAP, NullClient, DixUnknownAccess);
91 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
92
93 mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel;
94 attribs.event_mask = ExposureMask;
95 attribs.backing_store = NotUseful;
96 attribs.colormap = pCmapPriv->cmap;
97 attribs.border_pixel = 0;
98
99 /* Incorporate new attributes, if needed */
100 if (pWinPriv->attribMask) {
101 dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
102 mask |= pWinPriv->attribMask;
103 }
104
105 return XCreateWindow(dmxScreen->beDisplay,
106 parent,
107 pWindow->origin.x - wBorderWidth(pWindow),
108 pWindow->origin.y - wBorderWidth(pWindow),
109 pWindow->drawable.width,
110 pWindow->drawable.height,
111 pWindow->borderWidth,
112 pWindow->drawable.depth,
113 pWindow->drawable.class, visual, mask, &attribs);
114}
115
116/** Change the location and size of the "screen" window. Called from
117 * dmxextension.c dmxConfigureScreenWindow(). */
118void
119dmxResizeScreenWindow(ScreenPtr pScreen, int x, int y, int w, int h)
120{
121 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
122 unsigned int m;
123 XWindowChanges c;
124
125 if (!dmxScreen->beDisplay)
126 return;
127
128 /* Handle resizing on back-end server */
129 m = CWX | CWY | CWWidth | CWHeight;
130 c.x = x;
131 c.y = y;
132 c.width = w;
133 c.height = h;
134
135 XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c);
136 dmxSync(dmxScreen, False);
137}
138
139/** Change the location and size of the "root" window. Called from
140 * #dmxCreateWindow. */
141void
142dmxResizeRootWindow(WindowPtr pRoot, int x, int y, int w, int h)
143{
144 DMXScreenInfo *dmxScreen = &dmxScreens[pRoot->drawable.pScreen->myNum];
145 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
146 unsigned int m;
147 XWindowChanges c;
148
149 /* Handle resizing on back-end server */
150 if (dmxScreen->beDisplay) {
151 m = CWX | CWY | CWWidth | CWHeight;
152 c.x = x;
153 c.y = y;
154 c.width = (w > 0) ? w : 1;
155 c.height = (h > 0) ? h : 1;
156
157 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
158 }
159
160 if (w == 0 || h == 0) {
161 if (pWinPriv->mapped) {
162 if (dmxScreen->beDisplay)
163 XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
164 pWinPriv->mapped = FALSE;
165 }
166 }
167 else if (!pWinPriv->mapped) {
168 if (dmxScreen->beDisplay)
169 XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
170 pWinPriv->mapped = TRUE;
171 }
172
173 if (dmxScreen->beDisplay)
174 dmxSync(dmxScreen, False);
175}
176
177void
178dmxGetDefaultWindowAttributes(WindowPtr pWindow,
179 Colormap * cmap, Visual ** visual)
180{
181 ScreenPtr pScreen = pWindow->drawable.pScreen;
182
183 if (pWindow->drawable.class != InputOnly &&
184 pWindow->optional &&
185 pWindow->optional->visual != wVisual(pWindow->parent)) {
186
187 /* Find the matching visual */
188 *visual = dmxLookupVisualFromID(pScreen, wVisual(pWindow));
189
190 /* Handle optional colormaps */
191 if (pWindow->optional->colormap) {
192 ColormapPtr pCmap;
193 dmxColormapPrivPtr pCmapPriv;
194
195 dixLookupResourceByType((pointer *) &pCmap, wColormap(pWindow),
196 RT_COLORMAP, NullClient, DixUnknownAccess);
197 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
198 *cmap = pCmapPriv->cmap;
199 }
200 else {
201 *cmap = dmxColormapFromDefaultVisual(pScreen, *visual);
202 }
203 }
204 else {
205 *visual = CopyFromParent;
206 *cmap = (Colormap) 0;
207 }
208}
209
210static Window
211dmxCreateNonRootWindow(WindowPtr pWindow)
212{
213 ScreenPtr pScreen = pWindow->drawable.pScreen;
214 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
215 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
216 Window parent;
217 unsigned long mask = 0L;
218 XSetWindowAttributes attribs;
219 dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
220
221 /* Create window on back-end server */
222
223 parent = pParentPriv->window;
224
225 /* The parent won't exist if this call to CreateNonRootWindow came
226 from ReparentWindow and the grandparent window has not yet been
227 created */
228 if (!parent) {
229 dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
230 parent = pParentPriv->window;
231 }
232
233 /* Incorporate new attributes, if needed */
234 if (pWinPriv->attribMask) {
235 dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
236 mask |= pWinPriv->attribMask;
237 }
238
239 /* Add in default attributes */
240 if (pWindow->drawable.class != InputOnly) {
241 mask |= CWBackingStore;
242 attribs.backing_store = NotUseful;
243
244 if (!(mask & CWColormap) && pWinPriv->cmap) {
245 mask |= CWColormap;
246 attribs.colormap = pWinPriv->cmap;
247 if (!(mask & CWBorderPixel)) {
248 mask |= CWBorderPixel;
249 attribs.border_pixel = 0;
250 }
251 }
252 }
253
254 /* Handle case where subwindows are being mapped, but created out of
255 order -- if current window has a previous sibling, then it cannot
256 be created on top of the stack, so we must restack the windows */
257 pWinPriv->restacked = (pWindow->prevSib != NullWindow);
258
259 return XCreateWindow(dmxScreen->beDisplay,
260 parent,
261 pWindow->origin.x - wBorderWidth(pWindow),
262 pWindow->origin.y - wBorderWidth(pWindow),
263 pWindow->drawable.width,
264 pWindow->drawable.height,
265 pWindow->borderWidth,
266 pWindow->drawable.depth,
267 pWindow->drawable.class,
268 pWinPriv->visual, mask, &attribs);
269}
270
271/** This function handles lazy window creation and realization. Window
272 * creation is handled by #dmxCreateNonRootWindow(). It also handles
273 * any stacking changes that have occured since the window was
274 * originally created by calling #dmxDoRestackWindow(). If the window
275 * is shaped, the shape is set on the back-end server by calling
276 * #dmxDoSetShape(), and if the window has pictures (from RENDER)
277 * associated with it, those pictures are created on the back-end
278 * server by calling #dmxCreatePictureList(). If \a doSync is TRUE,
279 * then #dmxSync() is called. */
280void
281dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync)
282{
283 ScreenPtr pScreen = pWindow->drawable.pScreen;
284 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
285 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
286
287 if (!dmxScreen->beDisplay)
288 return;
289
290 pWinPriv->window = dmxCreateNonRootWindow(pWindow);
291 if (pWinPriv->restacked)
292 dmxDoRestackWindow(pWindow);
293 if (pWinPriv->isShaped)
294 dmxDoSetShape(pWindow);
295 if (pWinPriv->hasPict)
296 dmxCreatePictureList(pWindow);
297 if (pWinPriv->mapped)
298 XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
299 if (doSync)
300 dmxSync(dmxScreen, False);
301}
302
303/** Create \a pWindow on the back-end server. If the lazy window
304 * creation optimization is enabled, then the actual creation and
305 * realization of the window is handled by
306 * #dmxCreateAndRealizeWindow(). */
307Bool
308dmxCreateWindow(WindowPtr pWindow)
309{
310 ScreenPtr pScreen = pWindow->drawable.pScreen;
311 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
312 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
313 Bool ret = TRUE;
314
315 DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
316#if 0
317 if (pScreen->CreateWindow)
318 ret = pScreen->CreateWindow(pWindow);
319#endif
320
321 /* Set up the defaults */
322 pWinPriv->window = (Window) 0;
323 pWinPriv->offscreen = TRUE;
324 pWinPriv->mapped = FALSE;
325 pWinPriv->restacked = FALSE;
326 pWinPriv->attribMask = 0;
327 pWinPriv->isShaped = FALSE;
328 pWinPriv->hasPict = FALSE;
329#ifdef GLXEXT
330 pWinPriv->swapGroup = NULL;
331 pWinPriv->barrier = 0;
332#endif
333
334 if (dmxScreen->beDisplay) {
335 /* Only create the root window at this stage -- non-root windows are
336 created when they are mapped and are on-screen */
337 if (!pWindow->parent) {
338 dmxScreen->rootWin = pWinPriv->window
339 = dmxCreateRootWindow(pWindow);
340 if (dmxScreen->scrnX != dmxScreen->rootX
341 || dmxScreen->scrnY != dmxScreen->rootY
342 || dmxScreen->scrnWidth != dmxScreen->rootWidth
343 || dmxScreen->scrnHeight != dmxScreen->rootHeight) {
344 dmxResizeRootWindow(pWindow,
345 dmxScreen->rootX,
346 dmxScreen->rootY,
347 dmxScreen->rootWidth,
348 dmxScreen->rootHeight);
349 dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index],
350 dmxScreen->rootX,
351 dmxScreen->rootY,
352 dmxScreen->rootWidth,
353 dmxScreen->rootHeight);
354 pWindow->origin.x = dmxScreen->rootX;
355 pWindow->origin.y = dmxScreen->rootY;
356 }
357 }
358 else {
359 dmxGetDefaultWindowAttributes(pWindow,
360 &pWinPriv->cmap, &pWinPriv->visual);
361
362 if (dmxLazyWindowCreation) {
363 /* Save parent's visual for use later */
364 if (pWinPriv->visual == CopyFromParent)
365 pWinPriv->visual =
366 dmxLookupVisualFromID(pScreen,
367 wVisual(pWindow->parent));
368 }
369 else {
370 pWinPriv->window = dmxCreateNonRootWindow(pWindow);
371 }
372 }
373
374 dmxSync(dmxScreen, False);
375 }
376
377 DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
378
379 return ret;
380}
381
382/** Destroy \a pWindow on the back-end server. */
383Bool
384dmxBEDestroyWindow(WindowPtr pWindow)
385{
386 ScreenPtr pScreen = pWindow->drawable.pScreen;
387 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
388 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
389
390 if (pWinPriv->window) {
391 XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window);
392 pWinPriv->window = (Window) 0;
393 return TRUE;
394 }
395
396 return FALSE;
397}
398
399/** Destroy \a pWindow on the back-end server. If any RENDER pictures
400 were created, destroy them as well. */
401Bool
402dmxDestroyWindow(WindowPtr pWindow)
403{
404 ScreenPtr pScreen = pWindow->drawable.pScreen;
405 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
406 Bool ret = TRUE;
407 Bool needSync = FALSE;
408
409#ifdef GLXEXT
410 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
411#endif
412
413 DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
414
415 /* Destroy any picture list associated with this window */
416 needSync |= dmxDestroyPictureList(pWindow);
417
418 /* Destroy window on back-end server */
419 needSync |= dmxBEDestroyWindow(pWindow);
420 if (needSync)
421 dmxSync(dmxScreen, FALSE);
422
423#ifdef GLXEXT
424 if (pWinPriv->swapGroup && pWinPriv->windowDestroyed)
425 pWinPriv->windowDestroyed(pWindow);
426#endif
427
428 if (pScreen->DestroyWindow)
429 ret = pScreen->DestroyWindow(pWindow);
430
431 DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
432
433 return ret;
434}
435
436/** Change the position of \a pWindow to be \a x, \a y. */
437Bool
438dmxPositionWindow(WindowPtr pWindow, int x, int y)
439{
440 ScreenPtr pScreen = pWindow->drawable.pScreen;
441 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
442 Bool ret = TRUE;
443 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
444 unsigned int m;
445 XWindowChanges c;
446
447 DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
448#if 0
449 if (pScreen->PositionWindow)
450 ret = pScreen->PositionWindow(pWindow, x, y);
451#endif
452
453 /* Determine if the window is completely off the visible portion of
454 the screen */
455 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
456
457 /* If the window is now on-screen and it is mapped and it has not
458 been created yet, create it and map it */
459 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
460 dmxCreateAndRealizeWindow(pWindow, TRUE);
461 }
462 else if (pWinPriv->window) {
463 /* Position window on back-end server */
464 m = CWX | CWY | CWWidth | CWHeight;
465 c.x = pWindow->origin.x - wBorderWidth(pWindow);
466 c.y = pWindow->origin.y - wBorderWidth(pWindow);
467 c.width = pWindow->drawable.width;
468 c.height = pWindow->drawable.height;
469 if (pWindow->drawable.class != InputOnly) {
470 m |= CWBorderWidth;
471 c.border_width = pWindow->borderWidth;
472 }
473
474 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
475 dmxSync(dmxScreen, False);
476 }
477
478 DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
479
480 return ret;
481}
482
483static void
484dmxDoChangeWindowAttributes(WindowPtr pWindow,
485 unsigned long *mask, XSetWindowAttributes * attribs)
486{
487 dmxPixPrivPtr pPixPriv;
488
489 if (*mask & CWBackPixmap) {
490 switch (pWindow->backgroundState) {
491 case None:
492 attribs->background_pixmap = None;
493 break;
494
495 case ParentRelative:
496 attribs->background_pixmap = ParentRelative;
497 break;
498
499 case BackgroundPixmap:
500 pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->background.pixmap);
501 attribs->background_pixmap = pPixPriv->pixmap;
502 break;
503
504 case BackgroundPixel:
505 *mask &= ~CWBackPixmap;
506 break;
507 }
508 }
509
510 if (*mask & CWBackPixel) {
511 if (pWindow->backgroundState == BackgroundPixel)
512 attribs->background_pixel = pWindow->background.pixel;
513 else
514 *mask &= ~CWBackPixel;
515 }
516
517 if (*mask & CWBorderPixmap) {
518 if (pWindow->borderIsPixel)
519 *mask &= ~CWBorderPixmap;
520 else {
521 pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->border.pixmap);
522 attribs->border_pixmap = pPixPriv->pixmap;
523 }
524 }
525
526 if (*mask & CWBorderPixel) {
527 if (pWindow->borderIsPixel)
528 attribs->border_pixel = pWindow->border.pixel;
529 else
530 *mask &= ~CWBorderPixel;
531 }
532
533 if (*mask & CWBitGravity)
534 attribs->bit_gravity = pWindow->bitGravity;
535
536 if (*mask & CWWinGravity)
537 *mask &= ~CWWinGravity; /* Handled by dix */
538
539 if (*mask & CWBackingStore)
540 *mask &= ~CWBackingStore; /* Backing store not supported */
541
542 if (*mask & CWBackingPlanes)
543 *mask &= ~CWBackingPlanes; /* Backing store not supported */
544
545 if (*mask & CWBackingPixel)
546 *mask &= ~CWBackingPixel; /* Backing store not supported */
547
548 if (*mask & CWOverrideRedirect)
549 attribs->override_redirect = pWindow->overrideRedirect;
550
551 if (*mask & CWSaveUnder)
552 *mask &= ~CWSaveUnder; /* Save unders not supported */
553
554 if (*mask & CWEventMask)
555 *mask &= ~CWEventMask; /* Events are handled by dix */
556
557 if (*mask & CWDontPropagate)
558 *mask &= ~CWDontPropagate; /* Events are handled by dix */
559
560 if (*mask & CWColormap) {
561 ColormapPtr pCmap;
562 dmxColormapPrivPtr pCmapPriv;
563
564 dixLookupResourceByType((pointer *) &pCmap, wColormap(pWindow),
565 RT_COLORMAP, NullClient, DixUnknownAccess);
566 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
567 attribs->colormap = pCmapPriv->cmap;
568 }
569
570 if (*mask & CWCursor)
571 *mask &= ~CWCursor; /* Handled by the cursor code */
572}
573
574/** Change the window attributes of \a pWindow. */
575Bool
576dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
577{
578 ScreenPtr pScreen = pWindow->drawable.pScreen;
579 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
580 Bool ret = TRUE;
581 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
582 XSetWindowAttributes attribs;
583
584 DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
585#if 0
586 if (pScreen->ChangeWindowAttributes)
587 ret = pScreen->ChangeWindowAttributes(pWindow, mask);
588#endif
589
590 /* Change window attribs on back-end server */
591 dmxDoChangeWindowAttributes(pWindow, &mask, &attribs);
592
593 /* Save mask for lazy window creation optimization */
594 pWinPriv->attribMask |= mask;
595
596 if (mask && pWinPriv->window) {
597 XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window,
598 mask, &attribs);
599 dmxSync(dmxScreen, False);
600 }
601
602 DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
603 pScreen);
604
605 return ret;
606}
607
608/** Realize \a pWindow on the back-end server. If the lazy window
609 * creation optimization is enabled, the window is only realized when
610 * it at least partially overlaps the screen. */
611Bool
612dmxRealizeWindow(WindowPtr pWindow)
613{
614 ScreenPtr pScreen = pWindow->drawable.pScreen;
615 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
616 Bool ret = TRUE;
617 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
618
619 DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
620#if 0
621 if (pScreen->RealizeWindow)
622 ret = pScreen->RealizeWindow(pWindow);
623#endif
624
625 /* Determine if the window is completely off the visible portion of
626 the screen */
627 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
628
629 /* If the window hasn't been created and it's not offscreen, then
630 create it */
631 if (!pWinPriv->window && !pWinPriv->offscreen) {
632 dmxCreateAndRealizeWindow(pWindow, FALSE);
633 }
634
635 if (pWinPriv->window) {
636 /* Realize window on back-end server */
637 XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
638 dmxSync(dmxScreen, False);
639 }
640
641 /* Let the other functions know that the window is now mapped */
642 pWinPriv->mapped = TRUE;
643
644 DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
645
646 dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow);
647 return ret;
648}
649
650/** Unrealize \a pWindow on the back-end server. */
651Bool
652dmxUnrealizeWindow(WindowPtr pWindow)
653{
654 ScreenPtr pScreen = pWindow->drawable.pScreen;
655 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
656 Bool ret = TRUE;
657 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
658
659 DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
660#if 0
661 if (pScreen->UnrealizeWindow)
662 ret = pScreen->UnrealizeWindow(pWindow);
663#endif
664
665 if (pWinPriv->window) {
666 /* Unrealize window on back-end server */
667 XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
668 dmxSync(dmxScreen, False);
669 }
670
671 /* When unrealized (i.e., unmapped), the window is always considered
672 off of the visible portion of the screen */
673 pWinPriv->offscreen = TRUE;
674 pWinPriv->mapped = FALSE;
675
676#ifdef GLXEXT
677 if (pWinPriv->swapGroup && pWinPriv->windowUnmapped)
678 pWinPriv->windowUnmapped(pWindow);
679#endif
680
681 DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
682
683 dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow);
684 return ret;
685}
686
687static void
688dmxDoRestackWindow(WindowPtr pWindow)
689{
690 ScreenPtr pScreen = pWindow->drawable.pScreen;
691 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
692 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
693 WindowPtr pNextSib = pWindow->nextSib;
694 unsigned int m;
695 XWindowChanges c;
696
697 if (pNextSib == NullWindow) {
698 /* Window is at the bottom of the stack */
699 m = CWStackMode;
700 c.sibling = (Window) 0;
701 c.stack_mode = Below;
702 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
703 }
704 else {
705 /* Window is not at the bottom of the stack */
706 dmxWinPrivPtr pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
707
708 /* Handle case where siblings have not yet been created due to
709 lazy window creation optimization by first finding the next
710 sibling in the sibling list that has been created (if any)
711 and then putting the current window just above that sibling,
712 and if no next siblings have been created yet, then put it at
713 the bottom of the stack (since it might have a previous
714 sibling that should be above it). */
715 while (!pNextSibPriv->window) {
716 pNextSib = pNextSib->nextSib;
717 if (pNextSib == NullWindow) {
718 /* Window is at the bottom of the stack */
719 m = CWStackMode;
720 c.sibling = (Window) 0;
721 c.stack_mode = Below;
722 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
723 return;
724 }
725 pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
726 }
727
728 m = CWStackMode | CWSibling;
729 c.sibling = pNextSibPriv->window;
730 c.stack_mode = Above;
731 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
732 }
733}
734
735/** Handle window restacking. The actual restacking occurs in
736 * #dmxDoRestackWindow(). */
737void
738dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib)
739{
740 ScreenPtr pScreen = pWindow->drawable.pScreen;
741 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
742 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
743
744 DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
745#if 0
746 if (pScreen->RestackWindow)
747 pScreen->RestackWindow(pWindow, pOldNextSib);
748#endif
749
750 if (pOldNextSib != pWindow->nextSib) {
751 /* Track restacking for lazy window creation optimization */
752 pWinPriv->restacked = TRUE;
753
754 /* Restack window on back-end server */
755 if (pWinPriv->window) {
756 dmxDoRestackWindow(pWindow);
757 dmxSync(dmxScreen, False);
758 }
759 }
760
761 DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
762 dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow);
763}
764
765static Bool
766dmxWindowExposurePredicate(Display * dpy, XEvent * ev, XPointer ptr)
767{
768 return (ev->type == Expose && ev->xexpose.window == *(Window *) ptr);
769}
770
771/** Handle exposures on \a pWindow. Since window exposures are handled
772 * in DMX, the events that are generated by the back-end server are
773 * redundant, so we eat them here. */
774void
775dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn, RegionPtr other_exposed)
776{
777 ScreenPtr pScreen = pWindow->drawable.pScreen;
778 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
779 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
780 XEvent ev;
781
782 DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
783
784 dmxSync(dmxScreen, False);
785
786 if (pWinPriv->window) {
787 while (XCheckIfEvent(dmxScreen->beDisplay, &ev,
788 dmxWindowExposurePredicate,
789 (XPointer) &pWinPriv->window)) {
790 /* Handle expose events -- this should not be necessary
791 since the base window in which the root window was
792 created is guaranteed to be on top (override_redirect),
793 so we should just swallow these events. If for some
794 reason the window is not on top, then we'd need to
795 collect these events and send them to the client later
796 (e.g., during the block handler as Xnest does). */
797 }
798 }
799
800#if 1
801 if (pScreen->WindowExposures)
802 pScreen->WindowExposures(pWindow, prgn, other_exposed);
803#endif
804 DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
805}
806
807/** Move \a pWindow on the back-end server. Determine whether or not it
808 * is on or offscreen, and realize it if it is newly on screen and the
809 * lazy window creation optimization is enabled. */
810void
811dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
812{
813 ScreenPtr pScreen = pWindow->drawable.pScreen;
814 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
815 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
816 unsigned int m;
817 XWindowChanges c;
818
819 DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
820#if 0
821 if (pScreen->CopyWindow)
822 pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
823#endif
824
825 /* Determine if the window is completely off the visible portion of
826 the screen */
827 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
828
829 /* If the window is now on-screen and it is mapped and it has not
830 been created yet, create it and map it */
831 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
832 dmxCreateAndRealizeWindow(pWindow, TRUE);
833 }
834 else if (pWinPriv->window) {
835 /* Move window on back-end server */
836 m = CWX | CWY | CWWidth | CWHeight;
837 c.x = pWindow->origin.x - wBorderWidth(pWindow);
838 c.y = pWindow->origin.y - wBorderWidth(pWindow);
839 c.width = pWindow->drawable.width;
840 c.height = pWindow->drawable.height;
841
842 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
843 dmxSync(dmxScreen, False);
844 }
845
846 DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
847 dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow);
848}
849
850/** Resize \a pWindow on the back-end server. Determine whether or not
851 * it is on or offscreen, and realize it if it is newly on screen and
852 * the lazy window creation optimization is enabled. */
853void
854dmxResizeWindow(WindowPtr pWindow, int x, int y,
855 unsigned int w, unsigned int h, WindowPtr pSib)
856{
857 ScreenPtr pScreen = pWindow->drawable.pScreen;
858 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
859 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
860 dmxWinPrivPtr pSibPriv;
861 unsigned int m;
862 XWindowChanges c;
863
864 if (pSib)
865 pSibPriv = DMX_GET_WINDOW_PRIV(pSib);
866
867 DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
868#if 1
869 if (pScreen->ResizeWindow)
870 pScreen->ResizeWindow(pWindow, x, y, w, h, pSib);
871#endif
872
873 /* Determine if the window is completely off the visible portion of
874 the screen */
875 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
876
877 /* If the window is now on-screen and it is mapped and it has not
878 been created yet, create it and map it */
879 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
880 dmxCreateAndRealizeWindow(pWindow, TRUE);
881 }
882 else if (pWinPriv->window) {
883 /* Handle resizing on back-end server */
884 m = CWX | CWY | CWWidth | CWHeight;
885 c.x = pWindow->origin.x - wBorderWidth(pWindow);
886 c.y = pWindow->origin.y - wBorderWidth(pWindow);
887 c.width = pWindow->drawable.width;
888 c.height = pWindow->drawable.height;
889
890 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
891 dmxSync(dmxScreen, False);
892 }
893
894 DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
895 dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow);
896}
897
898/** Reparent \a pWindow on the back-end server. */
899void
900dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent)
901{
902 ScreenPtr pScreen = pWindow->drawable.pScreen;
903 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
904 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
905 dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
906
907 DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
908#if 0
909 if (pScreen->ReparentWindow)
910 pScreen->ReparentWindow(pWindow, pPriorParent);
911#endif
912
913 if (pWinPriv->window) {
914 if (!pParentPriv->window) {
915 dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
916 }
917
918 /* Handle reparenting on back-end server */
919 XReparentWindow(dmxScreen->beDisplay, pWinPriv->window,
920 pParentPriv->window,
921 pWindow->origin.x - wBorderWidth(pWindow),
922 pWindow->origin.x - wBorderWidth(pWindow));
923 dmxSync(dmxScreen, False);
924 }
925
926 DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
927 dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow);
928}
929
930/** Change border width for \a pWindow to \a width pixels. */
931void
932dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width)
933{
934 ScreenPtr pScreen = pWindow->drawable.pScreen;
935 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
936 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
937 unsigned int m;
938 XWindowChanges c;
939
940 DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
941#if 1
942 if (pScreen->ChangeBorderWidth)
943 pScreen->ChangeBorderWidth(pWindow, width);
944#endif
945
946 /* NOTE: Do we need to check for on/off screen here? */
947
948 if (pWinPriv->window) {
949 /* Handle border width change on back-end server */
950 m = CWBorderWidth;
951 c.border_width = width;
952
953 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
954 dmxSync(dmxScreen, False);
955 }
956
957 DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
958}
959
960static void
961dmxDoSetShape(WindowPtr pWindow)
962{
963 ScreenPtr pScreen = pWindow->drawable.pScreen;
964 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
965 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
966 int nBox;
967 BoxPtr pBox;
968 int nRect;
969 XRectangle *pRect;
970 XRectangle *pRectFirst;
971
972 /* First, set the bounding shape */
973 if (wBoundingShape(pWindow)) {
974 pBox = RegionRects(wBoundingShape(pWindow));
975 nRect = nBox = RegionNumRects(wBoundingShape(pWindow));
976 pRectFirst = pRect = malloc(nRect * sizeof(*pRect));
977 while (nBox--) {
978 pRect->x = pBox->x1;
979 pRect->y = pBox->y1;
980 pRect->width = pBox->x2 - pBox->x1;
981 pRect->height = pBox->y2 - pBox->y1;
982 pBox++;
983 pRect++;
984 }
985 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
986 ShapeBounding, 0, 0,
987 pRectFirst, nRect, ShapeSet, YXBanded);
988 free(pRectFirst);
989 }
990 else {
991 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
992 ShapeBounding, 0, 0, None, ShapeSet);
993 }
994
995 /* Next, set the clip shape */
996 if (wClipShape(pWindow)) {
997 pBox = RegionRects(wClipShape(pWindow));
998 nRect = nBox = RegionNumRects(wClipShape(pWindow));
999 pRectFirst = pRect = malloc(nRect * sizeof(*pRect));
1000 while (nBox--) {
1001 pRect->x = pBox->x1;
1002 pRect->y = pBox->y1;
1003 pRect->width = pBox->x2 - pBox->x1;
1004 pRect->height = pBox->y2 - pBox->y1;
1005 pBox++;
1006 pRect++;
1007 }
1008 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
1009 ShapeClip, 0, 0,
1010 pRectFirst, nRect, ShapeSet, YXBanded);
1011 free(pRectFirst);
1012 }
1013 else {
1014 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
1015 ShapeClip, 0, 0, None, ShapeSet);
1016 }
1017
1018 if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) {
1019 ErrorF("Input selected for window %x on Screen %d\n",
1020 (unsigned int) pWinPriv->window, pScreen->myNum);
1021 }
1022}
1023
1024/** Set shape of \a pWindow on the back-end server. */
1025void
1026dmxSetShape(WindowPtr pWindow, int kind)
1027{
1028 ScreenPtr pScreen = pWindow->drawable.pScreen;
1029 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1030 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
1031
1032 DMX_UNWRAP(SetShape, dmxScreen, pScreen);
1033#if 1
1034 if (pScreen->SetShape)
1035 pScreen->SetShape(pWindow, kind);
1036#endif
1037
1038 if (pWinPriv->window) {
1039 /* Handle setting the current shape on the back-end server */
1040 dmxDoSetShape(pWindow);
1041 dmxSync(dmxScreen, False);
1042 }
1043 else {
1044 pWinPriv->isShaped = TRUE;
1045 }
1046
1047 DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
1048}