From 855b7a27055f5aaead940cd94cf2522566d2f455 Mon Sep 17 00:00:00 2001 From: notbabaisyou Date: Sun, 31 May 2026 20:25:17 +0200 Subject: [PATCH 1/3] wip --- hw/xfree86/compositX/compositx.c | 339 +++++++++++++++++++++++++++++++ hw/xfree86/compositX/compositx.h | 76 +++++++ hw/xfree86/compositX/meson.build | 14 ++ hw/xfree86/compositX/render.c | 117 +++++++++++ hw/xfree86/meson.build | 3 + meson.build | 1 + meson_options.txt | 3 +- 7 files changed, 552 insertions(+), 1 deletion(-) create mode 100644 hw/xfree86/compositX/compositx.c create mode 100644 hw/xfree86/compositX/compositx.h create mode 100644 hw/xfree86/compositX/meson.build create mode 100644 hw/xfree86/compositX/render.c diff --git a/hw/xfree86/compositX/compositx.c b/hw/xfree86/compositX/compositx.c new file mode 100644 index 0000000000..04d20b2f5d --- /dev/null +++ b/hw/xfree86/compositX/compositx.c @@ -0,0 +1,339 @@ +/** + * 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" + +DevPrivateKeyRec compositXScreenPrivateKeyRec; +DevPrivateKeyRec compositXWindowPrivateKeyRec; + +static Atom compositXOpacityAtom; +static Atom compositXBypassAtom; + +static MODULESETUPPROTO(compositXSetup); + +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 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); + + 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); + + /* 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); +} + +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; +} + +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 0000000000..731924a785 --- /dev/null +++ b/hw/xfree86/compositX/compositx.h @@ -0,0 +1,76 @@ +/** + * 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; + + 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 0000000000..320b0018aa --- /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 0000000000..04e204c391 --- /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 b557ab0486..aad446f287 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/meson.build b/meson.build index 1ed5dd83e2..0704920564 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 ee95784941..6f4f5a7871 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') From abe45a5a8582095f8fc6d40ff7809c9967278190 Mon Sep 17 00:00:00 2001 From: notbabaisyou Date: Mon, 1 Jun 2026 23:12:13 +0200 Subject: [PATCH 2/3] wip 2 --- composite/compint.h | 20 -------------------- composite/compositeext.h | 18 ++++++++++++++++++ include/property.h | 2 +- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/composite/compint.h b/composite/compint.h index cb73c386d6..72022fd871 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 27ce7ce408..52acdb3a5a 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/include/property.h b/include/property.h index f4cbdb1aff..84eeb37c1e 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 */ , From 715391214384558675139aadb02d41f7194a76b0 Mon Sep 17 00:00:00 2001 From: notbabaisyou Date: Sat, 6 Jun 2026 10:43:34 +0200 Subject: [PATCH 3/3] test --- hw/xfree86/compositX/compositx.c | 114 +++++++++++++++++++++++++++++++ hw/xfree86/compositX/compositx.h | 1 + 2 files changed, 115 insertions(+) diff --git a/hw/xfree86/compositX/compositx.c b/hw/xfree86/compositX/compositx.c index 04d20b2f5d..37e12a8701 100644 --- a/hw/xfree86/compositX/compositx.c +++ b/hw/xfree86/compositX/compositx.c @@ -25,6 +25,10 @@ #include "propertyst.h" #include "xf86Module.h" +#define ShapeBounding 0 +#define ShapeClip 1 +#define ShapeInput 2 + DevPrivateKeyRec compositXScreenPrivateKeyRec; DevPrivateKeyRec compositXWindowPrivateKeyRec; @@ -33,6 +37,87 @@ 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) { @@ -74,6 +159,24 @@ compositXBlockHandler(void *data, void *pTimeout) 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) { @@ -98,6 +201,7 @@ compositXCloseScreen(ScreenPtr pScreen) CompXUnwrap(cxs, pScreen, DestroyWindow); CompXUnwrap(cxs, pScreen, RealizeWindow); CompXUnwrap(cxs, pScreen, UnrealizeWindow); + CompXUnwrap(cxs, pScreen, SetWindowPixmap); return (*pScreen->CloseScreen)(pScreen); } @@ -260,6 +364,11 @@ compositXScreenSetup(ScreenPtr pScreen) 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); @@ -272,6 +381,7 @@ compositXScreenSetup(ScreenPtr pScreen) CompXWrap(cxs, pScreen, DestroyWindow, compositXDestroyWindow); CompXWrap(cxs, pScreen, RealizeWindow, compositXRealizeWindow); CompXWrap(cxs, pScreen, UnrealizeWindow, compositXUnrealizeWindow); + CompXWrap(cxs, pScreen, SetWindowPixmap, compositXSetWindowPixmap); } static void @@ -319,6 +429,10 @@ compositXSetup(void* module, void* opts, int *errmaj, int *errmin) return module; } +#undef ShapeBounding +#undef ShapeClip +#undef ShapeInput + static XF86ModuleVersionInfo compositXVersRec = { "compositX", "Spaghetti Fork", diff --git a/hw/xfree86/compositX/compositx.h b/hw/xfree86/compositX/compositx.h index 731924a785..d3e1515ef5 100644 --- a/hw/xfree86/compositX/compositx.h +++ b/hw/xfree86/compositX/compositx.h @@ -38,6 +38,7 @@ typedef struct _CompXScreen { DestroyWindowProcPtr DestroyWindow; RealizeWindowProcPtr RealizeWindow; UnrealizeWindowProcPtr UnrealizeWindow; + SetWindowPixmapProcPtr SetWindowPixmap; Bool wrapped; /* guard against double-wrapping */