xserver/dix/connsetup.c
Enrico Weigelt, metux IT consult 21f82727a4 Xext: panoramiX: let PanoramiXCreateConnectionBlock() return rpcbuf
Let PanoramiXCreateConnectionBlock() only return x_rpcbuf_t, not touching
global structures anymore - it's caller will that now.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2026-09-29 16:11:03 +02:00

234 lines
7.2 KiB
C

/* SPDX-License-Identifier: X11 OR MIT OR AGPL-3.0-or-later
*
* Copyright © 2026 Enrico Weigelt, metux IT consult <info@metux.net>
*/
#include <dix-config.h>
#include <stdbool.h>
#include <stddef.h>
#include <version-config.h>
#include <X11/Xproto.h>
#include "include/misc.h"
#include "include/windowstr.h"
#include "dix/client_priv.h"
#include "dix/dix_priv.h"
#include "dix/rpcbuf_priv.h"
#include "dix/screenint_priv.h"
#include "dix/server_priv.h"
#include "dix/window_priv.h"
#include "Xext/panoramiX/panoramiXsrv.h"
#include "Xext/panoramiX/panoramiX_priv.h"
size_t ConnectionInfoSize = 0;
void dixSendConnAbort(ClientPtr pClient, const char *reason)
{
xConnSetupPrefix csp = {
.success = xFalse,
.lengthReason = strlen(reason),
.length = bytes_to_int32(csp.lengthReason),
.majorVersion = X_PROTOCOL,
.minorVersion = X_PROTOCOL_REVISION,
};
if (pClient->swapped) {
swaps(&csp.majorVersion);
swaps(&csp.minorVersion);
swaps(&csp.length);
}
dixWriteToClient(pClient, sizeof(csp), &csp);
dixWriteToClient(pClient, (int) csp.lengthReason, reason);
pClient->noClientException = -1;
}
size_t dixConnBlockScreenStart(const char *connInfo)
{
const xConnSetup *setup = (const xConnSetup *)connInfo;
return (
sizeof(xConnSetup) +
pad_to_int32(setup->nbytesVendor) +
setup->numFormats * sizeof(xPixmapFormat));
}
void dixInitConnectionBlock(void)
{
free(ConnectionInfo);
ConnectionInfo = NULL;
ConnectionInfoSize = 0;
x_rpcbuf_t rpcbuf = { 0 };
#ifdef XINERAMA
if (PanoramiXIsEnabled()) {
screenInfo.numRoots = 1;
rpcbuf = PanoramiXCreateConnectionBlock();
} else
#endif /* XINERAMA */
{
screenInfo.numRoots = screenInfo.numScreens;
rpcbuf = dixBuildConnectionBlock(screenInfo.numScreens);
}
if (rpcbuf.error)
FatalError("could not create connection block info");
/* must not free the rpcbuf here, because we store the data elsewhere */
ConnectionInfo = rpcbuf.buffer;
ConnectionInfoSize = rpcbuf.wpos;
}
void x_rpcbuf_write_xWindowRoot(x_rpcbuf_t *rpcbuf, ScreenPtr pScreen)
{
xWindowRoot root = {
.windowId = pScreen->root->drawable.id,
.defaultColormap = pScreen->defColormap,
.whitePixel = pScreen->whitePixel,
.blackPixel = pScreen->blackPixel,
.currentInputMask = 0, /* filled in when sent */
.pixWidth = pScreen->width,
.pixHeight = pScreen->height,
.mmWidth = pScreen->mmWidth,
.mmHeight = pScreen->mmHeight,
.minInstalledMaps = pScreen->minInstalledCmaps,
.maxInstalledMaps = pScreen->maxInstalledCmaps,
.rootVisualID = pScreen->rootVisual,
.backingStore = pScreen->backingStoreSupport,
.saveUnders = FALSE,
.rootDepth = pScreen->rootDepth,
.nDepths = pScreen->numDepths,
};
x_rpcbuf_write_CARD8s(rpcbuf, (CARD8*)&root, sizeof(root));
};
void x_rpcbuf_write_xDepth(x_rpcbuf_t *rpcbuf, DepthPtr pDepth)
{
/* write the xDepth header */
xDepth depth = {
.depth = pDepth->depth,
.nVisuals = pDepth->numVids,
};
x_rpcbuf_write_CARD8s(rpcbuf, (CARD8*)&depth, sizeof(depth));
}
void x_rpcbuf_write_xVisualInfo(x_rpcbuf_t *rpcbuf, VisualPtr pVisual)
{
xVisualType visual = {
.visualID = pVisual->vid,
.class = pVisual->class,
.bitsPerRGB = pVisual->bitsPerRGBValue,
.colormapEntries = pVisual->ColormapEntries,
.redMask = pVisual->redMask,
.greenMask = pVisual->greenMask,
.blueMask = pVisual->blueMask,
};
x_rpcbuf_write_CARD8s(rpcbuf, (CARD8*)&visual, sizeof(visual));
}
void x_rpcbuf_write_xPixmapFormat(x_rpcbuf_t *rpcbuf, PixmapFormatPtr pPixmapFormat)
{
xPixmapFormat format = {
.depth = pPixmapFormat->depth,
.bitsPerPixel = pPixmapFormat->bitsPerPixel,
.scanLinePad = pPixmapFormat->scanlinePad,
};
x_rpcbuf_write_CARD8s(rpcbuf, (CARD8*)&format, sizeof(format));
}
x_rpcbuf_t dixBuildConnectionBlock(int maxscreens)
{
const char VendorString[] = "XLibre";
if (!maxscreens) {
maxscreens = screenInfo.numScreens;
}
x_rpcbuf_t rpcbuf = { 0 };
xConnSetup setup = {
/* Leave off the ridBase and ridMask, these must be sent with
connection */
.release = VENDOR_RELEASE,
/*
* per-server image and bitmap parameters are defined in Xmd.h
*/
.imageByteOrder = screenInfo.imageByteOrder,
.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit,
.bitmapScanlinePad = screenInfo.bitmapScanlinePad,
.bitmapBitOrder = screenInfo.bitmapBitOrder,
.motionBufferSize = NumMotionEvents(),
.numRoots = maxscreens,
.nbytesVendor = strlen(VendorString),
.numFormats = screenInfo.numPixmapFormats,
.maxRequestSize = MAX_REQUEST_SIZE,
};
QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
x_rpcbuf_write_CARD8s(&rpcbuf, (CARD8*)&setup, sizeof(setup));
x_rpcbuf_write_string_pad(&rpcbuf, VendorString);
for (int i = 0; i < screenInfo.numPixmapFormats; i++) {
x_rpcbuf_write_xPixmapFormat(&rpcbuf, &(screenInfo.formats[i]));
}
DIX_FOR_N_SCREENS(0, maxscreens, {
x_rpcbuf_write_xWindowRoot(&rpcbuf, walkScreen);
DepthPtr pDepth = walkScreen->allowedDepths;
for (int j = 0; j < walkScreen->numDepths; j++, pDepth++) {
x_rpcbuf_write_xDepth(&rpcbuf, pDepth);
for (int k = 0; k < pDepth->numVids; k++) {
unsigned long vid = pDepth->vids[k];
VisualPtr pVisual;
for (pVisual = walkScreen->visuals;
pVisual->vid != vid; pVisual++);
x_rpcbuf_write_xVisualInfo(&rpcbuf, pVisual);
}
}
});
return rpcbuf;
}
char *dixNewConnectionInfoBlock(ClientPtr pClient, size_t *sz, size_t *scrOffset)
{
if (!ConnectionInfo)
return NULL;
char *newone = malloc(ConnectionInfoSize);
if (!newone)
return NULL;
memcpy(newone, ConnectionInfo, ConnectionInfoSize);
((xConnSetup *)newone)->ridBase = pClient->clientAsMask;
((xConnSetup *)newone)->ridMask = RESOURCE_ID_MASK;
/* fill in the "currentInputMask" */
/* attention: this still depends on setup block screens matching screenInfo.screens */
xWindowRoot *root = (xWindowRoot *) (newone + dixConnBlockScreenStart(newone));
int numScreens = ((xConnSetup *) newone)->numRoots;
for (unsigned int walkScreenIdx = 0; walkScreenIdx < numScreens; walkScreenIdx++) {
ScreenPtr walkScreen = screenInfo.screens[walkScreenIdx];
WindowPtr pRoot = walkScreen->root;
root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
xDepth *pDepth = (xDepth *) (root + 1);
for (unsigned int j = 0; j < root->nDepths; j++) {
pDepth = (xDepth *) (((char *) (pDepth + 1)) +
pDepth->nVisuals * sizeof(xVisualType));
}
root = (xWindowRoot *) pDepth;
}
if (sz)
*sz = ConnectionInfoSize;
if (scrOffset)
*scrOffset = dixConnBlockScreenStart(newone);
return newone;
}