From 159183c8a07697c0a73325b1c2a68c7ef217bf94 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Wed, 19 Mar 2025 10:50:56 +0100 Subject: [PATCH] Xnamespace: create per-namespace fake root windows For each namespace creating a fake (invisible) root window, which can be used for storing per-namespace properties (eg. cut buffers), etc. Signed-off-by: Enrico Weigelt, metux IT consult --- Xext/namespace/hook-init-rootwindow.c | 71 +++++++++++++++++++++++++++ Xext/namespace/hooks.h | 1 + Xext/namespace/meson.build | 1 + Xext/namespace/namespace.c | 1 + Xext/namespace/namespace.h | 2 + 5 files changed, 76 insertions(+) create mode 100644 Xext/namespace/hook-init-rootwindow.c diff --git a/Xext/namespace/hook-init-rootwindow.c b/Xext/namespace/hook-init-rootwindow.c new file mode 100644 index 000000000..2d7a8c067 --- /dev/null +++ b/Xext/namespace/hook-init-rootwindow.c @@ -0,0 +1,71 @@ +#define HOOK_NAME "initroot" + +#include + +#include +#include +#include + +#include "dix/window_priv.h" + +#include "namespace.h" +#include "hooks.h" + +static inline int setWinStrProp(WindowPtr pWin, Atom name, const char *text) { + return dixChangeWindowProperty(serverClient, pWin, name, XA_STRING, + 8, PropModeReplace, strlen(text), text, TRUE); +} + +void hookInitRootWindow(CallbackListPtr *pcbl, void *data, void *screen) +{ + ScreenPtr pScreen = (ScreenPtr)screen; + + // only act on first screen + if (pScreen->myNum) + return; + + /* create the virtual root windows */ + WindowPtr realRoot = pScreen->root; + + assert(realRoot); + + struct Xnamespace *walk; + + xorg_list_for_each_entry(walk, &ns_list, entry) { + if (strcmp(walk->name, NS_NAME_ROOT)==0) { + walk->rootWindow = realRoot; + XNS_LOG("<%s> actual root 0x%0x\n", walk->name, walk->rootWindow->drawable.id); + continue; + } + + int rc = 0; + WindowPtr pWin = dixCreateWindow( + FakeClientID(0), realRoot, 0, 0, 23, 23, + 0, /* bw */ + InputOutput, + 0, /* vmask */ + NULL, /* vlist */ + 0, /* depth */ + serverClient, + wVisual(realRoot), /* visual */ + &rc); + + if (!pWin) + FatalError("hookInitRootWindow: cant create per-namespace root window for %s\n", walk->name); + + Mask mask = pWin->eventMask; + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(pWin->drawable.id, X11_RESTYPE_WINDOW, (void *) pWin)) + FatalError("hookInitRootWindow: cant add per-namespace root window as resource\n"); + pWin->eventMask = mask; + + walk->rootWindow = pWin; + + // set window name + char buf[PATH_MAX] = { 0 }; + snprintf(buf, sizeof(buf)-1, "XNS-ROOT:%s", walk->name); + setWinStrProp(pWin, XA_WM_NAME, buf); + + XNS_LOG("<%s> virtual root 0x%0x\n", walk->name, walk->rootWindow->drawable.id); + } +} diff --git a/Xext/namespace/hooks.h b/Xext/namespace/hooks.h index d06408c52..9f08f6199 100644 --- a/Xext/namespace/hooks.h +++ b/Xext/namespace/hooks.h @@ -25,6 +25,7 @@ struct XnamespaceClientPriv *subj = XnsClientPriv(client); void hookClientState(CallbackListPtr *pcbl, void *unused, void *calldata); +void hookInitRootWindow(CallbackListPtr *pcbl, void *unused, void *calldata); void hookSelectionFilter(CallbackListPtr *pcbl, void *unused, void *calldata); #endif /* __XSERVER_NAMESPACE_HOOKS_H */ diff --git a/Xext/namespace/meson.build b/Xext/namespace/meson.build index 165882231..75a8a12ab 100644 --- a/Xext/namespace/meson.build +++ b/Xext/namespace/meson.build @@ -3,6 +3,7 @@ libxserver_namespace = static_library( [ 'config.c', 'hook-clientstate.c', + 'hook-init-rootwindow.c', 'hook-selection.c', 'namespace.c', ], diff --git a/Xext/namespace/namespace.c b/Xext/namespace/namespace.c index b2aa59913..496e0a87d 100644 --- a/Xext/namespace/namespace.c +++ b/Xext/namespace/namespace.c @@ -29,6 +29,7 @@ NamespaceExtensionInit(void) if (!(dixRegisterPrivateKey(&namespaceClientPrivKeyRec, PRIVATE_CLIENT, sizeof(struct XnamespaceClientPriv)) && AddCallback(&ClientStateCallback, hookClientState, NULL) && + AddCallback(&PostInitRootWindowCallback, hookInitRootWindow, NULL) && AddCallback(&SelectionFilterCallback, hookSelectionFilter, NULL))) FatalError("NamespaceExtensionInit: allocation failure\n"); diff --git a/Xext/namespace/namespace.h b/Xext/namespace/namespace.h index acabe1060..5bf9ba7f8 100644 --- a/Xext/namespace/namespace.h +++ b/Xext/namespace/namespace.h @@ -8,6 +8,7 @@ #include "include/list.h" #include "include/privates.h" #include "include/window.h" +#include "include/windowstr.h" struct Xnamespace { struct xorg_list entry; @@ -18,6 +19,7 @@ struct Xnamespace { char *authTokenData; size_t authTokenLen; size_t refcnt; + WindowPtr rootWindow; }; extern struct xorg_list ns_list;