diff options
Diffstat (limited to 'nx-X11/programs/Xserver/composite')
-rw-r--r-- | nx-X11/programs/Xserver/composite/.gitignore | 0 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/Imakefile | 29 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compalloc.c | 710 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compext.c | 1063 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compinit.c | 492 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compint.h | 360 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compositeext.h | 44 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compoverlay.c | 178 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compwindow.c | 909 |
9 files changed, 3785 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/composite/.gitignore b/nx-X11/programs/Xserver/composite/.gitignore new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/nx-X11/programs/Xserver/composite/.gitignore diff --git a/nx-X11/programs/Xserver/composite/Imakefile b/nx-X11/programs/Xserver/composite/Imakefile new file mode 100644 index 000000000..cf44ded4a --- /dev/null +++ b/nx-X11/programs/Xserver/composite/Imakefile @@ -0,0 +1,29 @@ +#include <Server.tmpl> + + NULL = + + SRCS = compalloc.c compext.c compinit.c compoverlay.c compwindow.c + + OBJS = compalloc.o compext.o compinit.o compoverlay.o compwindow.o + + INCLUDES = -I../include -I../mi -I../Xext -I../render -I../xfixes \ + -I../damageext -I../miext/damage -I$(EXTINCSRC) \ + -I$(XINCLUDESRC) \ + `pkg-config --cflags-only-I pixman-1` + + LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln + +#if defined(NXAgentServer) && NXAgentServer + NX_DEFINES = -DNXAGENT_SERVER +#endif + + DEFINES = \ + $(NX_DEFINES) \ + $(NULL) + +NormalLibraryTarget(composite,$(OBJS)) +NormalLibraryObjectRule() +LintLibraryTarget(composite,$(SRCS)) +NormalLintTarget($(SRCS)) + +DependTarget() diff --git a/nx-X11/programs/Xserver/composite/compalloc.c b/nx-X11/programs/Xserver/composite/compalloc.c new file mode 100644 index 000000000..22b036265 --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compalloc.c @@ -0,0 +1,710 @@ +/* + * $Id: compalloc.c,v 1.7 2005/07/03 07:37:34 daniels Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "compint.h" + +static void +compScreenUpdate(ScreenPtr pScreen) +{ + compCheckTree(pScreen); + compPaintChildrenToWindow(pScreen, pScreen->root); +} + +static void +compBlockHandler(int i, void *blockData, void *pTimeout, void *pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + CompScreenPtr cs = GetCompScreen(pScreen); + + pScreen->BlockHandler = cs->BlockHandler; + compScreenUpdate(pScreen); + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + /* Next damage will restore the block handler */ + cs->BlockHandler = NULL; +} + +static void +compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + WindowPtr pWin = (WindowPtr) closure; + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + CompWindowPtr cw = GetCompWindow(pWin); + + if (!cs->BlockHandler) { + cs->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = compBlockHandler; + } + cs->damaged = TRUE; + cw->damaged = TRUE; + + /* Mark the ancestors */ + /* We can't do this, Dave. No damagedDescendants support. */ + /* + pWin = pWin->parent; + while (pWin) { + if (pWin->damagedDescendants) + break; + pWin->damagedDescendants = TRUE; + pWin = pWin->parent; + } + */ +} + +static void +compDestroyDamage(DamagePtr pDamage, void *closure) +{ + WindowPtr pWin = (WindowPtr) closure; + CompWindowPtr cw = GetCompWindow(pWin); + + cw->damage = 0; +} + +static Bool +compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if (!pWin->viewable) + return FALSE; + + (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); + (*pScreen->MarkWindow) (pLayerWin->parent); + + *ppLayerWin = pLayerWin; + + return TRUE; +} + +static void +compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures) (pLayerWin->parent); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther); +} + +/* + * Redirect one window for one client + */ +int +compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update) +{ + CompWindowPtr cw = GetCompWindow(pWin); + CompClientWindowPtr ccw; + CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); + WindowPtr pLayerWin; + Bool anyMarked = FALSE; + + if (pWin == cs->pOverlayWin) { + return Success; + } + + if (!pWin->parent) + return BadMatch; + + /* + * Only one Manual update is allowed + */ + if (cw && update == CompositeRedirectManual) + for (ccw = cw->clients; ccw; ccw = ccw->next) + if (ccw->update == CompositeRedirectManual) + return BadAccess; + + /* + * Allocate per-client per-window structure + * The client *could* allocate multiple, but while supported, + * it is not expected to be common + */ + ccw = malloc (sizeof (CompClientWindowRec)); + if (!ccw) + return BadAlloc; + ccw->id = FakeClientID (pClient->index); + ccw->update = update; + /* + * Now make sure there's a per-window structure to hang this from + */ + if (!cw) + { + cw = malloc (sizeof (CompWindowRec)); + if (!cw) + { + free (ccw); + return BadAlloc; + } + cw->damage = DamageCreate (compReportDamage, + compDestroyDamage, + DamageReportNonEmpty, + FALSE, + pWin->drawable.pScreen, + pWin); + if (!cw->damage) + { + free (ccw); + free (cw); + return BadAlloc; + } + + anyMarked = compMarkWindows(pWin, &pLayerWin); + + RegionNull(&cw->borderClip); + cw->update = CompositeRedirectAutomatic; + cw->clients = 0; + cw->oldx = COMP_ORIGIN_INVALID; + cw->oldy = COMP_ORIGIN_INVALID; + cw->damageRegistered = FALSE; + cw->damaged = FALSE; + cw->pOldPixmap = NullPixmap; + FAKE_DIX_SET_WINDOW_PRIVATE(pWin, cw); + } + ccw->next = cw->clients; + cw->clients = ccw; + if (!AddResource (ccw->id, CompositeClientWindowType, pWin)) + return BadAlloc; + if (ccw->update == CompositeRedirectManual) + { + if (!anyMarked) + anyMarked = compMarkWindows(pWin, &pLayerWin); + + if (cw->damageRegistered) { + DamageUnregister (&pWin->drawable, cw->damage); + cw->damageRegistered = FALSE; + } + cw->update = CompositeRedirectManual; + } + else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { + if (!anyMarked) + anyMarked = compMarkWindows(pWin, &pLayerWin); + } + + if (!compCheckRedirect (pWin)) + { + FreeResource (ccw->id, RT_NONE); + return BadAlloc; + } + + if (anyMarked) + compHandleMarkedWindows(pWin, pLayerWin); + + return Success; +} + +void +compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent = pWin->parent; + + if (pParent->drawable.depth == pWin->drawable.depth) { + GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); + int bw = (int) pWin->borderWidth; + int x = bw; + int y = bw; + int w = pWin->drawable.width; + int h = pWin->drawable.height; + + if (pGC) { + ChangeGCVal val; + + val.val = IncludeInferiors; + dixChangeGC(NullClient, pGC, GCSubwindowMode, NULL, &val); + ValidateGC(&pWin->drawable, pGC); + (*pGC->ops->CopyArea) (&pPixmap->drawable, + &pWin->drawable, pGC, x, y, w, h, 0, 0); + FreeScratchGC(pGC); + } + } +} + +/* + * Free one of the per-client per-window resources, clearing + * redirect and the per-window pointer as appropriate + */ +void +compFreeClientWindow (WindowPtr pWin, XID id) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompWindowPtr cw = GetCompWindow (pWin); + CompClientWindowPtr ccw, *prev; + Bool anyMarked = FALSE; + WindowPtr pLayerWin; + PixmapPtr pPixmap = NULL; + + if (!cw) + return; + for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) + { + if (ccw->id == id) + { + *prev = ccw->next; + if (ccw->update == CompositeRedirectManual) + cw->update = CompositeRedirectAutomatic; + free (ccw); + break; + } + } + if (!cw->clients) + { + anyMarked = compMarkWindows(pWin, &pLayerWin); + + if (pWin->redirectDraw != RedirectDrawNone) { + pPixmap = (*pScreen->GetWindowPixmap) (pWin); + compSetParentPixmap(pWin); + } + + if (cw->damage) + DamageDestroy (cw->damage); + + RegionUninit(&cw->borderClip); + + FAKE_DIX_SET_WINDOW_PRIVATE(pWin, NULL); + free (cw); + } + else if (cw->update == CompositeRedirectAutomatic && + !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) + { + anyMarked = compMarkWindows(pWin, &pLayerWin); + + DamageRegister (&pWin->drawable, cw->damage); + cw->damageRegistered = TRUE; + pWin->redirectDraw = RedirectDrawAutomatic; + DamageDamageRegion (&pWin->drawable, &pWin->borderSize); + } + + if (anyMarked) + compHandleMarkedWindows(pWin, pLayerWin); + + if (pPixmap) { + compRestoreWindow(pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + } +} + +/* + * This is easy, just free the appropriate resource. + */ + +int +compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update) +{ + CompWindowPtr cw = GetCompWindow (pWin); + CompClientWindowPtr ccw; + + if (!cw) + return BadValue; + + for (ccw = cw->clients; ccw; ccw = ccw->next) + if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) + { + FreeResource (ccw->id, RT_NONE); + return Success; + } + return BadValue; +} + +/* + * Redirect all subwindows for one client + */ + +int +compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pWin); + CompClientWindowPtr ccw; + WindowPtr pChild; + + /* + * Only one Manual update is allowed + */ + if (csw && update == CompositeRedirectManual) + for (ccw = csw->clients; ccw; ccw = ccw->next) + if (ccw->update == CompositeRedirectManual) + return BadAccess; + /* + * Allocate per-client per-window structure + * The client *could* allocate multiple, but while supported, + * it is not expected to be common + */ + ccw = malloc (sizeof (CompClientWindowRec)); + if (!ccw) + return BadAlloc; + ccw->id = FakeClientID (pClient->index); + ccw->update = update; + /* + * Now make sure there's a per-window structure to hang this from + */ + if (!csw) + { + csw = malloc (sizeof (CompSubwindowsRec)); + if (!csw) + { + free (ccw); + return BadAlloc; + } + csw->update = CompositeRedirectAutomatic; + csw->clients = 0; + FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, csw); + } + /* + * Redirect all existing windows + */ + for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) + { + int ret = compRedirectWindow (pClient, pChild, update); + if (ret != Success) + { + for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) + (void) compUnredirectWindow (pClient, pChild, update); + if (!csw->clients) + { + free (csw); + FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, NULL); + } + free (ccw); + return ret; + } + } + /* + * Hook into subwindows list + */ + ccw->next = csw->clients; + csw->clients = ccw; + if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin)) + return BadAlloc; + if (ccw->update == CompositeRedirectManual) + { + csw->update = CompositeRedirectManual; + /* + * tell damage extension that damage events for this client are + * critical output + */ + DamageExtSetCritical (pClient, TRUE); + } + return Success; +} + +/* + * Free one of the per-client per-subwindows resources, + * which frees one redirect per subwindow + */ +void +compFreeClientSubwindows (WindowPtr pWin, XID id) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pWin); + CompClientWindowPtr ccw, *prev; + WindowPtr pChild; + + if (!csw) + return; + for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) + { + if (ccw->id == id) + { + ClientPtr pClient = clients[CLIENT_ID(id)]; + + *prev = ccw->next; + if (ccw->update == CompositeRedirectManual) + { + /* + * tell damage extension that damage events for this client are + * critical output + */ + DamageExtSetCritical (pClient, FALSE); + csw->update = CompositeRedirectAutomatic; + if (pWin->mapped) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE); + } + + /* + * Unredirect all existing subwindows + */ + for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) + (void) compUnredirectWindow (pClient, pChild, ccw->update); + + free (ccw); + break; + } + } + + /* + * Check if all of the per-client records are gone + */ + if (!csw->clients) + { + FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, NULL); + free (csw); + } +} + +/* + * This is easy, just free the appropriate resource. + */ + +int +compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pWin); + CompClientWindowPtr ccw; + + if (!csw) + return BadValue; + for (ccw = csw->clients; ccw; ccw = ccw->next) + if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) + { + FreeResource (ccw->id, RT_NONE); + return Success; + } + return BadValue; +} + +/* + * Add redirection information for one subwindow (during reparent) + */ + +int +compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pParent); + CompClientWindowPtr ccw; + + if (!csw) + return Success; + for (ccw = csw->clients; ccw; ccw = ccw->next) + { + int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)], + pWin, ccw->update); + if (ret != Success) + return ret; + } + return Success; +} + +/* + * Remove redirection information for one subwindow (during reparent) + */ + +int +compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pParent); + CompClientWindowPtr ccw; + + if (!csw) + return Success; + for (ccw = csw->clients; ccw; ccw = ccw->next) + { + int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)], + pWin, ccw->update); + if (ret != Success) + return ret; + } + return Success; +} + +static PixmapPtr +compNewPixmap (WindowPtr pWin, int x, int y, int w, int h) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent = pWin->parent; + PixmapPtr pPixmap; + + /* usage_hint unsupported by our old server infrastructure. */ + pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, + CREATE_PIXMAP_USAGE_BACKING_PIXMAP); + + if (!pPixmap) + return 0; + + pPixmap->screen_x = x; + pPixmap->screen_y = y; + + if (pParent->drawable.depth == pWin->drawable.depth) { + GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); + + /* + * Copy bits from the parent into the new pixmap so that it will + * have "reasonable" contents in case for background None areas. + */ + if (pGC) + { + ChangeGCVal val; + + val.val = IncludeInferiors; + dixChangeGC(NullClient, pGC, GCSubwindowMode, NULL, &val); + ValidateGC(&pPixmap->drawable, pGC); + (*pGC->ops->CopyArea) (&pParent->drawable, + &pPixmap->drawable, + pGC, + x - pParent->drawable.x, + y - pParent->drawable.y, + w, h, 0, 0); + FreeScratchGC (pGC); + } + } + else { + PictFormatPtr pSrcFormat = compWindowFormat (pParent); + PictFormatPtr pDstFormat = compWindowFormat (pWin); + XID inferiors = IncludeInferiors; + int error; + + PicturePtr pSrcPicture = CreatePicture(None, + &pParent->drawable, + pSrcFormat, + CPSubwindowMode, + &inferiors, + serverClient, &error); + + PicturePtr pDstPicture = CreatePicture(None, + &pPixmap->drawable, + pDstFormat, + 0, 0, + serverClient, &error); + + if (pSrcPicture && pDstPicture) { + CompositePicture(PictOpSrc, + pSrcPicture, + NULL, + pDstPicture, + x - pParent->drawable.x, + y - pParent->drawable.y, 0, 0, 0, 0, w, h); + } + if (pSrcPicture) + FreePicture(pSrcPicture, 0); + if (pDstPicture) + FreePicture(pDstPicture, 0); + } + return pPixmap; +} + +Bool +compAllocPixmap (WindowPtr pWin) +{ + int bw = (int) pWin->borderWidth; + int x = pWin->drawable.x - bw; + int y = pWin->drawable.y - bw; + int w = pWin->drawable.width + (bw << 1); + int h = pWin->drawable.height + (bw << 1); + PixmapPtr pPixmap = compNewPixmap (pWin, x, y, w, h); + CompWindowPtr cw = GetCompWindow (pWin); + + if (!pPixmap) + return FALSE; + if (cw->update == CompositeRedirectAutomatic) + pWin->redirectDraw = RedirectDrawAutomatic; + else + pWin->redirectDraw = RedirectDrawManual; + + compSetPixmap (pWin, pPixmap); + cw->oldx = COMP_ORIGIN_INVALID; + cw->oldy = COMP_ORIGIN_INVALID; + cw->damageRegistered = FALSE; + if (cw->update == CompositeRedirectAutomatic) + { + DamageRegister (&pWin->drawable, cw->damage); + cw->damageRegistered = TRUE; + } + + /* Make sure our borderClip is up to date */ + RegionUninit(&cw->borderClip); + RegionCopy(&cw->borderClip, &pWin->borderClip); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; + + return TRUE; +} + +void +compSetParentPixmap (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pParentPixmap; + CompWindowPtr cw = GetCompWindow (pWin); + + if (cw->damageRegistered) + { + DamageUnregister (&pWin->drawable, cw->damage); + cw->damageRegistered = FALSE; + DamageEmpty (cw->damage); + } + /* + * Move the parent-constrained border clip region back into + * the window so that ValidateTree will handle the unmap + * case correctly. Unmap adds the window borderClip to the + * parent exposed area; regions beyond the parent cause crashes + */ + RegionCopy(&pWin->borderClip, &cw->borderClip); + pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); + pWin->redirectDraw = RedirectDrawNone; + compSetPixmap (pWin, pParentPixmap); +} + +/* + * Make sure the pixmap is the right size and offset. Allocate a new + * pixmap to change size, adjust origin to change offset, leaving the + * old pixmap in cw->pOldPixmap so bits can be recovered + */ +Bool +compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y, + unsigned int w, unsigned int h, int bw) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); + PixmapPtr pNew; + CompWindowPtr cw = GetCompWindow (pWin); + int pix_x, pix_y; + int pix_w, pix_h; + + assert (cw && pWin->redirectDraw != RedirectDrawNone); + cw->oldx = pOld->screen_x; + cw->oldy = pOld->screen_y; + pix_x = draw_x - bw; + pix_y = draw_y - bw; + pix_w = w + (bw << 1); + pix_h = h + (bw << 1); + if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) + { + pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h); + if (!pNew) + return FALSE; + cw->pOldPixmap = pOld; + compSetPixmap (pWin, pNew); + } + else + { + pNew = pOld; + cw->pOldPixmap = 0; + } + pNew->screen_x = pix_x; + pNew->screen_y = pix_y; + return TRUE; +} diff --git a/nx-X11/programs/Xserver/composite/compext.c b/nx-X11/programs/Xserver/composite/compext.c new file mode 100644 index 000000000..8513c6d73 --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compext.c @@ -0,0 +1,1063 @@ +/* + * $Id: compext.c,v 1.5 2005/07/03 07:37:34 daniels Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "compint.h" +#include "XI.h" +#include "XIproto.h" +#include "protocol-versions.h" +#include "extinit.h" + +static CARD8 CompositeReqCode; + +#ifndef NXAGENT_SERVER +static DevPrivateKeyRec CompositeClientPrivateKeyRec; + +#define CompositeClientPrivateKey (&CompositeClientPrivateKeyRec) +#else /* !defined(NXAGENT_SERVER) */ +static int CompositeClientPrivIndex = -1; +#endif /* !defined(NXAGENT_SERVER) */ + +RESTYPE CompositeClientWindowType; +RESTYPE CompositeClientSubwindowsType; +RESTYPE CompositeClientOverlayType; + +typedef struct _CompositeClient { + int major_version; + int minor_version; +} CompositeClientRec, *CompositeClientPtr; + +#ifndef NXAGENT_SERVER +#define GetCompositeClient(pClient) ((CompositeClientPtr) \ + dixLookupPrivate(&(pClient)->devPrivates, CompositeClientPrivateKey)) +#else /* !defined(NXAGENT_SERVER) */ +#define GetCompositeClient(pClient) ((CompositeClientPtr) \ + (pClient)->devPrivates[CompositeClientPrivIndex].ptr) +#endif /* !edefined(NXAGENT_SERVER) */ + +static void +CompositeClientCallback (CallbackListPtr *list, + void *closure, + void *data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + CompositeClientPtr pCompositeClient = GetCompositeClient (pClient); + + pCompositeClient->major_version = 0; + pCompositeClient->minor_version = 0; +} + +static void +CompositeResetProc (ExtensionEntry *extEntry) +{ +} + +static int +FreeCompositeClientWindow(void *value, XID ccwid) +{ + WindowPtr pWin = value; + + compFreeClientWindow(pWin, ccwid); + return Success; +} + +static int +FreeCompositeClientSubwindows(void *value, XID ccwid) +{ + WindowPtr pWin = value; + + compFreeClientSubwindows(pWin, ccwid); + return Success; +} + +static int +FreeCompositeClientOverlay(void *value, XID ccwid) +{ + CompOverlayClientPtr pOc = (CompOverlayClientPtr) value; + + compFreeOverlayClient(pOc); + return Success; +} + +static int +ProcCompositeQueryVersion (ClientPtr client) +{ + CompositeClientPtr pCompositeClient = GetCompositeClient (client); + xCompositeQueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0 + }; + + REQUEST(xCompositeQueryVersionReq); + + REQUEST_SIZE_MATCH(xCompositeQueryVersionReq); + if (stuff->majorVersion < SERVER_COMPOSITE_MAJOR_VERSION) { + rep.majorVersion = stuff->majorVersion; + rep.minorVersion = stuff->minorVersion; + } else { + rep.majorVersion = SERVER_COMPOSITE_MAJOR_VERSION; + rep.minorVersion = SERVER_COMPOSITE_MINOR_VERSION; + } + pCompositeClient->major_version = rep.majorVersion; + pCompositeClient->minor_version = rep.minorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.majorVersion); + swapl(&rep.minorVersion); + } + WriteToClient(client, sizeof(xCompositeQueryVersionReply), &rep); + return Success; +} + +/* Unsupported by current architecture and porting is too much effort. */ +#if 0 +#define VERIFY_WINDOW(pWindow, wid, client, mode) \ + do { \ + int err; \ + err = dixLookupResourceByType((void **) &pWindow, wid, \ + RT_WINDOW, client, mode); \ + if (err != Success) { \ + client->errorValue = wid; \ + return err; \ + } \ + } while (0) +#endif /* 0 */ + +static int +ProcCompositeRedirectWindow (ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xCompositeRedirectWindowReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + + return compRedirectWindow (client, pWin, stuff->update); +} + +static int +ProcCompositeRedirectSubwindows (ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xCompositeRedirectSubwindowsReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + + return compRedirectSubwindows (client, pWin, stuff->update); +} + +static int +ProcCompositeUnredirectWindow (ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xCompositeUnredirectWindowReq); + + REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + + return compUnredirectWindow (client, pWin, stuff->update); +} + +static int +ProcCompositeUnredirectSubwindows (ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xCompositeUnredirectSubwindowsReq); + + REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + + return compUnredirectSubwindows (client, pWin, stuff->update); +} + +static int +ProcCompositeCreateRegionFromBorderClip (ClientPtr client) +{ + WindowPtr pWin; + CompWindowPtr cw; + RegionPtr pBorderClip, pRegion; + REQUEST(xCompositeCreateRegionFromBorderClipReq); + + REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + LEGAL_NEW_RESOURCE (stuff->region, client); + + cw = GetCompWindow (pWin); + if (cw) + pBorderClip = &cw->borderClip; + else + pBorderClip = &pWin->borderClip; + pRegion = XFixesRegionCopy (pBorderClip); + if (!pRegion) + return BadAlloc; + RegionTranslate(pRegion, -pWin->drawable.x, -pWin->drawable.y); + + if (!AddResource (stuff->region, RegionResType, (void *) pRegion)) + return BadAlloc; + + return Success; +} + +static int +ProcCompositeNameWindowPixmap (ClientPtr client) +{ + WindowPtr pWin; + CompWindowPtr cw; + PixmapPtr pPixmap; + ScreenPtr pScreen; + int rc; + + REQUEST(xCompositeNameWindowPixmapReq); + + REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + + pScreen = pWin->drawable.pScreen; + + if (!pWin->viewable) + return BadMatch; + + LEGAL_NEW_RESOURCE (stuff->pixmap, client); + + cw = GetCompWindow (pWin); + if (!cw) + return BadMatch; + + pPixmap = (*pScreen->GetWindowPixmap) (pWin); + if (!pPixmap) + return BadMatch; + + /* security creation/labeling check */ + /* + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, + pPixmap, RT_WINDOW, pWin, DixCreateAccess); + */ + rc = Success; + if (rc != Success) + return rc; + + ++pPixmap->refcnt; + + if (!AddResource (stuff->pixmap, RT_PIXMAP, (void *) pPixmap)) + return BadAlloc; + + /* Unsupported by current architecture. */ + /* + if (pScreen->NameWindowPixmap) { + rc = pScreen->NameWindowPixmap(pWin, pPixmap, stuff->pixmap); + if (rc != Success) { + FreeResource(stuff->pixmap, RT_NONE); + return rc; + } + } + */ + + return Success; +} + +static int +ProcCompositeGetOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeGetOverlayWindowReq); + xCompositeGetOverlayWindowReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + CompScreenPtr cs; + CompOverlayClientPtr pOc; + int rc; + + REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + pScreen = pWin->drawable.pScreen; + + /* + * Create an OverlayClient structure to mark this client's + * interest in the overlay window + */ + pOc = compCreateOverlayClient(pScreen, client); + if (pOc == NULL) + return BadAlloc; + + /* + * Make sure the overlay window exists + */ + cs = GetCompScreen(pScreen); + if (cs->pOverlayWin == NULL) + if (!compCreateOverlayWindow(pScreen)) { + FreeResource(pOc->resource, RT_NONE); + return BadAlloc; + } + + /* + rc = XaceHook(XACE_RESOURCE_ACCESS, client, cs->pOverlayWin->drawable.id, + RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL, DixGetAttrAccess); + */ + rc = Success; + if (rc != Success) { + FreeResource(pOc->resource, RT_NONE); + return rc; + } + + rep = (xCompositeGetOverlayWindowReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .overlayWin = cs->pOverlayWin->drawable.id + }; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.overlayWin); + } + WriteToClient(client, sz_xCompositeGetOverlayWindowReply, &rep); + + return Success; +} + +static int +ProcCompositeReleaseOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeReleaseOverlayWindowReq); + WindowPtr pWin; + CompOverlayClientPtr pOc; + + REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + + /* + * Has client queried a reference to the overlay window + * on this screen? If not, generate an error. + */ + pOc = compFindOverlayClient(pWin->drawable.pScreen, client); + if (pOc == NULL) + return BadMatch; + + /* The delete function will free the client structure */ + FreeResource(pOc->resource, RT_NONE); + + return Success; +} + +static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { + ProcCompositeQueryVersion, + ProcCompositeRedirectWindow, + ProcCompositeRedirectSubwindows, + ProcCompositeUnredirectWindow, + ProcCompositeUnredirectSubwindows, + ProcCompositeCreateRegionFromBorderClip, + ProcCompositeNameWindowPixmap, + ProcCompositeGetOverlayWindow, ProcCompositeReleaseOverlayWindow, +}; + +static int +ProcCompositeDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < CompositeNumberRequests) + return (*ProcCompositeVector[stuff->data]) (client); + else + return BadRequest; +} + +static int +SProcCompositeQueryVersion (ClientPtr client) +{ + REQUEST(xCompositeQueryVersionReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeQueryVersionReq); + swapl(&stuff->majorVersion); + swapl(&stuff->minorVersion); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeRedirectWindow (ClientPtr client) +{ + REQUEST(xCompositeRedirectWindowReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq); + swapl (&stuff->window); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeRedirectSubwindows (ClientPtr client) +{ + REQUEST(xCompositeRedirectSubwindowsReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq); + swapl (&stuff->window); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeUnredirectWindow (ClientPtr client) +{ + REQUEST(xCompositeUnredirectWindowReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq); + swapl (&stuff->window); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeUnredirectSubwindows (ClientPtr client) +{ + REQUEST(xCompositeUnredirectSubwindowsReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq); + swapl (&stuff->window); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeCreateRegionFromBorderClip (ClientPtr client) +{ + REQUEST(xCompositeCreateRegionFromBorderClipReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq); + swapl (&stuff->region); + swapl (&stuff->window); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeNameWindowPixmap (ClientPtr client) +{ + REQUEST(xCompositeNameWindowPixmapReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq); + swapl (&stuff->window); + swapl (&stuff->pixmap); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeGetOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeGetOverlayWindowReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq); + swapl(&stuff->window); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeReleaseOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeReleaseOverlayWindowReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq); + swapl(&stuff->window); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { + SProcCompositeQueryVersion, + SProcCompositeRedirectWindow, + SProcCompositeRedirectSubwindows, + SProcCompositeUnredirectWindow, + SProcCompositeUnredirectSubwindows, + SProcCompositeCreateRegionFromBorderClip, + SProcCompositeNameWindowPixmap, + SProcCompositeGetOverlayWindow, SProcCompositeReleaseOverlayWindow, +}; + +static int +SProcCompositeDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < CompositeNumberRequests) + return (*SProcCompositeVector[stuff->data]) (client); + else + return BadRequest; +} + +/* Both unused and incompatible due to architecture, disabled. */ +#if 0 +/** @see GetDefaultBytes */ +static void +GetCompositeClientWindowBytes(void *value, XID id, ResourceSizePtr size) +{ + WindowPtr window = value; + + /* Currently only pixmap bytes are reported to clients. */ + size->resourceSize = 0; + + /* Calculate pixmap reference sizes. */ + size->pixmapRefSize = 0; + if (window->redirectDraw != RedirectDrawNone) + { + SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP); + ResourceSizeRec pixmapSize = { 0, 0 }; + ScreenPtr screen = window->drawable.pScreen; + PixmapPtr pixmap = screen->GetWindowPixmap(window); + pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize); + size->pixmapRefSize += pixmapSize.pixmapRefSize; + } +} +#endif /* 0 */ + +void +CompositeExtensionInit (void) +{ + ExtensionEntry *extEntry; + int s; + + /* Assume initialization is going to fail */ + noCompositeExtension = TRUE; + + fprintf(stderr, "COMPOSITE: trying to initialize extension.\n"); + + for (s = 0; s < screenInfo.numScreens; s++) { + ScreenPtr pScreen = screenInfo.screens[s]; + VisualPtr vis; + + /* Composite on 8bpp pseudocolor root windows appears to fail, so + * just disable it on anything pseudocolor for safety. + */ + for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++); + if ((vis->class | DynamicClass) == PseudoColor) + return; + + /* Ensure that Render is initialized, which is required for automatic + * compositing. + */ + if (GetPictureScreenIfSet(pScreen) == NULL) + return; + } +#ifdef PANORAMIX + /* Xinerama's rewriting of window drawing before Composite gets to it + * breaks Composite. + */ + if (!noPanoramiXExtension) + return; +#endif + + CompositeClientWindowType = CreateNewResourceType (FreeCompositeClientWindow); + if (!CompositeClientWindowType) + return; + + /* SetResourceTypeSizeFunc(CompositeClientWindowType, + GetCompositeClientWindowBytes); + */ + + CompositeClientSubwindowsType = CreateNewResourceType (FreeCompositeClientSubwindows); + if (!CompositeClientSubwindowsType) + return; + + CompositeClientOverlayType = CreateNewResourceType + (FreeCompositeClientOverlay); + if (!CompositeClientOverlayType) + return; + +#ifndef NXAGENT_SERVER + if (!dixRegisterPrivateKey(&CompositeClientPrivateKeyRec, PRIVATE_CLIENT, + sizeof (CompositeClientRec))) + return; +#else /* !defined(NXAGENT_SERVER) */ + if ((CompositeClientPrivIndex = AllocateClientPrivateIndex()) < 0) + return; + if (!AllocateClientPrivate(CompositeClientPrivIndex, sizeof (CompositeClientRec))) + return; +#endif /* !defined(NXAGENT_SERVER) */ + + if (!AddCallback (&ClientStateCallback, CompositeClientCallback, 0)) + return; + + for (s = 0; s < screenInfo.numScreens; s++) + if (!compScreenInit (screenInfo.screens[s])) { + fprintf (stderr, "COMPOSITE: could not initialize via compScreenInit() for screen %d\n", s); + return; + } + + extEntry = AddExtension (COMPOSITE_NAME, 0, 0, + ProcCompositeDispatch, SProcCompositeDispatch, + CompositeResetProc, StandardMinorOpcode); + if (!extEntry) + return; + CompositeReqCode = (CARD8) extEntry->base; + + /* Initialization succeeded */ + noCompositeExtension = FALSE; +} + +/* + * This code requires features the current infrastructure does not provide + * and will thus be disabled. + */ +#if 0 + +#ifdef PANORAMIX +#include "panoramiXsrv.h" + +int (*PanoramiXSaveCompositeVector[CompositeNumberRequests]) (ClientPtr); + +static int +PanoramiXCompositeRedirectWindow(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeRedirectWindowReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; +} + +static int +PanoramiXCompositeRedirectSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeRedirectSubwindowsReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; +} + +static int +PanoramiXCompositeUnredirectWindow(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeUnredirectWindowReq); + + REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; +} + +static int +PanoramiXCompositeUnredirectSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeUnredirectSubwindowsReq); + + REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; +} + +static int +PanoramiXCompositeNameWindowPixmap(ClientPtr client) +{ + WindowPtr pWin; + CompWindowPtr cw; + PixmapPtr pPixmap; + int rc; + PanoramiXRes *win, *newPix; + int i; + + REQUEST(xCompositeNameWindowPixmapReq); + + REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + LEGAL_NEW_RESOURCE(stuff->pixmap, client); + + if (!(newPix = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = FALSE; + panoramix_setup_ids(newPix, client, stuff->pixmap); + + FOR_NSCREENS(i) { + rc = dixLookupResourceByType((void **) &pWin, win->info[i].id, + RT_WINDOW, client, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->window; + free(newPix); + return rc; + } + + if (!pWin->viewable) { + free(newPix); + return BadMatch; + } + + cw = GetCompWindow(pWin); + if (!cw) { + free(newPix); + return BadMatch; + } + + pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); + if (!pPixmap) { + free(newPix); + return BadMatch; + } + + if (!AddResource(newPix->info[i].id, RT_PIXMAP, (void *) pPixmap)) + return BadAlloc; + + ++pPixmap->refcnt; + } + + if (!AddResource(stuff->pixmap, XRT_PIXMAP, (void *) newPix)) + return BadAlloc; + + return Success; +} + +static int +PanoramiXCompositeGetOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeGetOverlayWindowReq); + xCompositeGetOverlayWindowReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + CompScreenPtr cs; + CompOverlayClientPtr pOc; + int rc; + PanoramiXRes *win, *overlayWin = NULL; + int i; + + REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + cs = GetCompScreen(screenInfo.screens[0]); + if (!cs->pOverlayWin) { + if (!(overlayWin = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + overlayWin->type = XRT_WINDOW; + overlayWin->u.win.root = FALSE; + } + + FOR_NSCREENS_BACKWARD(i) { + rc = dixLookupResourceByType((void **) &pWin, win->info[i].id, + RT_WINDOW, client, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->window; + free(overlayWin); + return rc; + } + pScreen = pWin->drawable.pScreen; + + /* + * Create an OverlayClient structure to mark this client's + * interest in the overlay window + */ + pOc = compCreateOverlayClient(pScreen, client); + if (pOc == NULL) { + free(overlayWin); + return BadAlloc; + } + + /* + * Make sure the overlay window exists + */ + cs = GetCompScreen(pScreen); + if (cs->pOverlayWin == NULL) + if (!compCreateOverlayWindow(pScreen)) { + FreeResource(pOc->resource, RT_NONE); + free(overlayWin); + return BadAlloc; + } + + /* + rc = XaceHook(XACE_RESOURCE_ACCESS, client, + cs->pOverlayWin->drawable.id, + RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL, + DixGetAttrAccess); + */ + rc = Success; + if (rc != Success) { + FreeResource(pOc->resource, RT_NONE); + free(overlayWin); + return rc; + } + } + + if (overlayWin) { + FOR_NSCREENS(i) { + cs = GetCompScreen(screenInfo.screens[i]); + overlayWin->info[i].id = cs->pOverlayWin->drawable.id; + } + + AddResource(overlayWin->info[0].id, XRT_WINDOW, overlayWin); + } + + cs = GetCompScreen(screenInfo.screens[0]); + + rep = (xCompositeGetOverlayWindowReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .overlayWin = cs->pOverlayWin->drawable.id + }; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.overlayWin); + } + WriteToClient(client, sz_xCompositeGetOverlayWindowReply, &rep); + + return Success; +} + +static int +PanoramiXCompositeReleaseOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeReleaseOverlayWindowReq); + WindowPtr pWin; + CompOverlayClientPtr pOc; + PanoramiXRes *win; + int i, rc; + + REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_BACKWARD(i) { + if ((rc = dixLookupResourceByType((void **) &pWin, win->info[i].id, + XRT_WINDOW, client, + DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + /* + * Has client queried a reference to the overlay window + * on this screen? If not, generate an error. + */ + pOc = compFindOverlayClient(pWin->drawable.pScreen, client); + if (pOc == NULL) + return BadMatch; + + /* The delete function will free the client structure */ + FreeResource(pOc->resource, RT_NONE); + } + + return Success; +} + +void +PanoramiXCompositeInit(void) +{ + int i; + + for (i = 0; i < CompositeNumberRequests; i++) + PanoramiXSaveCompositeVector[i] = ProcCompositeVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcCompositeVector[X_CompositeRedirectWindow] = + PanoramiXCompositeRedirectWindow; + ProcCompositeVector[X_CompositeRedirectSubwindows] = + PanoramiXCompositeRedirectSubwindows; + ProcCompositeVector[X_CompositeUnredirectWindow] = + PanoramiXCompositeUnredirectWindow; + ProcCompositeVector[X_CompositeUnredirectSubwindows] = + PanoramiXCompositeUnredirectSubwindows; + ProcCompositeVector[X_CompositeNameWindowPixmap] = + PanoramiXCompositeNameWindowPixmap; + ProcCompositeVector[X_CompositeGetOverlayWindow] = + PanoramiXCompositeGetOverlayWindow; + ProcCompositeVector[X_CompositeReleaseOverlayWindow] = + PanoramiXCompositeReleaseOverlayWindow; +} + +void +PanoramiXCompositeReset(void) +{ + int i; + + for (i = 0; i < CompositeNumberRequests; i++) + ProcCompositeVector[i] = PanoramiXSaveCompositeVector[i]; +} + +#endif + +#endif /* 0 */ diff --git a/nx-X11/programs/Xserver/composite/compinit.c b/nx-X11/programs/Xserver/composite/compinit.c new file mode 100644 index 000000000..ff2137887 --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compinit.c @@ -0,0 +1,492 @@ +/* + * $Id: compinit.c,v 1.9 2005/07/03 07:37:34 daniels Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "compint.h" +#include "compositeext.h" + +#ifndef NXAGENT_SERVER +DevPrivateKeyRec CompScreenPrivateKeyRec; +DevPrivateKeyRec CompWindowPrivateKeyRec; +DevPrivateKeyRec CompSubwindowsPrivateKeyRec; +#else /* !defined(NXAGENT_SERVER) */ +int CompScreenPrivIndex = -1; +int CompWindowPrivIndex = -1; +int CompSubwindowsPrivIndex = -1; +#endif + +static Bool +compCloseScreen (ScreenPtr pScreen) +{ + CompScreenPtr cs = GetCompScreen (pScreen); + Bool ret; + + free(cs->alternateVisuals); + + pScreen->CloseScreen = cs->CloseScreen; + pScreen->InstallColormap = cs->InstallColormap; + pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; + pScreen->ReparentWindow = cs->ReparentWindow; + + /* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ + /* + pScreen->ConfigNotify = cs->ConfigNotify; + */ + + pScreen->MoveWindow = cs->MoveWindow; + pScreen->ResizeWindow = cs->ResizeWindow; + pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; + + pScreen->ClipNotify = cs->ClipNotify; + pScreen->UnrealizeWindow = cs->UnrealizeWindow; + pScreen->RealizeWindow = cs->RealizeWindow; + pScreen->DestroyWindow = cs->DestroyWindow; + pScreen->CreateWindow = cs->CreateWindow; + pScreen->CopyWindow = cs->CopyWindow; + pScreen->PositionWindow = cs->PositionWindow; + + pScreen->GetImage = cs->GetImage; + pScreen->GetSpans = cs->GetSpans; + pScreen->SourceValidate = cs->SourceValidate; + + free (cs); + FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, NULL); + ret = (*pScreen->CloseScreen) (pScreen); + return ret; +} + +static void +compInstallColormap (ColormapPtr pColormap) +{ + VisualPtr pVisual = pColormap->pVisual; + ScreenPtr pScreen = pColormap->pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + int a; + + for (a = 0; a < cs->numAlternateVisuals; a++) + if (pVisual->vid == cs->alternateVisuals[a]) + return; + pScreen->InstallColormap = cs->InstallColormap; + (*pScreen->InstallColormap) (pColormap); + cs->InstallColormap = pScreen->InstallColormap; + pScreen->InstallColormap = compInstallColormap; +} + +/* Unsupported by current architecture, drop for now. */ +#if 0 +static void +compCheckBackingStore(WindowPtr pWin) +{ + if (pWin->backingStore != NotUseful && !pWin->backStorage) { + compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic); + pWin->backStorage = TRUE; + } + else if (pWin->backingStore == NotUseful && pWin->backStorage) { + compUnredirectWindow(serverClient, pWin, + CompositeRedirectAutomatic); + pWin->backStorage = FALSE; + } +} + +/* Fake backing store via automatic redirection */ +static Bool +compChangeWindowAttributes(WindowPtr pWin, unsigned long mask) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + Bool ret; + + pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; + ret = pScreen->ChangeWindowAttributes(pWin, mask); + + if (ret && (mask & CWBackingStore) && + pScreen->backingStoreSupport != NotUseful) + compCheckBackingStore(pWin); + + pScreen->ChangeWindowAttributes = compChangeWindowAttributes; + + return ret; +} +#endif /* 0 */ + +static void +compGetImage(DrawablePtr pDrawable, + int sx, int sy, + int w, int h, + unsigned int format, unsigned long planemask, char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + + pScreen->GetImage = cs->GetImage; + if (pDrawable->type == DRAWABLE_WINDOW) + compPaintChildrenToWindow(pScreen, (WindowPtr) pDrawable); + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine); + cs->GetImage = pScreen->GetImage; + pScreen->GetImage = compGetImage; +} + +static void +compGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, + int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDrawable->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + + pScreen->GetSpans = cs->GetSpans; + if (pDrawable->type == DRAWABLE_WINDOW) + compPaintChildrenToWindow(pScreen, (WindowPtr) pDrawable); + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + cs->GetSpans = pScreen->GetSpans; + pScreen->GetSpans = compGetSpans; +} + +static void +compSourceValidate(DrawablePtr pDrawable, + int x, int y, + int width, int height /* , unsigned int subWindowMode */ /* unsupported */) +{ + ScreenPtr pScreen = pDrawable->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + + pScreen->SourceValidate = cs->SourceValidate; + if (pDrawable->type == DRAWABLE_WINDOW /* && subWindowMode == IncludeInferiors */ /* unsupported */) + compPaintChildrenToWindow(pScreen, (WindowPtr) pDrawable); + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height /*, + subWindowMode */ /* unsupported */); + cs->SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = compSourceValidate; +} + +/* + * Add alternate visuals -- always expose an ARGB32 and RGB24 visual + */ + +static DepthPtr +compFindVisuallessDepth (ScreenPtr pScreen, int d) +{ + int i; + + for (i = 0; i < pScreen->numDepths; i++) + { + DepthPtr depth = &pScreen->allowedDepths[i]; + if (depth->depth == d) + { + /* + * Make sure it doesn't have visuals already + */ + if (depth->numVids) + return 0; + /* + * looks fine + */ + return depth; + } + } + /* + * If there isn't one, then it's gonna be hard to have + * an associated visual + */ + return 0; +} + +/* + * Add a list of visual IDs to the list of visuals to implicitly redirect. + */ +static Bool +compRegisterAlternateVisuals(CompScreenPtr cs, VisualID * vids, int nVisuals) +{ + VisualID *p; + + p = reallocarray(cs->alternateVisuals, + cs->numAlternateVisuals + nVisuals, sizeof(VisualID)); + if (p == NULL) + return FALSE; + + memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals); + + cs->alternateVisuals = p; + cs->numAlternateVisuals += nVisuals; + + return TRUE; +} + +Bool +CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids, + int nVisuals) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + + return compRegisterAlternateVisuals(cs, vids, nVisuals); +} + +Bool +CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, + VisualID parentVisual, + VisualID winVisual) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + CompImplicitRedirectException *p; + + p = reallocarray(cs->implicitRedirectExceptions, + cs->numImplicitRedirectExceptions + 1, sizeof(p[0])); + if (p == NULL) + return FALSE; + + p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual; + p[cs->numImplicitRedirectExceptions].winVisual = winVisual; + + cs->implicitRedirectExceptions = p; + cs->numImplicitRedirectExceptions++; + + return TRUE; +} + +typedef struct _alternateVisual { + int depth; + CARD32 format; +} CompAlternateVisual; + +static CompAlternateVisual altVisuals[] = { +#if COMP_INCLUDE_RGB24_VISUAL + { 24, PICT_r8g8b8 }, +#endif + { 32, PICT_a8r8g8b8 }, +}; + +static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) / + sizeof(CompAlternateVisual); + +static Bool +compAddAlternateVisual (ScreenPtr pScreen, CompScreenPtr cs, + CompAlternateVisual * alt) +{ + VisualPtr visual; + DepthPtr depth; + PictFormatPtr pPictFormat; + unsigned long alphaMask; + + /* + * The ARGB32 visual is always available. Other alternate depth visuals + * are only provided if their depth is less than the root window depth. + * There's no deep reason for this. + */ + if (alt->depth >= pScreen->rootDepth && alt->depth != 32) + return FALSE; + + depth = compFindVisuallessDepth(pScreen, alt->depth); + if (!depth) + /* alt->depth doesn't exist or already has alternate visuals. */ + return TRUE; + + pPictFormat = PictureMatchFormat(pScreen, alt->depth, alt->format); + if (!pPictFormat) + return FALSE; + + if (ResizeVisualArray(pScreen, 1, depth) == FALSE) { + return FALSE; + } + + visual = pScreen->visuals + (pScreen->numVisuals - 1); /* the new one */ + + /* Initialize the visual */ + visual->bitsPerRGBValue = 8; + if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) { + visual->class = PseudoColor; + visual->nplanes = PICT_FORMAT_BPP(alt->format); + visual->ColormapEntries = 1 << visual->nplanes; + } + else { + DirectFormatRec *direct = &pPictFormat->direct; + + visual->class = TrueColor; + visual->redMask = ((unsigned long) direct->redMask) << direct->red; + visual->greenMask = + ((unsigned long) direct->greenMask) << direct->green; + visual->blueMask = ((unsigned long) direct->blueMask) << direct->blue; + alphaMask = ((unsigned long) direct->alphaMask) << direct->alpha; + visual->offsetRed = direct->red; + visual->offsetGreen = direct->green; + visual->offsetBlue = direct->blue; + /* + * Include A bits in this (unlike GLX which includes only RGB) + * This lets DIX compute suitable masks for colormap allocations + */ + visual->nplanes = Ones(visual->redMask | + visual->greenMask | + visual->blueMask | alphaMask); + /* find widest component */ + visual->ColormapEntries = (1 << max(Ones(visual->redMask), + max(Ones(visual->greenMask), + Ones(visual->blueMask)))); + } + + /* remember the visual ID to detect auto-update windows */ + compRegisterAlternateVisuals(cs, &visual->vid, 1); + + return TRUE; +} + +static Bool +compAddAlternateVisuals(ScreenPtr pScreen, CompScreenPtr cs) +{ + int alt, ret = 0; + + for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++) + ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt); + + return ! !ret; +} + +Bool +compScreenInit (ScreenPtr pScreen) +{ + CompScreenPtr cs; + +#ifndef NXAGENT_SERVER + if (!dixRegisterPrivateKey(&CompScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&CompWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&CompSubwindowsPrivateKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; +#else /* !defined(NXAGENT_SERVER) */ + if ((CompScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + if ((CompWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) + return FALSE; + if ((CompSubwindowsPrivIndex = AllocateWindowPrivateIndex()) < 0) + return FALSE; + + if (!AllocateWindowPrivate (pScreen, CompWindowPrivIndex, 0)) + return FALSE; + + if (!AllocateWindowPrivate (pScreen, CompSubwindowsPrivIndex, 0)) + return FALSE; +#endif + + if (GetCompScreen (pScreen)) + return TRUE; + cs = (CompScreenPtr) malloc (sizeof (CompScreenRec)); + if (!cs) + return FALSE; + + cs->damaged = FALSE; + + cs->overlayWid = FakeClientID(0); + cs->pOverlayWin = NULL; + cs->pOverlayClients = NULL; + + cs->numAlternateVisuals = 0; + cs->alternateVisuals = NULL; + cs->numImplicitRedirectExceptions = 0; + cs->implicitRedirectExceptions = NULL; + + if (!compAddAlternateVisuals (pScreen, cs)) + { + free (cs); + return FALSE; + } + + if (!disableBackingStore) + pScreen->backingStoreSupport = WhenMapped; + + cs->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = compPositionWindow; + + cs->CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = compCopyWindow; + + cs->CreateWindow = pScreen->CreateWindow; + pScreen->CreateWindow = compCreateWindow; + + cs->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = compDestroyWindow; + + cs->RealizeWindow = pScreen->RealizeWindow; + pScreen->RealizeWindow = compRealizeWindow; + + cs->UnrealizeWindow = pScreen->UnrealizeWindow; + pScreen->UnrealizeWindow = compUnrealizeWindow; + + cs->ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = compClipNotify; + + /* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ + /* + cs->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = compConfigNotify; + */ + + cs->MoveWindow = pScreen->MoveWindow; + pScreen->MoveWindow = compMoveWindow; + + cs->ResizeWindow = pScreen->ResizeWindow; + pScreen->ResizeWindow = compResizeWindow; + + cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; + pScreen->ChangeBorderWidth = compChangeBorderWidth; + + cs->ReparentWindow = pScreen->ReparentWindow; + pScreen->ReparentWindow = compReparentWindow; + + cs->InstallColormap = pScreen->InstallColormap; + pScreen->InstallColormap = compInstallColormap; + + /* Unsupported by our current architecture, drop for now. */ + /* + cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pScreen->ChangeWindowAttributes = compChangeWindowAttributes; + */ + + cs->BlockHandler = NULL; + + cs->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = compCloseScreen; + + cs->GetImage = pScreen->GetImage; + pScreen->GetImage = compGetImage; + + cs->GetSpans = pScreen->GetSpans; + pScreen->GetSpans = compGetSpans; + + cs->SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = compSourceValidate; + + FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, cs); + + RegisterRealChildHeadProc(CompositeRealChildHead); + + return TRUE; +} diff --git a/nx-X11/programs/Xserver/composite/compint.h b/nx-X11/programs/Xserver/composite/compint.h new file mode 100644 index 000000000..62d5fd868 --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compint.h @@ -0,0 +1,360 @@ +/* + * $Id: compint.h,v 1.8 2005/07/03 08:53:37 daniels Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _COMPINT_H_ +#define _COMPINT_H_ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "dixevents.h" +#include "globals.h" +#include "picturestr.h" +#include "extnsionst.h" +#include "mi.h" +#include "damage.h" +#include "damageextint.h" +#include "xfixes.h" +#include <nx-X11/extensions/compositeproto.h> +#include "compositeext.h" +#include <assert.h> + +/* + * enable this for debugging +#define COMPOSITE_DEBUG + */ + +typedef struct _CompClientWindow { + struct _CompClientWindow *next; + XID id; + int update; +} CompClientWindowRec, *CompClientWindowPtr; + +typedef struct _CompWindow { + RegionRec borderClip; + DamagePtr damage; /* for automatic update mode */ + Bool damageRegistered; + Bool damaged; + int update; + CompClientWindowPtr clients; + int oldx; + int oldy; + PixmapPtr pOldPixmap; + int borderClipX, borderClipY; +} CompWindowRec, *CompWindowPtr; + +#define COMP_ORIGIN_INVALID 0x80000000 + +typedef struct _CompSubwindows { + int update; + CompClientWindowPtr clients; +} CompSubwindowsRec, *CompSubwindowsPtr; + +#ifndef COMP_INCLUDE_RGB24_VISUAL +#define COMP_INCLUDE_RGB24_VISUAL 0 +#endif + +typedef struct _CompOverlayClientRec *CompOverlayClientPtr; + +typedef struct _CompOverlayClientRec { + CompOverlayClientPtr pNext; + ClientPtr pClient; + ScreenPtr pScreen; + XID resource; +} CompOverlayClientRec; + +typedef struct _CompImplicitRedirectException { + XID parentVisual; + XID winVisual; +} CompImplicitRedirectException; + +typedef struct _CompScreen { + PositionWindowProcPtr PositionWindow; + CopyWindowProcPtr CopyWindow; + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + ClipNotifyProcPtr ClipNotify; + /* + * Called from ConfigureWindow, these + * three track changes to the offscreen storage + * geometry + */ + + /* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ + /* + ConfigNotifyProcPtr ConfigNotify; + */ + + MoveWindowProcPtr MoveWindow; + ResizeWindowProcPtr ResizeWindow; + ChangeBorderWidthProcPtr ChangeBorderWidth; + /* + * Reparenting has an effect on Subwindows redirect + */ + ReparentWindowProcPtr ReparentWindow; + + /* + * Colormaps for new visuals better not get installed + */ + InstallColormapProcPtr InstallColormap; + + /* + * Fake backing store via automatic redirection + */ + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + ScreenBlockHandlerProcPtr BlockHandler; + CloseScreenProcPtr CloseScreen; + Bool damaged; + int numAlternateVisuals; + VisualID *alternateVisuals; + int numImplicitRedirectExceptions; + CompImplicitRedirectException *implicitRedirectExceptions; + + WindowPtr pOverlayWin; + Window overlayWid; + CompOverlayClientPtr pOverlayClients; + + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; +} CompScreenRec, *CompScreenPtr; + +#ifndef NXAGENT_SERVER +extern DevPrivateKeyRec CompScreenPrivateKeyRec; + +#define CompScreenPrivateKey (&CompScreenPrivateKeyRec) + +extern DevPrivateKeyRec CompWindowPrivateKeyRec; + +#define CompWindowPrivateKey (&CompWindowPrivateKeyRec) + +extern DevPrivateKeyRec CompSubwindowsPrivateKeyRec; + +#define CompSubwindowsPrivateKey (&CompSubwindowsPrivateKeyRec) + +#define GetCompScreen(s) ((CompScreenPtr) \ + dixLookupPrivate(&(s)->devPrivates, CompScreenPrivateKey)) +#define GetCompWindow(w) ((CompWindowPtr) \ + dixLookupPrivate(&(w)->devPrivates, CompWindowPrivateKey)) +#define GetCompSubwindows(w) ((CompSubwindowsPtr) \ + dixLookupPrivate(&(w)->devPrivates, CompSubwindowsPrivateKey)) +#else /* !defined(NXAGENT_SERVER) */ +extern int CompScreenPrivIndex; +extern int CompWindowPrivIndex; +extern int CompSubwindowsPrivIndex; + +#define GetCompScreen(s) ((CompScreenPtr) (s)->devPrivates[CompScreenPrivIndex].ptr) +#define GetCompWindow(w) ((CompWindowPtr) (w)->devPrivates[CompWindowPrivIndex].ptr) +#define GetCompSubwindows(w) ((CompSubwindowsPtr) (w)->devPrivates[CompSubwindowsPrivIndex].ptr) +#endif /* !defined(NXAGENT_SERVER) */ + +extern RESTYPE CompositeClientSubwindowsType; +extern RESTYPE CompositeClientOverlayType; + +/* Shim for less ifdefs within the actual code. */ +#ifndef NXAGENT_SERVER +#define FAKE_DIX_SET_PRIVATE_IMPL(obj, privateKey, ptr_val) do { dixSetPrivate(&(obj)->devPrivates, privateKey, ptr_val); } while (0) + +#define FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pScreen, CompScreenPrivateKey, ptr_val) +#define FAKE_DIX_SET_WINDOW_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompWindowPrivateKey, ptr_val) +#define FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompSubwindowsPrivateKey, ptr_val) +#else /* !defined(NXAGENT_SERVER) */ +#define FAKE_DIX_SET_PRIVATE_IMPL(obj, privIndex, ptr_val) do { (obj)->devPrivates[privIndex].ptr = (void *) (ptr_val); } while (0) + +#define FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pScreen, CompScreenPrivIndex, ptr_val) +#define FAKE_DIX_SET_WINDOW_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompWindowPrivIndex, ptr_val) +#define FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompSubwindowsPrivIndex, ptr_val) +#endif /* !defined(NXAGENT_SERVER) */ + +/* + * compalloc.c + */ + +Bool +compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update); + +void +compFreeClientWindow (WindowPtr pWin, XID id); + +int +compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update); + +int +compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update); + +void +compFreeClientSubwindows (WindowPtr pWin, XID id); + +int +compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update); + +int +compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin); + +int +compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin); + +Bool +compAllocPixmap (WindowPtr pWin); + +void + compSetParentPixmap(WindowPtr pWin); + +void + compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap); + +Bool +compReallocPixmap (WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, int bw); + +/* + * compinit.c + */ + +Bool + compScreenInit(ScreenPtr pScreen); + +/* + * compoverlay.c + */ + +void + compFreeOverlayClient(CompOverlayClientPtr pOcToDel); + +CompOverlayClientPtr +compFindOverlayClient(ScreenPtr pScreen, ClientPtr pClient); + +CompOverlayClientPtr +compCreateOverlayClient(ScreenPtr pScreen, ClientPtr pClient); + +Bool + compCreateOverlayWindow(ScreenPtr pScreen); + +void + compDestroyOverlayWindow(ScreenPtr pScreen); + +/* + * compwindow.c + */ + +#ifdef COMPOSITE_DEBUG +void +compCheckTree (ScreenPtr pScreen); +#else +#define compCheckTree(s) +#endif + +PictFormatPtr +compWindowFormat (WindowPtr pWin); + +void +compSetPixmap (WindowPtr pWin, PixmapPtr pPixmap); + +Bool +compCheckRedirect (WindowPtr pWin); + +Bool +compPositionWindow (WindowPtr pWin, int x, int y); + +Bool +compRealizeWindow (WindowPtr pWin); + +Bool +compUnrealizeWindow (WindowPtr pWin); + + +void +compClipNotify (WindowPtr pWin, int dx, int dy); + +void +compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind); + +void +compResizeWindow (WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib); + +void +compChangeBorderWidth (WindowPtr pWin, unsigned int border_width); + +void +compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent); + +Bool +compCreateWindow (WindowPtr pWin); + +Bool +compDestroyWindow (WindowPtr pWin); + +void +compSetRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion); + +RegionPtr +compGetRedirectBorderClip (WindowPtr pWin); + +void +compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +void + compPaintChildrenToWindow(ScreenPtr pScreen, WindowPtr pWin); + +WindowPtr + CompositeRealChildHead(WindowPtr pWin); + +int + DeleteWindowNoInputDevices(void *value, XID wid); + +/* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ +/* +int +compConfigNotify(WindowPtr pWin, int x, int y, int w, int h, + int bw, WindowPtr pSib); +*/ + +void PanoramiXCompositeInit(void); +void PanoramiXCompositeReset(void); + +#endif /* _COMPINT_H_ */ diff --git a/nx-X11/programs/Xserver/composite/compositeext.h b/nx-X11/programs/Xserver/composite/compositeext.h new file mode 100644 index 000000000..b96cb1d68 --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compositeext.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2009 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _COMPOSITEEXT_H_ +#define _COMPOSITEEXT_H_ + +#include "misc.h" +#include "scrnintstr.h" + +extern _X_EXPORT Bool CompositeRegisterAlternateVisuals(ScreenPtr pScreen, + VisualID * vids, + int nVisuals); + +extern _X_EXPORT Bool CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, + VisualID parentVisual, + VisualID winVisual); + +extern _X_EXPORT RESTYPE CompositeClientWindowType; + +#endif /* _COMPOSITEEXT_H_ */ diff --git a/nx-X11/programs/Xserver/composite/compoverlay.c b/nx-X11/programs/Xserver/composite/compoverlay.c new file mode 100644 index 000000000..226bbcb6a --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compoverlay.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "compint.h" +#ifndef NXAGENT_SERVER +#include "xace.h" +#endif + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +/* + * Delete the given overlay client list element from its screen list. + */ +void +compFreeOverlayClient(CompOverlayClientPtr pOcToDel) +{ + ScreenPtr pScreen = pOcToDel->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + CompOverlayClientPtr *pPrev, pOc; + + for (pPrev = &cs->pOverlayClients; (pOc = *pPrev); pPrev = &pOc->pNext) { + if (pOc == pOcToDel) { + *pPrev = pOc->pNext; + free(pOc); + break; + } + } + + /* Destroy overlay window when there are no more clients using it */ + if (cs->pOverlayClients == NULL) + compDestroyOverlayWindow(pScreen); +} + +/* + * Return the client's first overlay client rec from the given screen + */ +CompOverlayClientPtr +compFindOverlayClient(ScreenPtr pScreen, ClientPtr pClient) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + CompOverlayClientPtr pOc; + + for (pOc = cs->pOverlayClients; pOc != NULL; pOc = pOc->pNext) + if (pOc->pClient == pClient) + return pOc; + + return NULL; +} + +/* + * Create an overlay client object for the given client + */ +CompOverlayClientPtr +compCreateOverlayClient(ScreenPtr pScreen, ClientPtr pClient) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + CompOverlayClientPtr pOc; + + pOc = (CompOverlayClientPtr) malloc(sizeof(CompOverlayClientRec)); + if (pOc == NULL) + return NULL; + + pOc->pClient = pClient; + pOc->pScreen = pScreen; + pOc->resource = FakeClientID(pClient->index); + pOc->pNext = cs->pOverlayClients; + cs->pOverlayClients = pOc; + + /* + * Create a resource for this element so it can be deleted + * when the client goes away. + */ + if (!AddResource(pOc->resource, CompositeClientOverlayType, (void *) pOc)) + return NULL; + + return pOc; +} + +/* + * Create the overlay window and map it + */ +Bool +compCreateOverlayWindow(ScreenPtr pScreen) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + WindowPtr pRoot = pScreen->root; + WindowPtr pWin; + XID attrs[] = { None, TRUE }; /* backPixmap, overrideRedirect */ + int result; + int w = pScreen->width; + int h = pScreen->height; + int x = 0, y = 0; + + /* Unsupported by current architecture, disabled. */ +#if 0 +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + x = -pScreen->x; + y = -pScreen->y; + w = PanoramiXPixWidth; + h = PanoramiXPixHeight; + } +#endif +#endif + + pWin = cs->pOverlayWin = + CreateWindow(cs->overlayWid, pRoot, x, y, w, h, 0, + InputOutput, CWBackPixmap | CWOverrideRedirect, &attrs[0], + pRoot->drawable.depth, + serverClient, pScreen->rootVisual, &result); + if (pWin == NULL) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (void *) pWin)) + return FALSE; + + MapWindow(pWin, serverClient); + + return TRUE; +} + +/* + * Destroy the overlay window + */ +void +compDestroyOverlayWindow(ScreenPtr pScreen) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + + cs->pOverlayWin = NullWindow; + FreeResource(cs->overlayWid, RT_NONE); +} diff --git a/nx-X11/programs/Xserver/composite/compwindow.c b/nx-X11/programs/Xserver/composite/compwindow.c new file mode 100644 index 000000000..e9bb39827 --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compwindow.c @@ -0,0 +1,909 @@ +/* + * $Id: compwindow.c,v 1.11 2005/07/03 07:37:34 daniels Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "compint.h" + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +#ifdef COMPOSITE_DEBUG +static int +compCheckWindow (WindowPtr pWin, void * data) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin); + PixmapPtr pParentPixmap = pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0; + PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen); + + if (!pWin->parent) + { + assert (pWin->redirectDraw == RedriectDrawNone); + assert (pWinPixmap == pScreenPixmap); + } + else if (pWin->redirectDraw != RedirectDrawNone) + { + assert (pWinPixmap != pParentPixmap); + assert (pWinPixmap != pScreenPixmap); + } + else + { + assert (pWinPixmap == pParentPixmap); + } + assert (0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3); + assert (0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3); + if (pParentPixmap) + assert (0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3); + return WT_WALKCHILDREN; +} + +void +compCheckTree (ScreenPtr pScreen) +{ + WalkTree (pScreen, compCheckWindow, 0); +} +#endif + +typedef struct _compPixmapVisit { + WindowPtr pWindow; + PixmapPtr pPixmap; +} CompPixmapVisitRec, *CompPixmapVisitPtr; + +static Bool +compRepaintBorder (ClientPtr pClient, void * closure) +{ + WindowPtr pWindow; +#ifndef NXAGENT_SERVER + int rc = + dixLookupWindow(&pWindow, (XID) (intptr_t) closure, pClient, + DixWriteAccess); +#else + pWindow = SecurityLookupWindow((XID) (intptr_t) closure, pClient, DixWriteAccess); + int rc = pWindow ? Success : BadWindow; +#endif + + if (rc == Success) + { + RegionRec exposed; + + RegionNull(&exposed); + RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize); +#ifndef NXAGENT_SERVER + pWindow->drawable.pScreen->PaintWindowBorder(pWindow, &exposed, PW_BORDER); +#else + (*pWindow->drawable.pScreen->PaintWindowBorder)(pWindow, &exposed, PW_BORDER); +#endif + RegionUninit(&exposed); + } + return TRUE; +} + +static int +compSetPixmapVisitWindow (WindowPtr pWindow, void * data) +{ + CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data; + ScreenPtr pScreen = pWindow->drawable.pScreen; + + if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone) + return WT_DONTWALKCHILDREN; + (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap); + /* + * Recompute winSize and borderSize. This is duplicate effort + * when resizing pixmaps, but necessary when changing redirection. + * Might be nice to fix this. + */ + SetWinSize (pWindow); + SetBorderSize (pWindow); + if (HasBorder (pWindow)) + QueueWorkProc (compRepaintBorder, serverClient, + (void *) (intptr_t) pWindow->drawable.id); + return WT_WALKCHILDREN; +} + +void +compSetPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ + CompPixmapVisitRec visitRec; + + visitRec.pWindow = pWindow; + visitRec.pPixmap = pPixmap; + TraverseTree (pWindow, compSetPixmapVisitWindow, (void *) &visitRec); + compCheckTree (pWindow->drawable.pScreen); +} + +Bool +compCheckRedirect (WindowPtr pWin) +{ + CompWindowPtr cw = GetCompWindow (pWin); + CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); + Bool should; + + should = pWin->realized && (pWin->drawable.class != InputOnly) && + (cw != NULL) && (pWin->parent != NULL); + + /* Never redirect the overlay window */ + if (cs->pOverlayWin != NULL) { + if (pWin == cs->pOverlayWin) { + should = FALSE; + } + } + + if (should != (pWin->redirectDraw != RedirectDrawNone)) + { + if (should) + return compAllocPixmap (pWin); + else { + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + + compSetParentPixmap(pWin); + compRestoreWindow(pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + } + } + else if (should) { + if (cw->update == CompositeRedirectAutomatic) + pWin->redirectDraw = RedirectDrawAutomatic; + else + pWin->redirectDraw = RedirectDrawManual; + } + return TRUE; +} + +static int +updateOverlayWindow(ScreenPtr pScreen) +{ + CompScreenPtr cs; + WindowPtr pWin; /* overlay window */ + XID vlist[2]; + int w = pScreen->width; + int h = pScreen->height; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + w = PanoramiXPixWidth; + h = PanoramiXPixHeight; + } +#endif + + cs = GetCompScreen(pScreen); + if ((pWin = cs->pOverlayWin) != NULL) { + if ((pWin->drawable.width == w) && (pWin->drawable.height == h)) + return Success; + + /* Let's resize the overlay window. */ + vlist[0] = w; + vlist[1] = h; + return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin)); + } + + /* Let's be on the safe side and not assume an overlay window is + always allocated. */ + return Success; +} + +Bool +compPositionWindow (WindowPtr pWin, int x, int y) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + Bool ret = TRUE; + + pScreen->PositionWindow = cs->PositionWindow; + /* + * "Shouldn't need this as all possible places should be wrapped + * + compCheckRedirect (pWin); + */ +#ifdef COMPOSITE_DEBUG + if ((pWin->redirectDraw != RedirectDrawNone) != + (pWin->viewable && (GetCompWindow(pWin) != NULL))) + abort (); +#endif + if (pWin->redirectDraw != RedirectDrawNone) + { + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + int bw = wBorderWidth (pWin); + int nx = pWin->drawable.x - bw; + int ny = pWin->drawable.y - bw; + + if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) + { + pPixmap->screen_x = nx; + pPixmap->screen_y = ny; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + } + + if (!(*pScreen->PositionWindow) (pWin, x, y)) + ret = FALSE; + cs->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = compPositionWindow; + compCheckTree (pWin->drawable.pScreen); + if (updateOverlayWindow(pScreen) != Success) + ret = FALSE; + return ret; +} + +Bool +compRealizeWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + Bool ret = TRUE; + + pScreen->RealizeWindow = cs->RealizeWindow; + compCheckRedirect (pWin); + if (!(*pScreen->RealizeWindow) (pWin)) + ret = FALSE; + cs->RealizeWindow = pScreen->RealizeWindow; + pScreen->RealizeWindow = compRealizeWindow; + compCheckTree (pWin->drawable.pScreen); + return ret; +} + +Bool +compUnrealizeWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + Bool ret = TRUE; + + pScreen->UnrealizeWindow = cs->UnrealizeWindow; + compCheckRedirect (pWin); + if (!(*pScreen->UnrealizeWindow) (pWin)) + ret = FALSE; + cs->UnrealizeWindow = pScreen->UnrealizeWindow; + pScreen->UnrealizeWindow = compUnrealizeWindow; + compCheckTree (pWin->drawable.pScreen); + return ret; +} + +/* + * Called after the borderClip for the window has settled down + * We use this to make sure our extra borderClip has the right origin + */ + +void +compClipNotify (WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + CompWindowPtr cw = GetCompWindow (pWin); + + if (cw) + { + if (cw->borderClipX != pWin->drawable.x || + cw->borderClipY != pWin->drawable.y) + { + RegionTranslate(&cw->borderClip, + pWin->drawable.x - cw->borderClipX, + pWin->drawable.y - cw->borderClipY); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; + } + } + if (cs->ClipNotify) + { + pScreen->ClipNotify = cs->ClipNotify; + (*pScreen->ClipNotify) (pWin, dx, dy); + cs->ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = compClipNotify; + } +} + +/* + * Returns TRUE if the window needs server-provided automatic redirect, + * which is true if the child and parent aren't both regular or ARGB visuals + */ + +static Bool +compIsAlternateVisual (ScreenPtr pScreen, + XID visual) +{ + CompScreenPtr cs = GetCompScreen (pScreen); + int i; + + for (i = 0; i < cs->numAlternateVisuals; i++) + if (cs->alternateVisuals[i] == visual) + return TRUE; + return FALSE; +} + +static Bool +compIsImplicitRedirectException(ScreenPtr pScreen, + XID parentVisual, XID winVisual) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + int i; + + for (i = 0; i < cs->numImplicitRedirectExceptions; i++) + if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual && + cs->implicitRedirectExceptions[i].winVisual == winVisual) + return TRUE; + + return FALSE; +} + +static Bool +compImplicitRedirect (WindowPtr pWin, WindowPtr pParent) +{ + if (pParent) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + XID winVisual = wVisual (pWin); + XID parentVisual = wVisual (pParent); + + if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual)) + return FALSE; + + if (winVisual != parentVisual && + (compIsAlternateVisual (pScreen, winVisual) || + compIsAlternateVisual (pScreen, parentVisual))) + return TRUE; + } + return FALSE; +} + +static void +compFreeOldPixmap(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (pWin->redirectDraw != RedirectDrawNone) { + CompWindowPtr cw = GetCompWindow(pWin); + + if (cw->pOldPixmap) { + (*pScreen->DestroyPixmap) (cw->pOldPixmap); + cw->pOldPixmap = NullPixmap; + } + } +} + +void +compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + + compCheckTree (pScreen); + if (pWin->redirectDraw != RedirectDrawNone) { + WindowPtr pParent; + int draw_x, draw_y; + unsigned int w, h, bw; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return; + + bw = wBorderWidth (pWin); + draw_x = pParent->drawable.x + x + (int)bw; + draw_y = pParent->drawable.y + y + (int)bw; + w = pWin->drawable.width; + h = pWin->drawable.height; + compReallocPixmap (pWin, draw_x, draw_y, w, h, bw); + } + compCheckTree (pScreen); + + pScreen->MoveWindow = cs->MoveWindow; + (*pScreen->MoveWindow) (pWin, x, y, pSib, kind); + cs->MoveWindow = pScreen->MoveWindow; + pScreen->MoveWindow = compMoveWindow; + + compFreeOldPixmap(pWin); + compCheckTree (pScreen); +} + +void +compResizeWindow (WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + + compCheckTree (pScreen); + if (pWin->redirectDraw != RedirectDrawNone) + { + WindowPtr pParent; + int draw_x, draw_y; + unsigned int bw; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return; + + bw = wBorderWidth (pWin); + draw_x = pParent->drawable.x + x + (int)bw; + draw_y = pParent->drawable.y + y + (int)bw; + compReallocPixmap (pWin, draw_x, draw_y, w, h, bw); + } + compCheckTree (pScreen); + + pScreen->ResizeWindow = cs->ResizeWindow; + (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib); + cs->ResizeWindow = pScreen->ResizeWindow; + pScreen->ResizeWindow = compResizeWindow; + + compFreeOldPixmap(pWin); + compCheckTree (pWin->drawable.pScreen); +} + +void +compChangeBorderWidth (WindowPtr pWin, unsigned int bw) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + + compCheckTree (pScreen); + if (pWin->redirectDraw != RedirectDrawNone) + { + WindowPtr pParent; + int draw_x, draw_y; + unsigned int w, h; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return; + + draw_x = pWin->drawable.x; + draw_y = pWin->drawable.y; + w = pWin->drawable.width; + h = pWin->drawable.height; + compReallocPixmap (pWin, draw_x, draw_y, w, h, bw); + } + + compCheckTree (pScreen); + pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; + (*pScreen->ChangeBorderWidth) (pWin, bw); + cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; + pScreen->ChangeBorderWidth = compChangeBorderWidth; + + compFreeOldPixmap(pWin); + compCheckTree (pWin->drawable.pScreen); +} + +void +compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + + pScreen->ReparentWindow = cs->ReparentWindow; + /* + * Remove any implicit redirect due to synthesized visual + */ + if (compImplicitRedirect (pWin, pPriorParent)) + compUnredirectWindow (serverClient, pWin, CompositeRedirectAutomatic); + /* + * Handle subwindows redirection + */ + compUnredirectOneSubwindow (pPriorParent, pWin); + compRedirectOneSubwindow (pWin->parent, pWin); + /* + * Add any implict redirect due to synthesized visual + */ + if (compImplicitRedirect (pWin, pWin->parent)) + compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic); + + /* + * Allocate any necessary redirect pixmap + * (this actually should never be true; pWin is always unmapped) + */ + compCheckRedirect (pWin); + + /* + * Reset pixmap pointers as appropriate + */ + if (pWin->parent && pWin->redirectDraw == RedirectDrawNone) + compSetPixmap (pWin, (*pScreen->GetWindowPixmap) (pWin->parent)); + /* + * Call down to next function + */ + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow) (pWin, pPriorParent); + cs->ReparentWindow = pScreen->ReparentWindow; + pScreen->ReparentWindow = compReparentWindow; + compCheckTree (pWin->drawable.pScreen); +} + +void +compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + int dx = 0, dy = 0; + + if (pWin->redirectDraw != RedirectDrawNone) + { + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + CompWindowPtr cw = GetCompWindow (pWin); + + assert (cw->oldx != COMP_ORIGIN_INVALID); + assert (cw->oldy != COMP_ORIGIN_INVALID); + if (cw->pOldPixmap) + { + /* + * Ok, the old bits are available in pOldPixmap and + * need to be copied to pNewPixmap. + */ + RegionRec rgnDst; + GCPtr pGC; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + RegionTranslate(prgnSrc, -dx, -dy); + + RegionNull(&rgnDst); + + RegionIntersect(&rgnDst, + &pWin->borderClip, prgnSrc); + + RegionTranslate(&rgnDst, + -pPixmap->screen_x, -pPixmap->screen_y); + + dx = dx + pPixmap->screen_x - cw->oldx; + dy = dy + pPixmap->screen_y - cw->oldy; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (pGC) + { + BoxPtr pBox = RegionRects (&rgnDst); + int nBox = RegionNumRects (&rgnDst); + + ValidateGC(&pPixmap->drawable, pGC); + while (nBox--) + { + (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable, + &pPixmap->drawable, + pGC, + pBox->x1 + dx, pBox->y1 + dy, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + pBox->x1, pBox->y1); + pBox++; + } + FreeScratchGC (pGC); + } + RegionUninit (&rgnDst); + return; + } + dx = pPixmap->screen_x - cw->oldx; + dy = pPixmap->screen_y - cw->oldy; + ptOldOrg.x += dx; + ptOldOrg.y += dy; + } + + pScreen->CopyWindow = cs->CopyWindow; + if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y) + { + if (dx || dy) + RegionTranslate(prgnSrc, dx, dy); + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + if (dx || dy) + RegionTranslate(prgnSrc, -dx, -dy); + } + else + { + ptOldOrg.x -= dx; + ptOldOrg.y -= dy; + RegionTranslate(prgnSrc, + pWin->drawable.x - ptOldOrg.x, + pWin->drawable.y - ptOldOrg.y); + DamageDamageRegion (&pWin->drawable, prgnSrc); + } + cs->CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = compCopyWindow; + compCheckTree (pWin->drawable.pScreen); +} + +Bool +compCreateWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + Bool ret; + + pScreen->CreateWindow = cs->CreateWindow; + ret = (*pScreen->CreateWindow) (pWin); + if (pWin->parent && ret) + { + CompSubwindowsPtr csw = GetCompSubwindows (pWin->parent); + CompClientWindowPtr ccw; + PixmapPtr parent_pixmap = (*pScreen->GetWindowPixmap)(pWin->parent); + PixmapPtr window_pixmap = (*pScreen->GetWindowPixmap)(pWin); + + if (window_pixmap != parent_pixmap) + (*pScreen->SetWindowPixmap) (pWin, parent_pixmap); + if (csw) + for (ccw = csw->clients; ccw; ccw = ccw->next) + compRedirectWindow (clients[CLIENT_ID(ccw->id)], + pWin, ccw->update); + if (compImplicitRedirect (pWin, pWin->parent)) + compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic); + } + cs->CreateWindow = pScreen->CreateWindow; + pScreen->CreateWindow = compCreateWindow; + compCheckTree (pWin->drawable.pScreen); + return ret; +} + +Bool +compDestroyWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + CompWindowPtr cw; + CompSubwindowsPtr csw; + Bool ret; + + pScreen->DestroyWindow = cs->DestroyWindow; + while ((cw = GetCompWindow (pWin))) + FreeResource (cw->clients->id, RT_NONE); + while ((csw = GetCompSubwindows (pWin))) + FreeResource (csw->clients->id, RT_NONE); + + if (pWin->redirectDraw != RedirectDrawNone) { + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + + compSetParentPixmap (pWin); + (*pScreen->DestroyPixmap) (pPixmap); + } + ret = (*pScreen->DestroyWindow) (pWin); + cs->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = compDestroyWindow; +/* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/ + return ret; +} + +void +compSetRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion) +{ + CompWindowPtr cw = GetCompWindow (pWin); + RegionRec damage; + + RegionNull(&damage); + /* + * Align old border clip with new border clip + */ + RegionTranslate(&cw->borderClip, + pWin->drawable.x - cw->borderClipX, + pWin->drawable.y - cw->borderClipY); + /* + * Compute newly visible portion of window for repaint + */ + RegionSubtract(&damage, pRegion, &cw->borderClip); + /* + * Report that as damaged so it will be redrawn + */ + DamageDamageRegion (&pWin->drawable, &damage); + RegionUninit(&damage); + /* + * Save the new border clip region + */ + RegionCopy(&cw->borderClip, pRegion); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; +} + +RegionPtr +compGetRedirectBorderClip (WindowPtr pWin) +{ + CompWindowPtr cw = GetCompWindow (pWin); + + return &cw->borderClip; +} + +static VisualPtr +compGetWindowVisual (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + VisualID vid = wVisual (pWin); + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + if (pScreen->visuals[i].vid == vid) + return &pScreen->visuals[i]; + return 0; +} + +PictFormatPtr +compWindowFormat (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + return PictureMatchVisual (pScreen, pWin->drawable.depth, + compGetWindowVisual (pWin)); +} + +static void +compWindowUpdateAutomatic (WindowPtr pWin) +{ + CompWindowPtr cw = GetCompWindow (pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent = pWin->parent; + PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin); + PictFormatPtr pSrcFormat = compWindowFormat (pWin); + PictFormatPtr pDstFormat = compWindowFormat (pWin->parent); + int error; + RegionPtr pRegion = DamageRegion (cw->damage); + PicturePtr pSrcPicture = CreatePicture (0, &pSrcPixmap->drawable, + pSrcFormat, + 0, 0, + serverClient, + &error); + XID subwindowMode = IncludeInferiors; + PicturePtr pDstPicture = CreatePicture (0, &pParent->drawable, + pDstFormat, + CPSubwindowMode, + &subwindowMode, + serverClient, + &error); + + /* + * First move the region from window to screen coordinates + */ + RegionTranslate(pRegion, + pWin->drawable.x, pWin->drawable.y); + + /* + * Clip against the "real" border clip + */ + RegionIntersect(pRegion, pRegion, &cw->borderClip); + + /* + * Now translate from screen to dest coordinates + */ + RegionTranslate(pRegion, + -pParent->drawable.x, -pParent->drawable.y); + + /* + * Clip the picture + */ + SetPictureClipRegion (pDstPicture, 0, 0, pRegion); + + /* + * And paint + */ + CompositePicture (PictOpSrc, + pSrcPicture, + 0, + pDstPicture, + 0, 0, /* src_x, src_y */ + 0, 0, /* msk_x, msk_y */ + pSrcPixmap->screen_x - pParent->drawable.x, + pSrcPixmap->screen_y - pParent->drawable.y, + pSrcPixmap->drawable.width, + pSrcPixmap->drawable.height); + FreePicture (pSrcPicture, 0); + FreePicture (pDstPicture, 0); + /* + * Empty the damage region. This has the nice effect of + * rendering the translations above harmless + */ + DamageEmpty (cw->damage); +} + +static void +compPaintWindowToParent(WindowPtr pWin) +{ + compPaintChildrenToWindow(pWin->drawable.pScreen, pWin); + + if (pWin->redirectDraw != RedirectDrawNone) { + CompWindowPtr cw = GetCompWindow(pWin); + + if (cw->damaged) { + compWindowUpdateAutomatic(pWin); + cw->damaged = FALSE; + } + } +} + +void +compPaintChildrenToWindow(ScreenPtr pScreen, WindowPtr pWin) +{ + WindowPtr pChild; + CompScreenPtr cs = GetCompScreen(pScreen); + + if (!cs->damaged) + return; + + for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) + compPaintWindowToParent(pChild); + + cs->damaged = FALSE; +} + +WindowPtr +CompositeRealChildHead(WindowPtr pWin) +{ + WindowPtr pChild, pChildBefore; + CompScreenPtr cs; + + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow(pWin->drawable.pScreen->myNum))) { + + /* First child is the screen saver; see if next child is the overlay */ + pChildBefore = pWin->firstChild; + pChild = pChildBefore->nextSib; + + } + else { + pChildBefore = NullWindow; + pChild = pWin->firstChild; + } + + if (!pChild) { + return NullWindow; + } + + cs = GetCompScreen(pWin->drawable.pScreen); + if (pChild == cs->pOverlayWin) { + return pChild; + } + else { + return pChildBefore; + } +} + +/* ConfigNotify not implemented... replace with the old pixmap reallocation algorithm... */ +/* +int +compConfigNotify(WindowPtr pWin, int x, int y, int w, int h, + int bw, WindowPtr pSib) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + Bool ret = 0; + WindowPtr pParent = pWin->parent; + int draw_x, draw_y; + Bool alloc_ret; + + if (cs->ConfigNotify) { + pScreen->ConfigNotify = cs->ConfigNotify; + ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib); + cs->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = compConfigNotify; + + if (ret) + return ret; + } + + if (pWin->redirectDraw == RedirectDrawNone) + return Success; + + compCheckTree(pScreen); + + draw_x = pParent->drawable.x + x + bw; + draw_y = pParent->drawable.y + y + bw; + alloc_ret = compReallocPixmap(pWin, draw_x, draw_y, w, h, bw); + + if (alloc_ret == FALSE) + return BadAlloc; + return Success; +} +*/ |