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
53 static void dmxDoRestackWindow(WindowPtr pWindow);
54 static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
55 unsigned long *mask,
56 XSetWindowAttributes * attribs);
57
58 static void dmxDoSetShape(WindowPtr pWindow);
59
60 /** Initialize the private area for the window functions. */
61 Bool
dmxInitWindow(ScreenPtr pScreen)62 dmxInitWindow(ScreenPtr pScreen)
63 {
64 if (!dixRegisterPrivateKey
65 (&dmxWinPrivateKeyRec, PRIVATE_WINDOW, sizeof(dmxWinPrivRec)))
66 return FALSE;
67
68 return TRUE;
69 }
70
71 Window
dmxCreateRootWindow(WindowPtr pWindow)72 dmxCreateRootWindow(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((void **) &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(). */
118 void
dmxResizeScreenWindow(ScreenPtr pScreen,int x,int y,int w,int h)119 dmxResizeScreenWindow(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. */
141 void
dmxResizeRootWindow(WindowPtr pRoot,int x,int y,int w,int h)142 dmxResizeRootWindow(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
177 void
dmxGetDefaultWindowAttributes(WindowPtr pWindow,Colormap * cmap,Visual ** visual)178 dmxGetDefaultWindowAttributes(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((void **) &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
210 static Window
dmxCreateNonRootWindow(WindowPtr pWindow)211 dmxCreateNonRootWindow(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. */
280 void
dmxCreateAndRealizeWindow(WindowPtr pWindow,Bool doSync)281 dmxCreateAndRealizeWindow(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(). */
307 Bool
dmxCreateWindow(WindowPtr pWindow)308 dmxCreateWindow(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. */
383 Bool
dmxBEDestroyWindow(WindowPtr pWindow)384 dmxBEDestroyWindow(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. */
401 Bool
dmxDestroyWindow(WindowPtr pWindow)402 dmxDestroyWindow(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. */
437 Bool
dmxPositionWindow(WindowPtr pWindow,int x,int y)438 dmxPositionWindow(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
483 static void
dmxDoChangeWindowAttributes(WindowPtr pWindow,unsigned long * mask,XSetWindowAttributes * attribs)484 dmxDoChangeWindowAttributes(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((void **) &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. */
575 Bool
dmxChangeWindowAttributes(WindowPtr pWindow,unsigned long mask)576 dmxChangeWindowAttributes(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. */
611 Bool
dmxRealizeWindow(WindowPtr pWindow)612 dmxRealizeWindow(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. */
651 Bool
dmxUnrealizeWindow(WindowPtr pWindow)652 dmxUnrealizeWindow(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
687 static void
dmxDoRestackWindow(WindowPtr pWindow)688 dmxDoRestackWindow(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(). */
737 void
dmxRestackWindow(WindowPtr pWindow,WindowPtr pOldNextSib)738 dmxRestackWindow(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
765 static Bool
dmxWindowExposurePredicate(Display * dpy,XEvent * ev,XPointer ptr)766 dmxWindowExposurePredicate(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. */
774 void
dmxWindowExposures(WindowPtr pWindow,RegionPtr prgn)775 dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn)
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);
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. */
810 void
dmxCopyWindow(WindowPtr pWindow,DDXPointRec ptOldOrg,RegionPtr prgnSrc)811 dmxCopyWindow(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. */
853 void
dmxResizeWindow(WindowPtr pWindow,int x,int y,unsigned int w,unsigned int h,WindowPtr pSib)854 dmxResizeWindow(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 unsigned int m;
861 XWindowChanges c;
862
863 DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
864 #if 1
865 if (pScreen->ResizeWindow)
866 pScreen->ResizeWindow(pWindow, x, y, w, h, pSib);
867 #endif
868
869 /* Determine if the window is completely off the visible portion of
870 the screen */
871 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
872
873 /* If the window is now on-screen and it is mapped and it has not
874 been created yet, create it and map it */
875 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
876 dmxCreateAndRealizeWindow(pWindow, TRUE);
877 }
878 else if (pWinPriv->window) {
879 /* Handle resizing on back-end server */
880 m = CWX | CWY | CWWidth | CWHeight;
881 c.x = pWindow->origin.x - wBorderWidth(pWindow);
882 c.y = pWindow->origin.y - wBorderWidth(pWindow);
883 c.width = pWindow->drawable.width;
884 c.height = pWindow->drawable.height;
885
886 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
887 dmxSync(dmxScreen, False);
888 }
889
890 DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
891 dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow);
892 }
893
894 /** Reparent \a pWindow on the back-end server. */
895 void
dmxReparentWindow(WindowPtr pWindow,WindowPtr pPriorParent)896 dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent)
897 {
898 ScreenPtr pScreen = pWindow->drawable.pScreen;
899 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
900 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
901 dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
902
903 DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
904 #if 0
905 if (pScreen->ReparentWindow)
906 pScreen->ReparentWindow(pWindow, pPriorParent);
907 #endif
908
909 if (pWinPriv->window) {
910 if (!pParentPriv->window) {
911 dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
912 }
913
914 /* Handle reparenting on back-end server */
915 XReparentWindow(dmxScreen->beDisplay, pWinPriv->window,
916 pParentPriv->window,
917 pWindow->origin.x - wBorderWidth(pWindow),
918 pWindow->origin.x - wBorderWidth(pWindow));
919 dmxSync(dmxScreen, False);
920 }
921
922 DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
923 dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow);
924 }
925
926 /** Change border width for \a pWindow to \a width pixels. */
927 void
dmxChangeBorderWidth(WindowPtr pWindow,unsigned int width)928 dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width)
929 {
930 ScreenPtr pScreen = pWindow->drawable.pScreen;
931 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
932 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
933 unsigned int m;
934 XWindowChanges c;
935
936 DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
937 #if 1
938 if (pScreen->ChangeBorderWidth)
939 pScreen->ChangeBorderWidth(pWindow, width);
940 #endif
941
942 /* NOTE: Do we need to check for on/off screen here? */
943
944 if (pWinPriv->window) {
945 /* Handle border width change on back-end server */
946 m = CWBorderWidth;
947 c.border_width = width;
948
949 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
950 dmxSync(dmxScreen, False);
951 }
952
953 DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
954 }
955
956 static void
dmxDoSetShape(WindowPtr pWindow)957 dmxDoSetShape(WindowPtr pWindow)
958 {
959 ScreenPtr pScreen = pWindow->drawable.pScreen;
960 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
961 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
962 int nBox;
963 BoxPtr pBox;
964 int nRect;
965 XRectangle *pRect;
966 XRectangle *pRectFirst;
967
968 /* First, set the bounding shape */
969 if (wBoundingShape(pWindow)) {
970 pBox = RegionRects(wBoundingShape(pWindow));
971 nRect = nBox = RegionNumRects(wBoundingShape(pWindow));
972 pRectFirst = pRect = xallocarray(nRect, sizeof(*pRect));
973 while (nBox--) {
974 pRect->x = pBox->x1;
975 pRect->y = pBox->y1;
976 pRect->width = pBox->x2 - pBox->x1;
977 pRect->height = pBox->y2 - pBox->y1;
978 pBox++;
979 pRect++;
980 }
981 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
982 ShapeBounding, 0, 0,
983 pRectFirst, nRect, ShapeSet, YXBanded);
984 free(pRectFirst);
985 }
986 else {
987 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
988 ShapeBounding, 0, 0, None, ShapeSet);
989 }
990
991 /* Next, set the clip shape */
992 if (wClipShape(pWindow)) {
993 pBox = RegionRects(wClipShape(pWindow));
994 nRect = nBox = RegionNumRects(wClipShape(pWindow));
995 pRectFirst = pRect = xallocarray(nRect, sizeof(*pRect));
996 while (nBox--) {
997 pRect->x = pBox->x1;
998 pRect->y = pBox->y1;
999 pRect->width = pBox->x2 - pBox->x1;
1000 pRect->height = pBox->y2 - pBox->y1;
1001 pBox++;
1002 pRect++;
1003 }
1004 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
1005 ShapeClip, 0, 0,
1006 pRectFirst, nRect, ShapeSet, YXBanded);
1007 free(pRectFirst);
1008 }
1009 else {
1010 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
1011 ShapeClip, 0, 0, None, ShapeSet);
1012 }
1013
1014 if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) {
1015 ErrorF("Input selected for window %x on Screen %d\n",
1016 (unsigned int) pWinPriv->window, pScreen->myNum);
1017 }
1018 }
1019
1020 /** Set shape of \a pWindow on the back-end server. */
1021 void
dmxSetShape(WindowPtr pWindow,int kind)1022 dmxSetShape(WindowPtr pWindow, int kind)
1023 {
1024 ScreenPtr pScreen = pWindow->drawable.pScreen;
1025 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1026 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
1027
1028 DMX_UNWRAP(SetShape, dmxScreen, pScreen);
1029 #if 1
1030 if (pScreen->SetShape)
1031 pScreen->SetShape(pWindow, kind);
1032 #endif
1033
1034 if (pWinPriv->window) {
1035 /* Handle setting the current shape on the back-end server */
1036 dmxDoSetShape(pWindow);
1037 dmxSync(dmxScreen, False);
1038 }
1039 else {
1040 pWinPriv->isShaped = TRUE;
1041 }
1042
1043 DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
1044 }
1045