First import
[xorg_rtime.git] / xorg-server-1.4 / hw / dmx / dmxwindow.c
blobb66f2a3bbb15e0a769bb052659f125f81d00068d
1 /*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
4 * All Rights Reserved.
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:
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.
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.
29 * Authors:
30 * Kevin E. Martin <kem@redhat.com>
34 /** \file
35 * This file provides support for window-related functions. */
37 #ifdef HAVE_DMX_CONFIG_H
38 #include <dmx-config.h>
39 #endif
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 #ifdef RENDER
50 #include "dmxpict.h"
51 #endif
53 #include "windowstr.h"
55 static void dmxDoRestackWindow(WindowPtr pWindow);
56 static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
57 unsigned long *mask,
58 XSetWindowAttributes *attribs);
60 #ifdef SHAPE
61 static void dmxDoSetShape(WindowPtr pWindow);
62 #endif
64 /** Initialize the private area for the window functions. */
65 Bool dmxInitWindow(ScreenPtr pScreen)
67 if (!AllocateWindowPrivate(pScreen, dmxWinPrivateIndex,
68 sizeof(dmxWinPrivRec)))
69 return FALSE;
71 return TRUE;
75 Window dmxCreateRootWindow(WindowPtr pWindow)
77 ScreenPtr pScreen = pWindow->drawable.pScreen;
78 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
79 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
80 Window parent;
81 Visual *visual;
82 unsigned long mask;
83 XSetWindowAttributes attribs;
84 ColormapPtr pCmap;
85 dmxColormapPrivPtr pCmapPriv;
87 /* Create root window */
89 parent = dmxScreen->scrnWin; /* This is our "Screen" window */
90 visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual;
92 pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP);
93 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
95 mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel;
96 attribs.event_mask = ExposureMask;
97 attribs.backing_store = NotUseful;
98 attribs.colormap = pCmapPriv->cmap;
99 attribs.border_pixel = 0;
101 /* Incorporate new attributes, if needed */
102 if (pWinPriv->attribMask) {
103 dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
104 mask |= pWinPriv->attribMask;
107 return XCreateWindow(dmxScreen->beDisplay,
108 parent,
109 pWindow->origin.x - wBorderWidth(pWindow),
110 pWindow->origin.y - wBorderWidth(pWindow),
111 pWindow->drawable.width,
112 pWindow->drawable.height,
113 pWindow->borderWidth,
114 pWindow->drawable.depth,
115 pWindow->drawable.class,
116 visual,
117 mask,
118 &attribs);
121 /** Change the location and size of the "screen" window. Called from
122 * #dmxReconfigureScreenWindow(). */
123 void dmxResizeScreenWindow(ScreenPtr pScreen,
124 int x, int y, int w, int h)
126 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
127 unsigned int m;
128 XWindowChanges c;
130 if (!dmxScreen->beDisplay)
131 return;
133 /* Handle resizing on back-end server */
134 m = CWX | CWY | CWWidth | CWHeight;
135 c.x = x;
136 c.y = y;
137 c.width = w;
138 c.height = h;
140 XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c);
141 dmxSync(dmxScreen, False);
144 /** Change the location and size of the "root" window. Called from
145 * #dmxReconfigureRootWindow(). */
146 void dmxResizeRootWindow(WindowPtr pRoot,
147 int x, int y, int w, int h)
149 DMXScreenInfo *dmxScreen = &dmxScreens[pRoot->drawable.pScreen->myNum];
150 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
151 unsigned int m;
152 XWindowChanges c;
154 /* Handle resizing on back-end server */
155 if (dmxScreen->beDisplay) {
156 m = CWX | CWY | CWWidth | CWHeight;
157 c.x = x;
158 c.y = y;
159 c.width = (w > 0) ? w : 1;
160 c.height = (h > 0) ? h : 1;
162 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
165 if (w == 0 || h == 0) {
166 if (pWinPriv->mapped) {
167 if (dmxScreen->beDisplay)
168 XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
169 pWinPriv->mapped = FALSE;
171 } else if (!pWinPriv->mapped) {
172 if (dmxScreen->beDisplay)
173 XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
174 pWinPriv->mapped = TRUE;
177 if (dmxScreen->beDisplay)
178 dmxSync(dmxScreen, False);
181 void dmxGetDefaultWindowAttributes(WindowPtr pWindow,
182 Colormap *cmap,
183 Visual **visual)
185 ScreenPtr pScreen = pWindow->drawable.pScreen;
187 if (pWindow->drawable.class != InputOnly &&
188 pWindow->optional &&
189 pWindow->optional->visual != wVisual(pWindow->parent)) {
191 /* Find the matching visual */
192 *visual = dmxLookupVisualFromID(pScreen, wVisual(pWindow));
194 /* Handle optional colormaps */
195 if (pWindow->optional->colormap) {
196 ColormapPtr pCmap;
197 dmxColormapPrivPtr pCmapPriv;
199 pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow),
200 RT_COLORMAP);
201 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
202 *cmap = pCmapPriv->cmap;
203 } else {
204 *cmap = dmxColormapFromDefaultVisual(pScreen, *visual);
206 } else {
207 *visual = CopyFromParent;
208 *cmap = (Colormap)0;
212 static Window dmxCreateNonRootWindow(WindowPtr pWindow)
214 ScreenPtr pScreen = pWindow->drawable.pScreen;
215 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
216 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
217 Window parent;
218 unsigned long mask = 0L;
219 XSetWindowAttributes attribs;
220 dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
222 /* Create window on back-end server */
224 parent = pParentPriv->window;
226 /* The parent won't exist if this call to CreateNonRootWindow came
227 from ReparentWindow and the grandparent window has not yet been
228 created */
229 if (!parent) {
230 dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
231 parent = pParentPriv->window;
234 /* Incorporate new attributes, if needed */
235 if (pWinPriv->attribMask) {
236 dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
237 mask |= pWinPriv->attribMask;
240 /* Add in default attributes */
241 if (pWindow->drawable.class != InputOnly) {
242 mask |= CWBackingStore;
243 attribs.backing_store = NotUseful;
245 if (!(mask & CWColormap) && pWinPriv->cmap) {
246 mask |= CWColormap;
247 attribs.colormap = pWinPriv->cmap;
248 if (!(mask & CWBorderPixel)) {
249 mask |= CWBorderPixel;
250 attribs.border_pixel = 0;
255 /* Handle case where subwindows are being mapped, but created out of
256 order -- if current window has a previous sibling, then it cannot
257 be created on top of the stack, so we must restack the windows */
258 pWinPriv->restacked = (pWindow->prevSib != NullWindow);
260 return XCreateWindow(dmxScreen->beDisplay,
261 parent,
262 pWindow->origin.x - wBorderWidth(pWindow),
263 pWindow->origin.y - wBorderWidth(pWindow),
264 pWindow->drawable.width,
265 pWindow->drawable.height,
266 pWindow->borderWidth,
267 pWindow->drawable.depth,
268 pWindow->drawable.class,
269 pWinPriv->visual,
270 mask,
271 &attribs);
274 /** This function handles lazy window creation and realization. Window
275 * creation is handled by #dmxCreateNonRootWindow(). It also handles
276 * any stacking changes that have occured since the window was
277 * originally created by calling #dmxDoRestackWindow(). If the window
278 * is shaped, the shape is set on the back-end server by calling
279 * #dmxDoSetShape(), and if the window has pictures (from RENDER)
280 * associated with it, those pictures are created on the back-end
281 * server by calling #dmxCreatePictureList(). If \a doSync is TRUE,
282 * then #dmxSync() is called. */
283 void dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync)
285 ScreenPtr pScreen = pWindow->drawable.pScreen;
286 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
287 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
289 if (!dmxScreen->beDisplay) return;
291 pWinPriv->window = dmxCreateNonRootWindow(pWindow);
292 if (pWinPriv->restacked) dmxDoRestackWindow(pWindow);
293 #ifdef SHAPE
294 if (pWinPriv->isShaped) dmxDoSetShape(pWindow);
295 #endif
296 #ifdef RENDER
297 if (pWinPriv->hasPict) dmxCreatePictureList(pWindow);
298 #endif
299 if (pWinPriv->mapped) XMapWindow(dmxScreen->beDisplay,
300 pWinPriv->window);
301 if (doSync) dmxSync(dmxScreen, False);
304 /** Create \a pWindow on the back-end server. If the lazy window
305 * creation optimization is enabled, then the actual creation and
306 * realization of the window is handled by
307 * #dmxCreateAndRealizeWindow(). */
308 Bool dmxCreateWindow(WindowPtr pWindow)
310 ScreenPtr pScreen = pWindow->drawable.pScreen;
311 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
312 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
313 Bool ret = TRUE;
315 DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
316 #if 0
317 if (pScreen->CreateWindow)
318 ret = pScreen->CreateWindow(pWindow);
319 #endif
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 #ifdef SHAPE
328 pWinPriv->isShaped = FALSE;
329 #endif
330 #ifdef RENDER
331 pWinPriv->hasPict = FALSE;
332 #endif
333 #ifdef GLXEXT
334 pWinPriv->swapGroup = NULL;
335 pWinPriv->barrier = 0;
336 #endif
338 if (dmxScreen->beDisplay) {
339 /* Only create the root window at this stage -- non-root windows are
340 created when they are mapped and are on-screen */
341 if (!pWindow->parent) {
342 dmxScreen->rootWin = pWinPriv->window
343 = dmxCreateRootWindow(pWindow);
344 if (dmxScreen->scrnX != dmxScreen->rootX
345 || dmxScreen->scrnY != dmxScreen->rootY
346 || dmxScreen->scrnWidth != dmxScreen->rootWidth
347 || dmxScreen->scrnHeight != dmxScreen->rootHeight) {
348 dmxResizeRootWindow(pWindow,
349 dmxScreen->rootX,
350 dmxScreen->rootY,
351 dmxScreen->rootWidth,
352 dmxScreen->rootHeight);
353 dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index],
354 dmxScreen->rootX,
355 dmxScreen->rootY,
356 dmxScreen->rootWidth,
357 dmxScreen->rootHeight);
358 pWindow->origin.x = dmxScreen->rootX;
359 pWindow->origin.y = dmxScreen->rootY;
361 } else {
362 dmxGetDefaultWindowAttributes(pWindow,
363 &pWinPriv->cmap,
364 &pWinPriv->visual);
366 if (dmxLazyWindowCreation) {
367 /* Save parent's visual for use later */
368 if (pWinPriv->visual == CopyFromParent)
369 pWinPriv->visual =
370 dmxLookupVisualFromID(pScreen,
371 wVisual(pWindow->parent));
372 } else {
373 pWinPriv->window = dmxCreateNonRootWindow(pWindow);
377 dmxSync(dmxScreen, False);
380 DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
382 return ret;
385 /** Destroy \a pWindow on the back-end server. */
386 Bool dmxBEDestroyWindow(WindowPtr pWindow)
388 ScreenPtr pScreen = pWindow->drawable.pScreen;
389 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
390 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
392 if (pWinPriv->window) {
393 XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window);
394 pWinPriv->window = (Window)0;
395 return TRUE;
398 return FALSE;
401 /** Destroy \a pWindow on the back-end server. If any RENDER pictures
402 were created, destroy them as well. */
403 Bool dmxDestroyWindow(WindowPtr pWindow)
405 ScreenPtr pScreen = pWindow->drawable.pScreen;
406 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
407 Bool ret = TRUE;
408 Bool needSync = FALSE;
409 #ifdef GLXEXT
410 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
411 #endif
413 DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
415 #ifdef RENDER
416 /* Destroy any picture list associated with this window */
417 needSync |= dmxDestroyPictureList(pWindow);
418 #endif
420 /* Destroy window on back-end server */
421 needSync |= dmxBEDestroyWindow(pWindow);
422 if (needSync) dmxSync(dmxScreen, FALSE);
424 #ifdef GLXEXT
425 if (pWinPriv->swapGroup && pWinPriv->windowDestroyed)
426 pWinPriv->windowDestroyed(pWindow);
427 #endif
429 #if 0
430 if (pScreen->DestroyWindow)
431 ret = pScreen->DestroyWindow(pWindow);
432 #endif
433 DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
435 return ret;
438 /** Change the position of \a pWindow to be \a x, \a y. */
439 Bool dmxPositionWindow(WindowPtr pWindow, int x, int y)
441 ScreenPtr pScreen = pWindow->drawable.pScreen;
442 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
443 Bool ret = TRUE;
444 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
445 unsigned int m;
446 XWindowChanges c;
448 DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
449 #if 0
450 if (pScreen->PositionWindow)
451 ret = pScreen->PositionWindow(pWindow, x, y);
452 #endif
454 /* Determine if the window is completely off the visible portion of
455 the screen */
456 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
458 /* If the window is now on-screen and it is mapped and it has not
459 been created yet, create it and map it */
460 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
461 dmxCreateAndRealizeWindow(pWindow, TRUE);
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;
474 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
475 dmxSync(dmxScreen, False);
478 DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
480 return ret;
483 static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
484 unsigned long *mask,
485 XSetWindowAttributes *attribs)
487 dmxPixPrivPtr pPixPriv;
489 if (*mask & CWBackPixmap) {
490 switch (pWindow->backgroundState) {
491 case None:
492 attribs->background_pixmap = None;
493 break;
495 case ParentRelative:
496 attribs->background_pixmap = ParentRelative;
497 break;
499 case BackgroundPixmap:
500 pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->background.pixmap);
501 attribs->background_pixmap = pPixPriv->pixmap;
502 break;
504 case BackgroundPixel:
505 *mask &= ~CWBackPixmap;
506 break;
510 if (*mask & CWBackPixel) {
511 if (pWindow->backgroundState == BackgroundPixel)
512 attribs->background_pixel = pWindow->background.pixel;
513 else
514 *mask &= ~CWBackPixel;
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;
526 if (*mask & CWBorderPixel) {
527 if (pWindow->borderIsPixel)
528 attribs->border_pixel = pWindow->border.pixel;
529 else
530 *mask &= ~CWBorderPixel;
533 if (*mask & CWBitGravity)
534 attribs->bit_gravity = pWindow->bitGravity;
536 if (*mask & CWWinGravity)
537 *mask &= ~CWWinGravity; /* Handled by dix */
539 if (*mask & CWBackingStore)
540 *mask &= ~CWBackingStore; /* Backing store not supported */
542 if (*mask & CWBackingPlanes)
543 *mask &= ~CWBackingPlanes; /* Backing store not supported */
545 if (*mask & CWBackingPixel)
546 *mask &= ~CWBackingPixel; /* Backing store not supported */
548 if (*mask & CWOverrideRedirect)
549 attribs->override_redirect = pWindow->overrideRedirect;
551 if (*mask & CWSaveUnder)
552 *mask &= ~CWSaveUnder; /* Save unders not supported */
554 if (*mask & CWEventMask)
555 *mask &= ~CWEventMask; /* Events are handled by dix */
557 if (*mask & CWDontPropagate)
558 *mask &= ~CWDontPropagate; /* Events are handled by dix */
560 if (*mask & CWColormap) {
561 ColormapPtr pCmap;
562 dmxColormapPrivPtr pCmapPriv;
564 pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP);
565 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
566 attribs->colormap = pCmapPriv->cmap;
569 if (*mask & CWCursor)
570 *mask &= ~CWCursor; /* Handled by the cursor code */
573 /** Change the window attributes of \a pWindow. */
574 Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
576 ScreenPtr pScreen = pWindow->drawable.pScreen;
577 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
578 Bool ret = TRUE;
579 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
580 XSetWindowAttributes attribs;
582 DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
583 #if 0
584 if (pScreen->ChangeWindowAttributes)
585 ret = pScreen->ChangeWindowAttributes(pWindow, mask);
586 #endif
588 /* Change window attribs on back-end server */
589 dmxDoChangeWindowAttributes(pWindow, &mask, &attribs);
591 /* Save mask for lazy window creation optimization */
592 pWinPriv->attribMask |= mask;
594 if (mask && pWinPriv->window) {
595 XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window,
596 mask, &attribs);
597 dmxSync(dmxScreen, False);
600 DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
601 pScreen);
603 return ret;
606 /** Realize \a pWindow on the back-end server. If the lazy window
607 * creation optimization is enabled, the window is only realized when
608 * it at least partially overlaps the screen. */
609 Bool dmxRealizeWindow(WindowPtr pWindow)
611 ScreenPtr pScreen = pWindow->drawable.pScreen;
612 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
613 Bool ret = TRUE;
614 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
616 DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
617 #if 0
618 if (pScreen->RealizeWindow)
619 ret = pScreen->RealizeWindow(pWindow);
620 #endif
622 /* Determine if the window is completely off the visible portion of
623 the screen */
624 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
626 /* If the window hasn't been created and it's not offscreen, then
627 create it */
628 if (!pWinPriv->window && !pWinPriv->offscreen) {
629 dmxCreateAndRealizeWindow(pWindow, FALSE);
632 if (pWinPriv->window) {
633 /* Realize window on back-end server */
634 XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
635 dmxSync(dmxScreen, False);
638 /* Let the other functions know that the window is now mapped */
639 pWinPriv->mapped = TRUE;
641 DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
643 dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow);
644 return ret;
647 /** Unrealize \a pWindow on the back-end server. */
648 Bool dmxUnrealizeWindow(WindowPtr pWindow)
650 ScreenPtr pScreen = pWindow->drawable.pScreen;
651 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
652 Bool ret = TRUE;
653 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
655 DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
656 #if 0
657 if (pScreen->UnrealizeWindow)
658 ret = pScreen->UnrealizeWindow(pWindow);
659 #endif
661 if (pWinPriv->window) {
662 /* Unrealize window on back-end server */
663 XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
664 dmxSync(dmxScreen, False);
667 /* When unrealized (i.e., unmapped), the window is always considered
668 off of the visible portion of the screen */
669 pWinPriv->offscreen = TRUE;
670 pWinPriv->mapped = FALSE;
672 #ifdef GLXEXT
673 if (pWinPriv->swapGroup && pWinPriv->windowUnmapped)
674 pWinPriv->windowUnmapped(pWindow);
675 #endif
677 DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
679 dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow);
680 return ret;
683 static void dmxDoRestackWindow(WindowPtr pWindow)
685 ScreenPtr pScreen = pWindow->drawable.pScreen;
686 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
687 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
688 WindowPtr pNextSib = pWindow->nextSib;
689 unsigned int m;
690 XWindowChanges c;
692 if (pNextSib == NullWindow) {
693 /* Window is at the bottom of the stack */
694 m = CWStackMode;
695 c.sibling = (Window)0;
696 c.stack_mode = Below;
697 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
698 } else {
699 /* Window is not at the bottom of the stack */
700 dmxWinPrivPtr pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
702 /* Handle case where siblings have not yet been created due to
703 lazy window creation optimization by first finding the next
704 sibling in the sibling list that has been created (if any)
705 and then putting the current window just above that sibling,
706 and if no next siblings have been created yet, then put it at
707 the bottom of the stack (since it might have a previous
708 sibling that should be above it). */
709 while (!pNextSibPriv->window) {
710 pNextSib = pNextSib->nextSib;
711 if (pNextSib == NullWindow) {
712 /* Window is at the bottom of the stack */
713 m = CWStackMode;
714 c.sibling = (Window)0;
715 c.stack_mode = Below;
716 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
717 return;
719 pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
722 m = CWStackMode | CWSibling;
723 c.sibling = pNextSibPriv->window;
724 c.stack_mode = Above;
725 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
729 /** Handle window restacking. The actual restacking occurs in
730 * #dmxDoRestackWindow(). */
731 void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib)
733 ScreenPtr pScreen = pWindow->drawable.pScreen;
734 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
735 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
737 DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
738 #if 0
739 if (pScreen->RestackWindow)
740 pScreen->RestackWindow(pWindow, pOldNextSib);
741 #endif
743 if (pOldNextSib != pWindow->nextSib) {
744 /* Track restacking for lazy window creation optimization */
745 pWinPriv->restacked = TRUE;
747 /* Restack window on back-end server */
748 if (pWinPriv->window) {
749 dmxDoRestackWindow(pWindow);
750 dmxSync(dmxScreen, False);
754 DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
755 dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow);
758 static Bool dmxWindowExposurePredicate(Display *dpy, XEvent *ev, XPointer ptr)
760 return (ev->type == Expose && ev->xexpose.window == *(Window *)ptr);
763 /** Handle exposures on \a pWindow. Since window exposures are handled
764 * in DMX, the events that are generated by the back-end server are
765 * redundant, so we eat them here. */
766 void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn,
767 RegionPtr other_exposed)
769 ScreenPtr pScreen = pWindow->drawable.pScreen;
770 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
771 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
772 XEvent ev;
774 DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
776 dmxSync(dmxScreen, False);
778 if (pWinPriv->window) {
779 while (XCheckIfEvent(dmxScreen->beDisplay, &ev,
780 dmxWindowExposurePredicate,
781 (XPointer)&pWinPriv->window)) {
782 /* Handle expose events -- this should not be necessary
783 since the base window in which the root window was
784 created is guaranteed to be on top (override_redirect),
785 so we should just swallow these events. If for some
786 reason the window is not on top, then we'd need to
787 collect these events and send them to the client later
788 (e.g., during the block handler as Xnest does). */
792 #if 1
793 if (pScreen->WindowExposures)
794 pScreen->WindowExposures(pWindow, prgn, other_exposed);
795 #endif
796 DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
799 /** Paint background of \a pWindow in \a pRegion. */
800 void dmxPaintWindowBackground(WindowPtr pWindow, RegionPtr pRegion, int what)
802 ScreenPtr pScreen = pWindow->drawable.pScreen;
803 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
804 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
805 BoxPtr pBox;
806 int nBox;
808 DMX_UNWRAP(PaintWindowBackground, dmxScreen, pScreen);
809 #if 0
810 if (pScreen->PaintWindowBackground)
811 pScreen->PaintWindowBackground(pWindow, pRegion, what);
812 #endif
814 if (pWinPriv->window) {
815 /* Paint window background on back-end server */
816 pBox = REGION_RECTS(pRegion);
817 nBox = REGION_NUM_RECTS(pRegion);
818 while (nBox--) {
819 XClearArea(dmxScreen->beDisplay, pWinPriv->window,
820 pBox->x1 - pWindow->drawable.x,
821 pBox->y1 - pWindow->drawable.y,
822 pBox->x2 - pBox->x1,
823 pBox->y2 - pBox->y1,
824 False);
825 pBox++;
827 dmxSync(dmxScreen, False);
830 DMX_WRAP(PaintWindowBackground, dmxPaintWindowBackground, dmxScreen, pScreen);
833 /** Paint window border for \a pWindow in \a pRegion. */
834 void dmxPaintWindowBorder(WindowPtr pWindow, RegionPtr pRegion, int what)
836 ScreenPtr pScreen = pWindow->drawable.pScreen;
837 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
839 DMX_UNWRAP(PaintWindowBorder, dmxScreen, pScreen);
840 #if 0
841 if (pScreen->PaintWindowBorder)
842 pScreen->PaintWindowBorder(pWindow, pRegion, what);
843 #endif
845 /* Paint window border on back-end server */
847 DMX_WRAP(PaintWindowBorder, dmxPaintWindowBorder, dmxScreen, pScreen);
850 /** Move \a pWindow on the back-end server. Determine whether or not it
851 * is on or offscreen, and realize it if it is newly on screen and the
852 * lazy window creation optimization is enabled. */
853 void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
855 ScreenPtr pScreen = pWindow->drawable.pScreen;
856 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
857 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
858 unsigned int m;
859 XWindowChanges c;
861 DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
862 #if 0
863 if (pScreen->CopyWindow)
864 pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
865 #endif
867 /* Determine if the window is completely off the visible portion of
868 the screen */
869 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
871 /* If the window is now on-screen and it is mapped and it has not
872 been created yet, create it and map it */
873 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
874 dmxCreateAndRealizeWindow(pWindow, TRUE);
875 } else if (pWinPriv->window) {
876 /* Move window on back-end server */
877 m = CWX | CWY | CWWidth | CWHeight;
878 c.x = pWindow->origin.x - wBorderWidth(pWindow);
879 c.y = pWindow->origin.y - wBorderWidth(pWindow);
880 c.width = pWindow->drawable.width;
881 c.height = pWindow->drawable.height;
883 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
884 dmxSync(dmxScreen, False);
887 DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
888 dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow);
891 /** Resize \a pWindow on the back-end server. Determine whether or not
892 * it is on or offscreen, and realize it if it is newly on screen and
893 * the lazy window creation optimization is enabled. */
894 void dmxResizeWindow(WindowPtr pWindow, int x, int y,
895 unsigned int w, unsigned int h, WindowPtr pSib)
897 ScreenPtr pScreen = pWindow->drawable.pScreen;
898 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
899 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
900 dmxWinPrivPtr pSibPriv;
901 unsigned int m;
902 XWindowChanges c;
904 if (pSib)
905 pSibPriv = DMX_GET_WINDOW_PRIV(pSib);
907 DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
908 #if 1
909 if (pScreen->ResizeWindow)
910 pScreen->ResizeWindow(pWindow, x, y, w, h, pSib);
911 #endif
913 /* Determine if the window is completely off the visible portion of
914 the screen */
915 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
917 /* If the window is now on-screen and it is mapped and it has not
918 been created yet, create it and map it */
919 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
920 dmxCreateAndRealizeWindow(pWindow, TRUE);
921 } else if (pWinPriv->window) {
922 /* Handle resizing on back-end server */
923 m = CWX | CWY | CWWidth | CWHeight;
924 c.x = pWindow->origin.x - wBorderWidth(pWindow);
925 c.y = pWindow->origin.y - wBorderWidth(pWindow);
926 c.width = pWindow->drawable.width;
927 c.height = pWindow->drawable.height;
929 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
930 dmxSync(dmxScreen, False);
933 DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
934 dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow);
937 /** Reparent \a pWindow on the back-end server. */
938 void dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent)
940 ScreenPtr pScreen = pWindow->drawable.pScreen;
941 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
942 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
943 dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
945 DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
946 #if 0
947 if (pScreen->ReparentWindow)
948 pScreen->ReparentWindow(pWindow, pPriorParent);
949 #endif
951 if (pWinPriv->window) {
952 if (!pParentPriv->window) {
953 dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
956 /* Handle reparenting on back-end server */
957 XReparentWindow(dmxScreen->beDisplay, pWinPriv->window,
958 pParentPriv->window,
959 pWindow->origin.x - wBorderWidth(pWindow),
960 pWindow->origin.x - wBorderWidth(pWindow));
961 dmxSync(dmxScreen, False);
964 DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
965 dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow);
968 /** Change border width for \a pWindow to \a width pixels. */
969 void dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width)
971 ScreenPtr pScreen = pWindow->drawable.pScreen;
972 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
973 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
974 unsigned int m;
975 XWindowChanges c;
977 DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
978 #if 1
979 if (pScreen->ChangeBorderWidth)
980 pScreen->ChangeBorderWidth(pWindow, width);
981 #endif
983 /* NOTE: Do we need to check for on/off screen here? */
985 if (pWinPriv->window) {
986 /* Handle border width change on back-end server */
987 m = CWBorderWidth;
988 c.border_width = width;
990 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
991 dmxSync(dmxScreen, False);
994 DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
997 #ifdef SHAPE
998 static void dmxDoSetShape(WindowPtr pWindow)
1000 ScreenPtr pScreen = pWindow->drawable.pScreen;
1001 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1002 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
1003 int nBox;
1004 BoxPtr pBox;
1005 int nRect;
1006 XRectangle *pRect;
1007 XRectangle *pRectFirst;
1009 /* First, set the bounding shape */
1010 if (wBoundingShape(pWindow)) {
1011 pBox = REGION_RECTS(wBoundingShape(pWindow));
1012 nRect = nBox = REGION_NUM_RECTS(wBoundingShape(pWindow));
1013 pRectFirst = pRect = xalloc(nRect * sizeof(*pRect));
1014 while (nBox--) {
1015 pRect->x = pBox->x1;
1016 pRect->y = pBox->y1;
1017 pRect->width = pBox->x2 - pBox->x1;
1018 pRect->height = pBox->y2 - pBox->y1;
1019 pBox++;
1020 pRect++;
1022 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
1023 ShapeBounding, 0, 0,
1024 pRectFirst, nRect,
1025 ShapeSet, YXBanded);
1026 xfree(pRectFirst);
1027 } else {
1028 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
1029 ShapeBounding, 0, 0, None, ShapeSet);
1032 /* Next, set the clip shape */
1033 if (wClipShape(pWindow)) {
1034 pBox = REGION_RECTS(wClipShape(pWindow));
1035 nRect = nBox = REGION_NUM_RECTS(wClipShape(pWindow));
1036 pRectFirst = pRect = xalloc(nRect * sizeof(*pRect));
1037 while (nBox--) {
1038 pRect->x = pBox->x1;
1039 pRect->y = pBox->y1;
1040 pRect->width = pBox->x2 - pBox->x1;
1041 pRect->height = pBox->y2 - pBox->y1;
1042 pBox++;
1043 pRect++;
1045 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
1046 ShapeClip, 0, 0,
1047 pRectFirst, nRect,
1048 ShapeSet, YXBanded);
1049 xfree(pRectFirst);
1050 } else {
1051 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
1052 ShapeClip, 0, 0, None, ShapeSet);
1055 if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) {
1056 ErrorF("Input selected for window %x on Screen %d\n",
1057 (unsigned int)pWinPriv->window, pScreen->myNum);
1061 /** Set shape of \a pWindow on the back-end server. */
1062 void dmxSetShape(WindowPtr pWindow)
1064 ScreenPtr pScreen = pWindow->drawable.pScreen;
1065 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1066 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
1068 DMX_UNWRAP(SetShape, dmxScreen, pScreen);
1069 #if 1
1070 if (pScreen->SetShape)
1071 pScreen->SetShape(pWindow);
1072 #endif
1074 if (pWinPriv->window) {
1075 /* Handle setting the current shape on the back-end server */
1076 dmxDoSetShape(pWindow);
1077 dmxSync(dmxScreen, False);
1078 } else {
1079 pWinPriv->isShaped = TRUE;
1082 DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
1084 #endif