diff --git a/composite/compint.h b/composite/compint.h
index cb73c386d..72022fd87 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -171,12 +171,7 @@ typedef struct _CompScreen {
SourceValidateProcPtr SourceValidate;
} CompScreenRec, *CompScreenPtr;
-extern DevPrivateKeyRec CompScreenPrivateKeyRec;
-
#define CompScreenPrivateKey (&CompScreenPrivateKeyRec)
-
-extern DevPrivateKeyRec CompWindowPrivateKeyRec;
-
#define CompWindowPrivateKey (&CompWindowPrivateKeyRec)
extern DevPrivateKeyRec CompSubwindowsPrivateKeyRec;
@@ -197,18 +192,9 @@ extern RESTYPE CompositeClientOverlayType;
* 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);
@@ -257,12 +243,6 @@ compFindOverlayClient(ScreenPtr pScreen, ClientPtr pClient);
CompOverlayClientPtr
compCreateOverlayClient(ScreenPtr pScreen, ClientPtr pClient);
-Bool
- compCreateOverlayWindow(ScreenPtr pScreen);
-
-void
- compDestroyOverlayWindow(ScreenPtr pScreen);
-
/*
* compwindow.c
*/
diff --git a/composite/compositeext.h b/composite/compositeext.h
index 27ce7ce40..52acdb3a5 100644
--- a/composite/compositeext.h
+++ b/composite/compositeext.h
@@ -31,6 +31,9 @@
#include "misc.h"
#include "scrnintstr.h"
+extern _X_EXPORT DevPrivateKeyRec CompWindowPrivateKeyRec;
+extern _X_EXPORT DevPrivateKeyRec CompScreenPrivateKeyRec;
+
extern _X_EXPORT Bool CompositeRegisterAlternateVisuals(ScreenPtr pScreen,
VisualID * vids,
int nVisuals);
@@ -45,4 +48,19 @@ Bool CompositeIsImplicitRedirectException(ScreenPtr pScreen,
XID parentVisual, XID winVisual);
extern _X_EXPORT RESTYPE CompositeClientWindowType;
+extern _X_EXPORT Bool
+ compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update);
+
+extern _X_EXPORT int
+ compUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update);
+
+extern _X_EXPORT int
+ compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update);
+
+extern _X_EXPORT Bool
+ compCreateOverlayWindow(ScreenPtr pScreen);
+
+extern _X_EXPORT void
+ compDestroyOverlayWindow(ScreenPtr pScreen);
+
#endif /* _COMPOSITEEXT_H_ */
diff --git a/hw/xfree86/compositX/compositx.c b/hw/xfree86/compositX/compositx.c
new file mode 100644
index 000000000..37e12a870
--- /dev/null
+++ b/hw/xfree86/compositX/compositx.c
@@ -0,0 +1,453 @@
+/**
+ * Spaghetti Display Server
+ * Copyright (C) 2026 SpaghettiFork
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include
+#endif
+
+#include "compositx.h"
+#include "dixstruct.h"
+#include "privates.h"
+#include "propertyst.h"
+#include "xf86Module.h"
+
+#define ShapeBounding 0
+#define ShapeClip 1
+#define ShapeInput 2
+
+DevPrivateKeyRec compositXScreenPrivateKeyRec;
+DevPrivateKeyRec compositXWindowPrivateKeyRec;
+
+static Atom compositXOpacityAtom;
+static Atom compositXBypassAtom;
+
+static MODULESETUPPROTO(compositXSetup);
+
+static RegionPtr
+compositXRegionCopy(RegionPtr pRegion)
+{
+ RegionPtr pNew = RegionCreate(RegionExtents(pRegion),
+ RegionNumRects(pRegion));
+
+ if (!pNew)
+ return NULL;
+
+ if (!RegionCopy(pNew, pRegion)) {
+ RegionDestroy(pNew);
+ return NULL;
+ }
+
+ return pNew;
+}
+
+static void SetWindowShapeRegion(WindowPtr pWin, int kind,
+ int xOff, int yOff, RegionPtr pRegion)
+{
+ RegionPtr *pDestRegion;
+
+ switch (kind) {
+ case ShapeBounding:
+ case ShapeClip:
+ case ShapeInput:
+ break;
+ default:
+ return;
+ }
+
+ if (pRegion) {
+ pRegion = compositXRegionCopy(pRegion);
+ if (!pRegion)
+ return;
+
+ if (!pWin->optional)
+ MakeWindowOptional(pWin);
+
+ switch (kind) {
+ default:
+ case ShapeBounding:
+ pDestRegion = &pWin->optional->boundingShape;
+ break;
+ case ShapeClip:
+ pDestRegion = &pWin->optional->clipShape;
+ break;
+ case ShapeInput:
+ pDestRegion = &pWin->optional->inputShape;
+ break;
+ }
+
+ if (xOff || yOff)
+ RegionTranslate(pRegion, xOff, yOff);
+ } else {
+ if (pWin->optional) {
+ switch (kind) {
+ default:
+ case ShapeBounding:
+ pDestRegion = &pWin->optional->boundingShape;
+ break;
+ case ShapeClip:
+ pDestRegion = &pWin->optional->clipShape;
+ break;
+ case ShapeInput:
+ pDestRegion = &pWin->optional->inputShape;
+ break;
+ }
+ } else {
+ pDestRegion = &pRegion; /* a NULL region pointer */
+ }
+ }
+
+ if (*pDestRegion)
+ RegionDestroy(*pDestRegion);
+
+ *pDestRegion = pRegion;
+ (*pWin->drawable.pScreen->SetShape) (pWin, kind);
+ SendShapeNotify(pWin, kind);
+}
+
+static Bool
+compositXIsBypassed(WindowPtr pWindow)
+{
+ PropertyPtr pProp;
+
+ if (dixLookupProperty(&pProp, pWindow, compositXBypassAtom,
+ serverClient, DixReadAccess) != Success)
+ return FALSE;
+
+ return pProp->format == 32 && pProp->size >= 1 &&
+ *(CARD32 *) pProp->data == 1;
+}
+
+static void
+compositXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+ WindowPtr pWindow = closure;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+
+ RegionUnion(&cxs->pendingDamage, &cxs->pendingDamage, pRegion);
+}
+
+static void
+compositXWakeupHandler(void *data, int result)
+{
+}
+
+static void
+compositXBlockHandler(void *data, void *pTimeout)
+{
+ ScreenPtr pScreen = data;
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+
+ if (!RegionNotEmpty(&cxs->pendingDamage))
+ return;
+
+ compositXRepaint(pScreen);
+ RegionEmpty(&cxs->pendingDamage);
+}
+
+static void
+compositXSetWindowPixmap(WindowPtr pWin, PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ CompXWindowPtr cxw = GetCompXWindow(pWin);
+
+ if (cxw->pDamage)
+ DamageUnregister(cxw->pDamage);
+
+ CompXUnwrap(cxs, pScreen, SetWindowPixmap);
+ (*pScreen->SetWindowPixmap)(pWin, pPixmap);
+ CompXWrap(cxs, pScreen, SetWindowPixmap, compositXSetWindowPixmap);
+
+ if (cxw->pDamage && pWin->realized)
+ DamageRegister(&pWin->drawable, cxw->pDamage);
+}
+
+static Bool
+compositXCloseScreen(ScreenPtr pScreen)
+{
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+
+ RemoveBlockAndWakeupHandlers(compositXBlockHandler,
+ compositXWakeupHandler, pScreen);
+ RegionUninit(&cxs->pendingDamage);
+
+ if (cxs->pOverlayPicture) {
+ FreePicture(cxs->pOverlayPicture, 0);
+ cxs->pOverlayPicture = NULL;
+ }
+
+ if (cxs->pOverlay) {
+ compDestroyOverlayWindow(pScreen);
+ cxs->pOverlay = NULL;
+ }
+
+ CompXUnwrap(cxs, pScreen, CloseScreen);
+ CompXUnwrap(cxs, pScreen, CreateWindow);
+ CompXUnwrap(cxs, pScreen, DestroyWindow);
+ CompXUnwrap(cxs, pScreen, RealizeWindow);
+ CompXUnwrap(cxs, pScreen, UnrealizeWindow);
+ CompXUnwrap(cxs, pScreen, SetWindowPixmap);
+
+ return (*pScreen->CloseScreen)(pScreen);
+}
+
+static Bool
+compositXCreateWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ CompXWindowPtr cxw = GetCompXWindow(pWindow);
+ Bool ret;
+
+ CompXUnwrap(cxs, pScreen, CreateWindow);
+ ret = (*pScreen->CreateWindow)(pWindow);
+ CompXWrap(cxs, pScreen, CreateWindow, compositXCreateWindow);
+
+ if (ret) {
+ cxw->opacity = COMPOSITX_OPAQUE;
+ cxw->bypass = FALSE;
+ cxw->pDamage = NULL;
+ }
+
+ return ret;
+}
+
+static Bool
+compositXDestroyWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;;
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ CompXWindowPtr cxw = GetCompXWindow(pWindow);
+
+ CompXUnwrap(cxs, pScreen, DestroyWindow);
+ (*pScreen->DestroyWindow)(pWindow);
+ CompXWrap(cxs, pScreen, DestroyWindow, compositXDestroyWindow);
+
+ /* damage may still be live if the window is destroyed while mapped */
+ if (cxw->pDamage) {
+ DamageDestroy(cxw->pDamage);
+ cxw->pDamage = NULL;
+ }
+
+ return TRUE;
+}
+
+static Bool
+compositXRealizeWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ CompXWindowPtr cxw = GetCompXWindow(pWindow);
+ Bool ret;
+
+ CompXUnwrap(cxs, pScreen, RealizeWindow);
+ ret = (*pScreen->RealizeWindow)(pWindow);
+ CompXWrap(cxs, pScreen, RealizeWindow, compositXRealizeWindow);
+
+ if (ret && !cxw->pDamage) {
+ cxw->bypass = compositXIsBypassed(pWindow);
+ if (cxw->bypass) {
+ compUnredirectWindow(serverClient, pWindow, CompositeRedirectManual);
+ } else {
+ cxw->pDamage = DamageCreate(compositXDamageReport,
+ NULL,
+ DamageReportRawRegion,
+ TRUE,
+ pScreen,
+ pWindow);
+ if (cxw->pDamage)
+ DamageRegister(&pWindow->drawable, cxw->pDamage);
+ }
+ }
+
+ return ret;
+}
+
+static Bool
+compositXUnrealizeWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ CompXWindowPtr cxw = GetCompXWindow(pWindow);
+ Bool ret;
+
+ if (cxw->bypass) {
+ compRedirectWindow(serverClient, pWindow, CompositeRedirectManual);
+ cxw->bypass = FALSE;
+ }
+
+ CompXUnwrap(cxs, pScreen, UnrealizeWindow);
+ ret = (*pScreen->UnrealizeWindow)(pWindow);
+ CompXWrap(cxs, pScreen, UnrealizeWindow, compositXUnrealizeWindow);
+
+ return ret;
+}
+
+static void
+compositXPropertyCallback(CallbackListPtr *pcbl, void *unused, void *data)
+{
+ PropertyStateRec *rec = data;
+ CompXWindowPtr cxw = GetCompXWindow(rec->win);
+ Bool bypass;
+
+ if (rec->prop->propertyName == compositXOpacityAtom) {
+ if (rec->state == PropertyNewValue && rec->prop->size >= 1)
+ cxw->opacity = *(CARD32 *) rec->prop->data;
+ else
+ cxw->opacity = COMPOSITX_OPAQUE;
+ return;
+ }
+
+ if (rec->prop->propertyName == compositXBypassAtom) {
+ bypass = (rec->state == PropertyNewValue &&
+ rec->prop->size >= 1 &&
+ *(CARD32 *) rec->prop->data == 1);
+
+ if (bypass == cxw->bypass || !rec->win->mapped)
+ return;
+
+ cxw->bypass = bypass;
+
+ if (bypass) {
+ if (cxw->pDamage) {
+ DamageUnregister(cxw->pDamage);
+ DamageDestroy(cxw->pDamage);
+ cxw->pDamage = NULL;
+ }
+ compUnredirectWindow(serverClient, rec->win, CompositeRedirectManual);
+ } else {
+ ScreenPtr pScreen = rec->win->drawable.pScreen;
+
+ compRedirectWindow(serverClient, rec->win, CompositeRedirectManual);
+ cxw->pDamage = DamageCreate(compositXDamageReport, NULL,
+ DamageReportRawRegion, TRUE,
+ pScreen, rec->win);
+ if (cxw->pDamage)
+ DamageRegister(&rec->win->drawable, cxw->pDamage);
+ }
+ }
+}
+
+static void
+compositXScreenSetup(ScreenPtr pScreen)
+{
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ CompScreenPtr cs = GetCompScreen(pScreen);
+ BoxRec screenBox = {0, 0, pScreen->width, pScreen->height};
+
+ if (!cs)
+ return;
+
+ if (cs->pOverlayWin == NULL)
+ if (!compCreateOverlayWindow(pScreen))
+ return;
+
+ if (cxs->wrapped)
+ return;
+
+ cxs->wrapped = TRUE;
+ cxs->pOverlay = cs->pOverlayWin;
+ compositXInitOverlay(pScreen);
+
+ /* Ignore all inputs on the overlay. */
+ RegionPtr pEmpty = RegionCreate(NULL, 0);
+ SetWindowShapeRegion(cxs->pOverlay, ShapeInput, 0, 0, pEmpty);
+ RegionDestroy(pEmpty);
+
+ /* manual: the Composite extension will not auto-paint redirected windows */
+ compRedirectSubwindows(serverClient, pScreen->root, CompositeRedirectManual);
+
+ RegionInit(&cxs->pendingDamage, &screenBox, 1);
+ RegisterBlockAndWakeupHandlers(compositXBlockHandler,
+ compositXWakeupHandler, pScreen);
+
+ CompXWrap(cxs, pScreen, CloseScreen, compositXCloseScreen);
+ CompXWrap(cxs, pScreen, CreateWindow, compositXCreateWindow);
+ CompXWrap(cxs, pScreen, DestroyWindow, compositXDestroyWindow);
+ CompXWrap(cxs, pScreen, RealizeWindow, compositXRealizeWindow);
+ CompXWrap(cxs, pScreen, UnrealizeWindow, compositXUnrealizeWindow);
+ CompXWrap(cxs, pScreen, SetWindowPixmap, compositXSetWindowPixmap);
+}
+
+static void
+compositXInitBlockHandler(void *data, void *pTimeout)
+{
+ RemoveBlockAndWakeupHandlers(compositXInitBlockHandler,
+ compositXWakeupHandler, NULL);
+
+ for (int i = 0; i < screenInfo.numScreens; i++)
+ compositXScreenSetup(screenInfo.screens[i]);
+}
+
+static void*
+compositXSetup(void* module, void* opts, int *errmaj, int *errmin)
+{
+ static Bool initialized = FALSE;
+
+ if (initialized) {
+ if (errmaj) *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+ initialized = TRUE;
+
+ if (!dixRegisterPrivateKey(&compositXScreenPrivateKeyRec,
+ PRIVATE_SCREEN,
+ sizeof(CompXScreenRec)) ||
+ !dixRegisterPrivateKey(&compositXWindowPrivateKeyRec,
+ PRIVATE_WINDOW,
+ sizeof(CompXWindowRec))) {
+ if (errmaj) *errmaj = LDR_NOMEM;
+ return NULL;
+ }
+
+ compositXOpacityAtom = MakeAtom("_NET_WM_WINDOW_OPACITY",
+ sizeof("_NET_WM_WINDOW_OPACITY") - 1,
+ TRUE);
+ compositXBypassAtom = MakeAtom("_NET_WM_BYPASS_COMPOSITOR",
+ sizeof("_NET_WM_BYPASS_COMPOSITOR") - 1,
+ TRUE);
+
+ RegisterBlockAndWakeupHandlers(compositXInitBlockHandler,
+ compositXWakeupHandler, NULL);
+ AddCallback(&PropertyStateCallback, compositXPropertyCallback, NULL);
+
+ return module;
+}
+
+#undef ShapeBounding
+#undef ShapeClip
+#undef ShapeInput
+
+static XF86ModuleVersionInfo compositXVersRec = {
+ "compositX",
+ "Spaghetti Fork",
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_EXTENSION,
+ ABI_EXTENSION_VERSION,
+ MOD_CLASS_EXTENSION,
+ {0, 0, 0, 0}
+};
+
+_X_EXPORT XF86ModuleData compositxModuleData = {
+ &compositXVersRec,
+ compositXSetup,
+ NULL
+};
\ No newline at end of file
diff --git a/hw/xfree86/compositX/compositx.h b/hw/xfree86/compositX/compositx.h
new file mode 100644
index 000000000..d3e1515ef
--- /dev/null
+++ b/hw/xfree86/compositX/compositx.h
@@ -0,0 +1,77 @@
+/**
+ * Spaghetti Display Server
+ * Copyright (C) 2026 SpaghettiFork
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifndef COMPOSITX_H
+#define COMPOSITX_H
+
+#ifdef HAVE_DIX_CONFIG_H
+#include
+#endif
+
+#include
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "damage.h"
+#include "compint.h"
+#include "picturestr.h"
+
+/* sentinel for windows without _NET_WM_WINDOW_OPACITY */
+#define COMPOSITX_OPAQUE 0xffffffffU
+
+typedef struct _CompXScreen {
+ CloseScreenProcPtr CloseScreen;
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ SetWindowPixmapProcPtr SetWindowPixmap;
+
+ Bool wrapped; /* guard against double-wrapping */
+
+ WindowPtr pOverlay;
+ PicturePtr pOverlayPicture; /* cached destination; freed in CloseScreen */
+ RegionRec pendingDamage; /* accumulated dirty region, drained in block handler */
+} CompXScreenRec, *CompXScreenPtr;
+
+typedef struct _CompXWindow {
+ CARD32 opacity; /* _NET_WM_WINDOW_OPACITY value; COMPOSITX_OPAQUE if absent */
+ Bool bypass; /* _NET_WM_BYPASS_COMPOSITOR == 1 */
+ DamagePtr pDamage;
+} CompXWindowRec, *CompXWindowPtr;
+
+extern DevPrivateKeyRec compositXScreenPrivateKeyRec;
+extern DevPrivateKeyRec compositXWindowPrivateKeyRec;
+
+#define GetCompXScreen(s) \
+ ((CompXScreenPtr) dixLookupPrivate(&(s)->devPrivates, \
+ &compositXScreenPrivateKeyRec))
+#define GetCompXWindow(w) \
+ ((CompXWindowPtr) dixLookupPrivate(&(w)->devPrivates, \
+ &compositXWindowPrivateKeyRec))
+
+#define CompXWrap(priv, real, field, func) do { \
+ (priv)->field = (real)->field; \
+ (real)->field = (func); \
+} while (0)
+
+#define CompXUnwrap(priv, real, field) \
+ ((real)->field = (priv)->field)
+
+void compositXInitOverlay(ScreenPtr pScreen);
+void compositXRepaint(ScreenPtr pScreen);
+
+#endif /* COMPOSITX_H */
\ No newline at end of file
diff --git a/hw/xfree86/compositX/meson.build b/hw/xfree86/compositX/meson.build
new file mode 100644
index 000000000..320b0018a
--- /dev/null
+++ b/hw/xfree86/compositX/meson.build
@@ -0,0 +1,14 @@
+sources = [
+ 'compositx.c',
+ 'render.c',
+]
+
+shared_module('compositx',
+ sources,
+ include_directories: [ inc, xorg_inc ],
+ dependencies: common_dep,
+ link_with: [ xorg_server ],
+ c_args: xorg_c_args,
+ install: true,
+ install_dir: module_dir,
+)
\ No newline at end of file
diff --git a/hw/xfree86/compositX/render.c b/hw/xfree86/compositX/render.c
new file mode 100644
index 000000000..04e204c39
--- /dev/null
+++ b/hw/xfree86/compositX/render.c
@@ -0,0 +1,117 @@
+/**
+ * Spaghetti Display Server
+ * Copyright (C) 2026 SpaghettiFork
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include
+#endif
+
+#include "compositx.h"
+#include "picturestr.h"
+#include "dixstruct.h"
+
+static PictFormatPtr
+compositXFormatForVisual(ScreenPtr pScreen, int depth, VisualID vid)
+{
+ for (int i = 0; i < pScreen->numVisuals; i++) {
+ if (pScreen->visuals[i].vid == vid)
+ return PictureMatchVisual(pScreen, depth, &pScreen->visuals[i]);
+ }
+
+ return NULL;
+}
+
+static PicturePtr
+compositXSolidAlpha(CARD16 alpha)
+{
+ xRenderColor color = { 0, 0, 0, alpha };
+ int error;
+ return CreateSolidPicture(0, &color, &error);
+}
+
+void
+compositXInitOverlay(ScreenPtr pScreen)
+{
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ PictFormatPtr pFormat;
+ int error;
+
+ if (!cxs->pOverlay)
+ return;
+
+ pFormat = compositXFormatForVisual(pScreen, cxs->pOverlay->drawable.depth,
+ wVisual(cxs->pOverlay));
+ if (!pFormat)
+ return;
+
+ cxs->pOverlayPicture = CreatePicture(0, &cxs->pOverlay->drawable, pFormat,
+ 0, NULL, serverClient, &error);
+}
+
+void
+compositXRepaint(ScreenPtr pScreen)
+{
+ CompXScreenPtr cxs = GetCompXScreen(pScreen);
+ PicturePtr pClear, pSrc, pMask;
+ PictFormatPtr pFormat;
+ PixmapPtr pPixmap;
+ CompXWindowPtr cxw;
+ WindowPtr pChild;
+ int error;
+
+ if (!cxs->pOverlayPicture)
+ return;
+
+ pClear = compositXSolidAlpha(0);
+ CompositePicture(PictOpSrc, pClear, NULL, cxs->pOverlayPicture,
+ 0, 0, 0, 0, 0, 0, pScreen->width, pScreen->height);
+ FreePicture(pClear, 0);
+
+ for (pChild = pScreen->root->lastChild; pChild; pChild = pChild->prevSib) {
+ cxw = GetCompXWindow(pChild);
+
+ if (!pChild->mapped || !GetCompWindow(pChild) || cxw->bypass)
+ continue;
+
+ pPixmap = (*pScreen->GetWindowPixmap)(pChild);
+ if (!pPixmap)
+ continue;
+
+ pFormat = compositXFormatForVisual(pScreen, pChild->drawable.depth,
+ wVisual(pChild));
+ if (!pFormat)
+ continue;
+
+ pSrc = CreatePicture(0, &pPixmap->drawable, pFormat,
+ 0, NULL, serverClient, &error);
+ if (!pSrc)
+ continue;
+
+ pMask = (cxw->opacity != COMPOSITX_OPAQUE)
+ ? compositXSolidAlpha((CARD16)(cxw->opacity >> 16))
+ : NULL;
+
+ CompositePicture(PictOpOver,
+ pSrc, pMask, cxs->pOverlayPicture,
+ 0, 0, 0, 0,
+ pChild->drawable.x, pChild->drawable.y,
+ pChild->drawable.width, pChild->drawable.height);
+
+ FreePicture(pSrc, 0);
+ if (pMask)
+ FreePicture(pMask, 0);
+ }
+}
\ No newline at end of file
diff --git a/hw/xfree86/meson.build b/hw/xfree86/meson.build
index b557ab048..aad446f28 100644
--- a/hw/xfree86/meson.build
+++ b/hw/xfree86/meson.build
@@ -131,6 +131,9 @@ subdir('shadowfb')
if build_vgahw
subdir('vgahw')
endif
+if build_compositx
+ subdir('compositX')
+endif
if build_fission
subdir('drivers/fission')
endif
diff --git a/include/property.h b/include/property.h
index f4cbdb1af..84eeb37c1 100644
--- a/include/property.h
+++ b/include/property.h
@@ -57,7 +57,7 @@ typedef struct _PropertyStateRec {
int state;
} PropertyStateRec;
-extern CallbackListPtr PropertyStateCallback;
+extern _X_EXPORT CallbackListPtr PropertyStateCallback;
extern _X_EXPORT int dixLookupProperty(PropertyPtr * /*result */ ,
WindowPtr /*pWin */ ,
diff --git a/meson.build b/meson.build
index 1ed5dd83e..070492056 100644
--- a/meson.build
+++ b/meson.build
@@ -358,6 +358,7 @@ if build_glamor
epoxy_dep = dependency('epoxy', required: false)
endif
+build_compositx = get_option('compositx') and compositeproto_dep.found()
# Lots of sha1 options, because Linux is about choice :)
# The idea behind the ordering here is that we should first prefer system
diff --git a/meson_options.txt b/meson_options.txt
index ee9578494..6f4f5a787 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -12,7 +12,8 @@ option('xwin', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto',
description: 'Enable XWin X server')
option('xquartz', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto',
description: 'Enable Xquartz X server')
-
+option('compositx', type: 'boolean', value: true,
+ description: 'Enable compositX, the built-in compositor')
option('builder_addr', type: 'string', description: 'Builder address', value: 'xorg@lists.freedesktop.org')
option('builder_string', type: 'string', description: 'Additional builder string')