diff options
Diffstat (limited to 'xorg-server/pseudoramiX/pseudoramiX.c')
-rw-r--r-- | xorg-server/pseudoramiX/pseudoramiX.c | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/xorg-server/pseudoramiX/pseudoramiX.c b/xorg-server/pseudoramiX/pseudoramiX.c new file mode 100644 index 000000000..23dbc7328 --- /dev/null +++ b/xorg-server/pseudoramiX/pseudoramiX.c @@ -0,0 +1,516 @@ +/* + * Minimal implementation of PanoramiX/Xinerama + * + * This is used in rootless mode where the underlying window server + * already provides an abstracted view of multiple screens as one + * large screen area. + * + * This code is largely based on panoramiX.c, which contains the + * following copyright notice: + */ +/***************************************************************** + Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + 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. + + The above copyright notice and this permission notice 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 + DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, + BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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. + + Except as contained in this notice, the name of Digital Equipment Corporation + shall not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization from Digital + Equipment Corporation. + ******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "pseudoramiX.h" +#include "extnsionst.h" +#include "extinit.h" +#include "dixstruct.h" +#include "window.h" +#include <X11/extensions/panoramiXproto.h> +#include "globals.h" + +#define TRACE PseudoramiXTrace("TRACE " __FILE__ ":%s",__FUNCTION__) +#define DEBUG_LOG PseudoramiXDebug + +Bool noPseudoramiXExtension = FALSE; + +extern int +ProcPanoramiXQueryVersion(ClientPtr client); + +static void +PseudoramiXResetProc(ExtensionEntry *extEntry); + +static int +ProcPseudoramiXQueryVersion(ClientPtr client); +static int +ProcPseudoramiXGetState(ClientPtr client); +static int +ProcPseudoramiXGetScreenCount(ClientPtr client); +static int +ProcPseudoramiXGetScreenSize(ClientPtr client); +static int +ProcPseudoramiXIsActive(ClientPtr client); +static int +ProcPseudoramiXQueryScreens(ClientPtr client); +static int +ProcPseudoramiXDispatch(ClientPtr client); + +static int +SProcPseudoramiXQueryVersion(ClientPtr client); +static int +SProcPseudoramiXGetState(ClientPtr client); +static int +SProcPseudoramiXGetScreenCount(ClientPtr client); +static int +SProcPseudoramiXGetScreenSize(ClientPtr client); +static int +SProcPseudoramiXIsActive(ClientPtr client); +static int +SProcPseudoramiXQueryScreens(ClientPtr client); +static int +SProcPseudoramiXDispatch(ClientPtr client); + +typedef struct { + int x; + int y; + int w; + int h; +} PseudoramiXScreenRec; + +static PseudoramiXScreenRec *pseudoramiXScreens = NULL; +static int pseudoramiXScreensAllocated = 0; +static int pseudoramiXNumScreens = 0; +static unsigned long pseudoramiXGeneration = 0; + +static void +PseudoramiXTrace(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(X_NONE, 10, format, ap); + va_end(ap); +} + +static void +PseudoramiXDebug(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(X_NONE, 3, format, ap); + va_end(ap); +} + +// Add a PseudoramiX screen. +// The rest of the X server will know nothing about this screen. +// Can be called before or after extension init. +// Screens must be re-added once per generation. +void +PseudoramiXAddScreen(int x, int y, int w, int h) +{ + PseudoramiXScreenRec *s; + + if (noPseudoramiXExtension) return; + + if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) { + pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1; + pseudoramiXScreens = realloc(pseudoramiXScreens, + pseudoramiXScreensAllocated * + sizeof(PseudoramiXScreenRec)); + } + + DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h); + + s = &pseudoramiXScreens[pseudoramiXNumScreens++]; + s->x = x; + s->y = y; + s->w = w; + s->h = h; +} + +// Initialize PseudoramiX. +// Copied from PanoramiXExtensionInit +void +PseudoramiXExtensionInit(void) +{ + Bool success = FALSE; + ExtensionEntry *extEntry; + + if (noPseudoramiXExtension) return; + + TRACE; + + /* Even with only one screen we need to enable PseudoramiX to allow + dynamic screen configuration changes. */ +#if 0 + if (pseudoramiXNumScreens == 1) { + // Only one screen - disable Xinerama extension. + noPseudoramiXExtension = TRUE; + return; + } +#endif + + if (pseudoramiXGeneration != serverGeneration) { + extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0, + ProcPseudoramiXDispatch, + SProcPseudoramiXDispatch, + PseudoramiXResetProc, + StandardMinorOpcode); + if (!extEntry) { + ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n"); + } + else { + pseudoramiXGeneration = serverGeneration; + success = TRUE; + } + } + + if (!success) { + ErrorF("%s Extension (PseudoramiX) failed to initialize\n", + PANORAMIX_PROTOCOL_NAME); + return; + } +} + +void +PseudoramiXResetScreens(void) +{ + TRACE; + + pseudoramiXNumScreens = 0; +} + +static void +PseudoramiXResetProc(ExtensionEntry *extEntry) +{ + TRACE; + + PseudoramiXResetScreens(); +} + +// was PanoramiX +static int +ProcPseudoramiXQueryVersion(ClientPtr client) +{ + TRACE; + + return ProcPanoramiXQueryVersion(client); +} + +// was PanoramiX +static int +ProcPseudoramiXGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int rc; + + TRACE; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPseudoramiXExtension; + rep.window = stuff->window; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.window); + } + WriteToClient(client, sizeof(xPanoramiXGetStateReply),&rep); + return Success; +} + +// was PanoramiX +static int +ProcPseudoramiXGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int rc; + + TRACE; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = pseudoramiXNumScreens; + rep.window = stuff->window; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.window); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply),&rep); + return Success; +} + +// was PanoramiX +static int +ProcPseudoramiXGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + register int rc; + + TRACE; + + if (stuff->screen >= pseudoramiXNumScreens) + return BadMatch; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + /* screen dimensions */ + rep.width = pseudoramiXScreens[stuff->screen].w; + // was screenInfo.screens[stuff->screen]->width; + rep.height = pseudoramiXScreens[stuff->screen].h; + // was screenInfo.screens[stuff->screen]->height; + rep.window = stuff->window; + rep.screen = stuff->screen; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.width); + swapl(&rep.height); + swapl(&rep.window); + swapl(&rep.screen); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply),&rep); + return Success; +} + +// was Xinerama +static int +ProcPseudoramiXIsActive(ClientPtr client) +{ + /* REQUEST(xXineramaIsActiveReq); */ + xXineramaIsActiveReply rep; + + TRACE; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPseudoramiXExtension; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.state); + } + WriteToClient(client, sizeof(xXineramaIsActiveReply),&rep); + return Success; +} + +// was Xinerama +static int +ProcPseudoramiXQueryScreens(ClientPtr client) +{ + /* REQUEST(xXineramaQueryScreensReq); */ + xXineramaQueryScreensReply rep; + + DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n", + noPseudoramiXExtension, + pseudoramiXNumScreens); + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens; + rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.number); + } + WriteToClient(client, sizeof(xXineramaQueryScreensReply),&rep); + + if (!noPseudoramiXExtension) { + xXineramaScreenInfo scratch; + int i; + + for (i = 0; i < pseudoramiXNumScreens; i++) { + scratch.x_org = pseudoramiXScreens[i].x; + scratch.y_org = pseudoramiXScreens[i].y; + scratch.width = pseudoramiXScreens[i].w; + scratch.height = pseudoramiXScreens[i].h; + + if (client->swapped) { + swaps(&scratch.x_org); + swaps(&scratch.y_org); + swaps(&scratch.width); + swaps(&scratch.height); + } + WriteToClient(client, sz_XineramaScreenInfo,&scratch); + } + } + + return Success; +} + +// was PanoramiX +static int +ProcPseudoramiXDispatch(ClientPtr client) +{ + REQUEST(xReq); + TRACE; + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return ProcPseudoramiXQueryVersion(client); + + case X_PanoramiXGetState: + return ProcPseudoramiXGetState(client); + + case X_PanoramiXGetScreenCount: + return ProcPseudoramiXGetScreenCount(client); + + case X_PanoramiXGetScreenSize: + return ProcPseudoramiXGetScreenSize(client); + + case X_XineramaIsActive: + return ProcPseudoramiXIsActive(client); + + case X_XineramaQueryScreens: + return ProcPseudoramiXQueryScreens(client); + } + return BadRequest; +} + +static int +SProcPseudoramiXQueryVersion(ClientPtr client) +{ + REQUEST(xPanoramiXQueryVersionReq); + + TRACE; + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); + return ProcPseudoramiXQueryVersion(client); +} + +static int +SProcPseudoramiXGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + + TRACE; + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + return ProcPseudoramiXGetState(client); +} + +static int +SProcPseudoramiXGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + + TRACE; + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return ProcPseudoramiXGetScreenCount(client); +} + +static int +SProcPseudoramiXGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + + TRACE; + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return ProcPseudoramiXGetScreenSize(client); +} + +static int +SProcPseudoramiXIsActive(ClientPtr client) +{ + REQUEST(xXineramaIsActiveReq); + + TRACE; + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + return ProcPseudoramiXIsActive(client); +} + +static int +SProcPseudoramiXQueryScreens(ClientPtr client) +{ + REQUEST(xXineramaQueryScreensReq); + + TRACE; + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + return ProcPseudoramiXQueryScreens(client); +} + +static int +SProcPseudoramiXDispatch(ClientPtr client) +{ + REQUEST(xReq); + + TRACE; + + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return SProcPseudoramiXQueryVersion(client); + + case X_PanoramiXGetState: + return SProcPseudoramiXGetState(client); + + case X_PanoramiXGetScreenCount: + return SProcPseudoramiXGetScreenCount(client); + + case X_PanoramiXGetScreenSize: + return SProcPseudoramiXGetScreenSize(client); + + case X_XineramaIsActive: + return SProcPseudoramiXIsActive(client); + + case X_XineramaQueryScreens: + return SProcPseudoramiXQueryScreens(client); + } + return BadRequest; +} |