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