2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
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
30 * Kevin E. Martin <kem@redhat.com>
35 * This file provides support for window-related functions. */
37 #ifdef HAVE_DMX_CONFIG_H
38 #include <dmx-config.h>
43 #include "dmxwindow.h"
44 #include "dmxpixmap.h"
46 #include "dmxvisual.h"
48 #include "dmxextension.h"
51 #include "windowstr.h"
53 static void dmxDoRestackWindow(WindowPtr pWindow
);
54 static void dmxDoChangeWindowAttributes(WindowPtr pWindow
,
56 XSetWindowAttributes
* attribs
);
58 static void dmxDoSetShape(WindowPtr pWindow
);
60 /** Initialize the private area for the window functions. */
62 dmxInitWindow(ScreenPtr pScreen
)
64 if (!dixRegisterPrivateKey
65 (&dmxWinPrivateKeyRec
, PRIVATE_WINDOW
, sizeof(dmxWinPrivRec
)))
72 dmxCreateRootWindow(WindowPtr pWindow
)
74 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
75 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
76 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
80 XSetWindowAttributes attribs
;
82 dmxColormapPrivPtr pCmapPriv
;
84 /* Create root window */
86 parent
= dmxScreen
->scrnWin
; /* This is our "Screen" window */
87 visual
= dmxScreen
->beVisuals
[dmxScreen
->beDefVisualIndex
].visual
;
89 dixLookupResourceByType((pointer
*) &pCmap
, wColormap(pWindow
),
90 RT_COLORMAP
, NullClient
, DixUnknownAccess
);
91 pCmapPriv
= DMX_GET_COLORMAP_PRIV(pCmap
);
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;
99 /* Incorporate new attributes, if needed */
100 if (pWinPriv
->attribMask
) {
101 dmxDoChangeWindowAttributes(pWindow
, &pWinPriv
->attribMask
, &attribs
);
102 mask
|= pWinPriv
->attribMask
;
105 return XCreateWindow(dmxScreen
->beDisplay
,
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
);
116 /** Change the location and size of the "screen" window. Called from
117 * dmxextension.c dmxConfigureScreenWindow(). */
119 dmxResizeScreenWindow(ScreenPtr pScreen
, int x
, int y
, int w
, int h
)
121 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
125 if (!dmxScreen
->beDisplay
)
128 /* Handle resizing on back-end server */
129 m
= CWX
| CWY
| CWWidth
| CWHeight
;
135 XConfigureWindow(dmxScreen
->beDisplay
, dmxScreen
->scrnWin
, m
, &c
);
136 dmxSync(dmxScreen
, False
);
139 /** Change the location and size of the "root" window. Called from
140 * #dmxCreateWindow. */
142 dmxResizeRootWindow(WindowPtr pRoot
, int x
, int y
, int w
, int h
)
144 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pRoot
->drawable
.pScreen
->myNum
];
145 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pRoot
);
149 /* Handle resizing on back-end server */
150 if (dmxScreen
->beDisplay
) {
151 m
= CWX
| CWY
| CWWidth
| CWHeight
;
154 c
.width
= (w
> 0) ? w
: 1;
155 c
.height
= (h
> 0) ? h
: 1;
157 XConfigureWindow(dmxScreen
->beDisplay
, pWinPriv
->window
, m
, &c
);
160 if (w
== 0 || h
== 0) {
161 if (pWinPriv
->mapped
) {
162 if (dmxScreen
->beDisplay
)
163 XUnmapWindow(dmxScreen
->beDisplay
, pWinPriv
->window
);
164 pWinPriv
->mapped
= FALSE
;
167 else if (!pWinPriv
->mapped
) {
168 if (dmxScreen
->beDisplay
)
169 XMapWindow(dmxScreen
->beDisplay
, pWinPriv
->window
);
170 pWinPriv
->mapped
= TRUE
;
173 if (dmxScreen
->beDisplay
)
174 dmxSync(dmxScreen
, False
);
178 dmxGetDefaultWindowAttributes(WindowPtr pWindow
,
179 Colormap
* cmap
, Visual
** visual
)
181 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
183 if (pWindow
->drawable
.class != InputOnly
&&
185 pWindow
->optional
->visual
!= wVisual(pWindow
->parent
)) {
187 /* Find the matching visual */
188 *visual
= dmxLookupVisualFromID(pScreen
, wVisual(pWindow
));
190 /* Handle optional colormaps */
191 if (pWindow
->optional
->colormap
) {
193 dmxColormapPrivPtr pCmapPriv
;
195 dixLookupResourceByType((pointer
*) &pCmap
, wColormap(pWindow
),
196 RT_COLORMAP
, NullClient
, DixUnknownAccess
);
197 pCmapPriv
= DMX_GET_COLORMAP_PRIV(pCmap
);
198 *cmap
= pCmapPriv
->cmap
;
201 *cmap
= dmxColormapFromDefaultVisual(pScreen
, *visual
);
205 *visual
= CopyFromParent
;
206 *cmap
= (Colormap
) 0;
211 dmxCreateNonRootWindow(WindowPtr pWindow
)
213 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
214 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
215 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
217 unsigned long mask
= 0L;
218 XSetWindowAttributes attribs
;
219 dmxWinPrivPtr pParentPriv
= DMX_GET_WINDOW_PRIV(pWindow
->parent
);
221 /* Create window on back-end server */
223 parent
= pParentPriv
->window
;
225 /* The parent won't exist if this call to CreateNonRootWindow came
226 from ReparentWindow and the grandparent window has not yet been
229 dmxCreateAndRealizeWindow(pWindow
->parent
, FALSE
);
230 parent
= pParentPriv
->window
;
233 /* Incorporate new attributes, if needed */
234 if (pWinPriv
->attribMask
) {
235 dmxDoChangeWindowAttributes(pWindow
, &pWinPriv
->attribMask
, &attribs
);
236 mask
|= pWinPriv
->attribMask
;
239 /* Add in default attributes */
240 if (pWindow
->drawable
.class != InputOnly
) {
241 mask
|= CWBackingStore
;
242 attribs
.backing_store
= NotUseful
;
244 if (!(mask
& CWColormap
) && pWinPriv
->cmap
) {
246 attribs
.colormap
= pWinPriv
->cmap
;
247 if (!(mask
& CWBorderPixel
)) {
248 mask
|= CWBorderPixel
;
249 attribs
.border_pixel
= 0;
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
);
259 return XCreateWindow(dmxScreen
->beDisplay
,
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
);
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. */
281 dmxCreateAndRealizeWindow(WindowPtr pWindow
, Bool doSync
)
283 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
284 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
285 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
287 if (!dmxScreen
->beDisplay
)
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
);
300 dmxSync(dmxScreen
, False
);
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(). */
308 dmxCreateWindow(WindowPtr pWindow
)
310 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
311 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
312 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
315 DMX_UNWRAP(CreateWindow
, dmxScreen
, pScreen
);
317 if (pScreen
->CreateWindow
)
318 ret
= pScreen
->CreateWindow(pWindow
);
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
;
330 pWinPriv
->swapGroup
= NULL
;
331 pWinPriv
->barrier
= 0;
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
,
347 dmxScreen
->rootWidth
,
348 dmxScreen
->rootHeight
);
349 dmxUpdateScreenResources(screenInfo
.screens
[dmxScreen
->index
],
352 dmxScreen
->rootWidth
,
353 dmxScreen
->rootHeight
);
354 pWindow
->origin
.x
= dmxScreen
->rootX
;
355 pWindow
->origin
.y
= dmxScreen
->rootY
;
359 dmxGetDefaultWindowAttributes(pWindow
,
360 &pWinPriv
->cmap
, &pWinPriv
->visual
);
362 if (dmxLazyWindowCreation
) {
363 /* Save parent's visual for use later */
364 if (pWinPriv
->visual
== CopyFromParent
)
366 dmxLookupVisualFromID(pScreen
,
367 wVisual(pWindow
->parent
));
370 pWinPriv
->window
= dmxCreateNonRootWindow(pWindow
);
374 dmxSync(dmxScreen
, False
);
377 DMX_WRAP(CreateWindow
, dmxCreateWindow
, dmxScreen
, pScreen
);
382 /** Destroy \a pWindow on the back-end server. */
384 dmxBEDestroyWindow(WindowPtr pWindow
)
386 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
387 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
388 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
390 if (pWinPriv
->window
) {
391 XDestroyWindow(dmxScreen
->beDisplay
, pWinPriv
->window
);
392 pWinPriv
->window
= (Window
) 0;
399 /** Destroy \a pWindow on the back-end server. If any RENDER pictures
400 were created, destroy them as well. */
402 dmxDestroyWindow(WindowPtr pWindow
)
404 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
405 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
407 Bool needSync
= FALSE
;
410 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
413 DMX_UNWRAP(DestroyWindow
, dmxScreen
, pScreen
);
415 /* Destroy any picture list associated with this window */
416 needSync
|= dmxDestroyPictureList(pWindow
);
418 /* Destroy window on back-end server */
419 needSync
|= dmxBEDestroyWindow(pWindow
);
421 dmxSync(dmxScreen
, FALSE
);
424 if (pWinPriv
->swapGroup
&& pWinPriv
->windowDestroyed
)
425 pWinPriv
->windowDestroyed(pWindow
);
428 if (pScreen
->DestroyWindow
)
429 ret
= pScreen
->DestroyWindow(pWindow
);
431 DMX_WRAP(DestroyWindow
, dmxDestroyWindow
, dmxScreen
, pScreen
);
436 /** Change the position of \a pWindow to be \a x, \a y. */
438 dmxPositionWindow(WindowPtr pWindow
, int x
, int y
)
440 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
441 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
443 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
447 DMX_UNWRAP(PositionWindow
, dmxScreen
, pScreen
);
449 if (pScreen
->PositionWindow
)
450 ret
= pScreen
->PositionWindow(pWindow
, x
, y
);
453 /* Determine if the window is completely off the visible portion of
455 pWinPriv
->offscreen
= DMX_WINDOW_OFFSCREEN(pWindow
);
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
);
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
) {
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
);
484 dmxDoChangeWindowAttributes(WindowPtr pWindow
,
485 unsigned long *mask
, XSetWindowAttributes
* attribs
)
487 dmxPixPrivPtr pPixPriv
;
489 if (*mask
& CWBackPixmap
) {
490 switch (pWindow
->backgroundState
) {
492 attribs
->background_pixmap
= None
;
496 attribs
->background_pixmap
= ParentRelative
;
499 case BackgroundPixmap
:
500 pPixPriv
= DMX_GET_PIXMAP_PRIV(pWindow
->background
.pixmap
);
501 attribs
->background_pixmap
= pPixPriv
->pixmap
;
504 case BackgroundPixel
:
505 *mask
&= ~CWBackPixmap
;
510 if (*mask
& CWBackPixel
) {
511 if (pWindow
->backgroundState
== BackgroundPixel
)
512 attribs
->background_pixel
= pWindow
->background
.pixel
;
514 *mask
&= ~CWBackPixel
;
517 if (*mask
& CWBorderPixmap
) {
518 if (pWindow
->borderIsPixel
)
519 *mask
&= ~CWBorderPixmap
;
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
;
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
) {
562 dmxColormapPrivPtr pCmapPriv
;
564 dixLookupResourceByType((pointer
*) &pCmap
, wColormap(pWindow
),
565 RT_COLORMAP
, NullClient
, DixUnknownAccess
);
566 pCmapPriv
= DMX_GET_COLORMAP_PRIV(pCmap
);
567 attribs
->colormap
= pCmapPriv
->cmap
;
570 if (*mask
& CWCursor
)
571 *mask
&= ~CWCursor
; /* Handled by the cursor code */
574 /** Change the window attributes of \a pWindow. */
576 dmxChangeWindowAttributes(WindowPtr pWindow
, unsigned long mask
)
578 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
579 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
581 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
582 XSetWindowAttributes attribs
;
584 DMX_UNWRAP(ChangeWindowAttributes
, dmxScreen
, pScreen
);
586 if (pScreen
->ChangeWindowAttributes
)
587 ret
= pScreen
->ChangeWindowAttributes(pWindow
, mask
);
590 /* Change window attribs on back-end server */
591 dmxDoChangeWindowAttributes(pWindow
, &mask
, &attribs
);
593 /* Save mask for lazy window creation optimization */
594 pWinPriv
->attribMask
|= mask
;
596 if (mask
&& pWinPriv
->window
) {
597 XChangeWindowAttributes(dmxScreen
->beDisplay
, pWinPriv
->window
,
599 dmxSync(dmxScreen
, False
);
602 DMX_WRAP(ChangeWindowAttributes
, dmxChangeWindowAttributes
, dmxScreen
,
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. */
612 dmxRealizeWindow(WindowPtr pWindow
)
614 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
615 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
617 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
619 DMX_UNWRAP(RealizeWindow
, dmxScreen
, pScreen
);
621 if (pScreen
->RealizeWindow
)
622 ret
= pScreen
->RealizeWindow(pWindow
);
625 /* Determine if the window is completely off the visible portion of
627 pWinPriv
->offscreen
= DMX_WINDOW_OFFSCREEN(pWindow
);
629 /* If the window hasn't been created and it's not offscreen, then
631 if (!pWinPriv
->window
&& !pWinPriv
->offscreen
) {
632 dmxCreateAndRealizeWindow(pWindow
, FALSE
);
635 if (pWinPriv
->window
) {
636 /* Realize window on back-end server */
637 XMapWindow(dmxScreen
->beDisplay
, pWinPriv
->window
);
638 dmxSync(dmxScreen
, False
);
641 /* Let the other functions know that the window is now mapped */
642 pWinPriv
->mapped
= TRUE
;
644 DMX_WRAP(RealizeWindow
, dmxRealizeWindow
, dmxScreen
, pScreen
);
646 dmxUpdateWindowInfo(DMX_UPDATE_REALIZE
, pWindow
);
650 /** Unrealize \a pWindow on the back-end server. */
652 dmxUnrealizeWindow(WindowPtr pWindow
)
654 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
655 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
657 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
659 DMX_UNWRAP(UnrealizeWindow
, dmxScreen
, pScreen
);
661 if (pScreen
->UnrealizeWindow
)
662 ret
= pScreen
->UnrealizeWindow(pWindow
);
665 if (pWinPriv
->window
) {
666 /* Unrealize window on back-end server */
667 XUnmapWindow(dmxScreen
->beDisplay
, pWinPriv
->window
);
668 dmxSync(dmxScreen
, False
);
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
;
677 if (pWinPriv
->swapGroup
&& pWinPriv
->windowUnmapped
)
678 pWinPriv
->windowUnmapped(pWindow
);
681 DMX_WRAP(UnrealizeWindow
, dmxUnrealizeWindow
, dmxScreen
, pScreen
);
683 dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE
, pWindow
);
688 dmxDoRestackWindow(WindowPtr pWindow
)
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
;
697 if (pNextSib
== NullWindow
) {
698 /* Window is at the bottom of the stack */
700 c
.sibling
= (Window
) 0;
701 c
.stack_mode
= Below
;
702 XConfigureWindow(dmxScreen
->beDisplay
, pWinPriv
->window
, m
, &c
);
705 /* Window is not at the bottom of the stack */
706 dmxWinPrivPtr pNextSibPriv
= DMX_GET_WINDOW_PRIV(pNextSib
);
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 */
720 c
.sibling
= (Window
) 0;
721 c
.stack_mode
= Below
;
722 XConfigureWindow(dmxScreen
->beDisplay
, pWinPriv
->window
, m
, &c
);
725 pNextSibPriv
= DMX_GET_WINDOW_PRIV(pNextSib
);
728 m
= CWStackMode
| CWSibling
;
729 c
.sibling
= pNextSibPriv
->window
;
730 c
.stack_mode
= Above
;
731 XConfigureWindow(dmxScreen
->beDisplay
, pWinPriv
->window
, m
, &c
);
735 /** Handle window restacking. The actual restacking occurs in
736 * #dmxDoRestackWindow(). */
738 dmxRestackWindow(WindowPtr pWindow
, WindowPtr pOldNextSib
)
740 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
741 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
742 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
744 DMX_UNWRAP(RestackWindow
, dmxScreen
, pScreen
);
746 if (pScreen
->RestackWindow
)
747 pScreen
->RestackWindow(pWindow
, pOldNextSib
);
750 if (pOldNextSib
!= pWindow
->nextSib
) {
751 /* Track restacking for lazy window creation optimization */
752 pWinPriv
->restacked
= TRUE
;
754 /* Restack window on back-end server */
755 if (pWinPriv
->window
) {
756 dmxDoRestackWindow(pWindow
);
757 dmxSync(dmxScreen
, False
);
761 DMX_WRAP(RestackWindow
, dmxRestackWindow
, dmxScreen
, pScreen
);
762 dmxUpdateWindowInfo(DMX_UPDATE_RESTACK
, pWindow
);
766 dmxWindowExposurePredicate(Display
* dpy
, XEvent
* ev
, XPointer ptr
)
768 return (ev
->type
== Expose
&& ev
->xexpose
.window
== *(Window
*) ptr
);
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. */
775 dmxWindowExposures(WindowPtr pWindow
, RegionPtr prgn
, RegionPtr other_exposed
)
777 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
778 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
779 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
782 DMX_UNWRAP(WindowExposures
, dmxScreen
, pScreen
);
784 dmxSync(dmxScreen
, False
);
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). */
801 if (pScreen
->WindowExposures
)
802 pScreen
->WindowExposures(pWindow
, prgn
, other_exposed
);
804 DMX_WRAP(WindowExposures
, dmxWindowExposures
, dmxScreen
, pScreen
);
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. */
811 dmxCopyWindow(WindowPtr pWindow
, DDXPointRec ptOldOrg
, RegionPtr prgnSrc
)
813 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
814 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
815 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
819 DMX_UNWRAP(CopyWindow
, dmxScreen
, pScreen
);
821 if (pScreen
->CopyWindow
)
822 pScreen
->CopyWindow(pWindow
, ptOldOrg
, prgnSrc
);
825 /* Determine if the window is completely off the visible portion of
827 pWinPriv
->offscreen
= DMX_WINDOW_OFFSCREEN(pWindow
);
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
);
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
;
842 XConfigureWindow(dmxScreen
->beDisplay
, pWinPriv
->window
, m
, &c
);
843 dmxSync(dmxScreen
, False
);
846 DMX_WRAP(CopyWindow
, dmxCopyWindow
, dmxScreen
, pScreen
);
847 dmxUpdateWindowInfo(DMX_UPDATE_COPY
, pWindow
);
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. */
854 dmxResizeWindow(WindowPtr pWindow
, int x
, int y
,
855 unsigned int w
, unsigned int h
, WindowPtr pSib
)
857 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
858 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
859 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
860 dmxWinPrivPtr pSibPriv
;
865 pSibPriv
= DMX_GET_WINDOW_PRIV(pSib
);
867 DMX_UNWRAP(ResizeWindow
, dmxScreen
, pScreen
);
869 if (pScreen
->ResizeWindow
)
870 pScreen
->ResizeWindow(pWindow
, x
, y
, w
, h
, pSib
);
873 /* Determine if the window is completely off the visible portion of
875 pWinPriv
->offscreen
= DMX_WINDOW_OFFSCREEN(pWindow
);
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
);
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
;
890 XConfigureWindow(dmxScreen
->beDisplay
, pWinPriv
->window
, m
, &c
);
891 dmxSync(dmxScreen
, False
);
894 DMX_WRAP(ResizeWindow
, dmxResizeWindow
, dmxScreen
, pScreen
);
895 dmxUpdateWindowInfo(DMX_UPDATE_RESIZE
, pWindow
);
898 /** Reparent \a pWindow on the back-end server. */
900 dmxReparentWindow(WindowPtr pWindow
, WindowPtr pPriorParent
)
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
);
907 DMX_UNWRAP(ReparentWindow
, dmxScreen
, pScreen
);
909 if (pScreen
->ReparentWindow
)
910 pScreen
->ReparentWindow(pWindow
, pPriorParent
);
913 if (pWinPriv
->window
) {
914 if (!pParentPriv
->window
) {
915 dmxCreateAndRealizeWindow(pWindow
->parent
, FALSE
);
918 /* Handle reparenting on back-end server */
919 XReparentWindow(dmxScreen
->beDisplay
, pWinPriv
->window
,
921 pWindow
->origin
.x
- wBorderWidth(pWindow
),
922 pWindow
->origin
.x
- wBorderWidth(pWindow
));
923 dmxSync(dmxScreen
, False
);
926 DMX_WRAP(ReparentWindow
, dmxReparentWindow
, dmxScreen
, pScreen
);
927 dmxUpdateWindowInfo(DMX_UPDATE_REPARENT
, pWindow
);
930 /** Change border width for \a pWindow to \a width pixels. */
932 dmxChangeBorderWidth(WindowPtr pWindow
, unsigned int width
)
934 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
935 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
936 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
940 DMX_UNWRAP(ChangeBorderWidth
, dmxScreen
, pScreen
);
942 if (pScreen
->ChangeBorderWidth
)
943 pScreen
->ChangeBorderWidth(pWindow
, width
);
946 /* NOTE: Do we need to check for on/off screen here? */
948 if (pWinPriv
->window
) {
949 /* Handle border width change on back-end server */
951 c
.border_width
= width
;
953 XConfigureWindow(dmxScreen
->beDisplay
, pWinPriv
->window
, m
, &c
);
954 dmxSync(dmxScreen
, False
);
957 DMX_WRAP(ChangeBorderWidth
, dmxChangeBorderWidth
, dmxScreen
, pScreen
);
961 dmxDoSetShape(WindowPtr pWindow
)
963 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
964 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
965 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
970 XRectangle
*pRectFirst
;
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
));
980 pRect
->width
= pBox
->x2
- pBox
->x1
;
981 pRect
->height
= pBox
->y2
- pBox
->y1
;
985 XShapeCombineRectangles(dmxScreen
->beDisplay
, pWinPriv
->window
,
987 pRectFirst
, nRect
, ShapeSet
, YXBanded
);
991 XShapeCombineMask(dmxScreen
->beDisplay
, pWinPriv
->window
,
992 ShapeBounding
, 0, 0, None
, ShapeSet
);
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
));
1001 pRect
->x
= pBox
->x1
;
1002 pRect
->y
= pBox
->y1
;
1003 pRect
->width
= pBox
->x2
- pBox
->x1
;
1004 pRect
->height
= pBox
->y2
- pBox
->y1
;
1008 XShapeCombineRectangles(dmxScreen
->beDisplay
, pWinPriv
->window
,
1010 pRectFirst
, nRect
, ShapeSet
, YXBanded
);
1014 XShapeCombineMask(dmxScreen
->beDisplay
, pWinPriv
->window
,
1015 ShapeClip
, 0, 0, None
, ShapeSet
);
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
);
1024 /** Set shape of \a pWindow on the back-end server. */
1026 dmxSetShape(WindowPtr pWindow
, int kind
)
1028 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1029 DMXScreenInfo
*dmxScreen
= &dmxScreens
[pScreen
->myNum
];
1030 dmxWinPrivPtr pWinPriv
= DMX_GET_WINDOW_PRIV(pWindow
);
1032 DMX_UNWRAP(SetShape
, dmxScreen
, pScreen
);
1034 if (pScreen
->SetShape
)
1035 pScreen
->SetShape(pWindow
, kind
);
1038 if (pWinPriv
->window
) {
1039 /* Handle setting the current shape on the back-end server */
1040 dmxDoSetShape(pWindow
);
1041 dmxSync(dmxScreen
, False
);
1044 pWinPriv
->isShaped
= TRUE
;
1047 DMX_WRAP(SetShape
, dmxSetShape
, dmxScreen
, pScreen
);