diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:54 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:54 +0000 |
commit | ded6147bfb5d75ff1e67c858040a628b61bc17d1 (patch) | |
tree | 82355105e93cdac89ef7d987424351c77545faf0 | |
parent | cb6ef07bf01e72d1a6e6e83ceb7f76d6534da941 (diff) |
R6.6 is the Xorg base-lineXORG-MAIN
609 files changed, 262690 insertions, 0 deletions
diff --git a/Xext/EVI.c b/Xext/EVI.c new file mode 100644 index 000000000..8ccc31af2 --- /dev/null +++ b/Xext/EVI.c @@ -0,0 +1,179 @@ +/* $Xorg: EVI.c,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc. +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. +********************************************************/ +#include "X.h" +#include "Xproto.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "dix.h" +#define _XEVI_SERVER_ +#include "XEVIstr.h" +#include "EVIstruct.h" +static unsigned char XEVIReqCode = 0; +static EviPrivPtr eviPriv; +static int +ProcEVIQueryVersion(ClientPtr client) +{ + REQUEST(xEVIQueryVersionReq); + xEVIQueryVersionReply rep; + register int n; + REQUEST_SIZE_MATCH (xEVIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XEVI_MAJOR_VERSION; + rep.minorVersion = XEVI_MAJOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xEVIQueryVersionReply), (char *)&rep); + return (client->noClientException); +} +#define swapEviInfo(eviInfo, l) \ +{ \ + int l1 = l; \ + xExtendedVisualInfo *eviInfo1 = eviInfo; \ + while (l1-- > 0) { \ + swapl(&eviInfo1->core_visual_id, n); \ + swapl(&eviInfo1->transparency_value, n); \ + swaps(&eviInfo1->num_colormap_conflicts, n); \ + eviInfo1++; \ + } \ +} +#define swapVisual(visual, l) \ +{ \ + int l1 = l; \ + VisualID32 *visual1 = visual; \ + while (l1-- > 0) { \ + swapl(visual1, n); \ + visual1++; \ + } \ +} +static int +ProcEVIGetVisualInfo(ClientPtr client) +{ + REQUEST(xEVIGetVisualInfoReq); + xEVIGetVisualInfoReply rep; + int n, n_conflict, n_info, sz_info, sz_conflict; + VisualID32 *conflict; + xExtendedVisualInfo *eviInfo; + int status; + REQUEST_FIXED_SIZE(xEVIGetVisualInfoReq, stuff->n_visual * sz_VisualID32); + status = eviPriv->getVisualInfo((VisualID32 *)&stuff[1], (int)stuff->n_visual, + &eviInfo, &n_info, &conflict, &n_conflict); + if (status != Success) + return status; + sz_info = n_info * sz_xExtendedVisualInfo; + sz_conflict = n_conflict * sz_VisualID32; + rep.type = X_Reply; + rep.n_info = n_info; + rep.n_conflicts = n_conflict; + rep.sequenceNumber = client->sequence; + rep.length = (sz_info + sz_conflict) >> 2; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.n_info, n); + swapl(&rep.n_conflicts, n); + swapEviInfo(eviInfo, n_info); + swapVisual(conflict, n_conflict); + } + WriteToClient(client, sz_xEVIGetVisualInfoReply, (char *)&rep); + WriteToClient(client, sz_info, (char *)eviInfo); + WriteToClient(client, sz_conflict, (char *)conflict); + eviPriv->freeVisualInfo(eviInfo, conflict); + return (client->noClientException); +} +static int +ProcEVIDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_EVIQueryVersion: + return ProcEVIQueryVersion (client); + case X_EVIGetVisualInfo: + return ProcEVIGetVisualInfo (client); + default: + return BadRequest; + } +} +static int +SProcEVIQueryVersion(client) +ClientPtr client; +{ + REQUEST(xEVIQueryVersionReq); + int n; + swaps(&stuff->length, n); + return ProcEVIQueryVersion(client); +} +static int +SProcEVIGetVisualInfo(ClientPtr client) +{ + register int n; + REQUEST(xEVIGetVisualInfoReq); + swaps(&stuff->length, n); + return ProcEVIGetVisualInfo(client); +} +static int +SProcEVIDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_EVIQueryVersion: + return SProcEVIQueryVersion (client); + case X_EVIGetVisualInfo: + return SProcEVIGetVisualInfo (client); + default: + return BadRequest; + } +} +/*ARGSUSED*/ +static void +EVIResetProc(ExtensionEntry *extEntry) +{ + eviDDXReset(); +} +/**************** + * XEVIExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ +void +EVIExtensionInit(void) +{ + ExtensionEntry *extEntry, *AddExtension(); + if (extEntry = AddExtension(EVINAME, 0, 0, + ProcEVIDispatch, + SProcEVIDispatch, + EVIResetProc, StandardMinorOpcode)) + { + XEVIReqCode = (unsigned char)extEntry->base; + eviPriv = eviDDXInit(); + } +} diff --git a/Xext/EVIstruct.h b/Xext/EVIstruct.h new file mode 100644 index 000000000..9bb24b0d2 --- /dev/null +++ b/Xext/EVIstruct.h @@ -0,0 +1,53 @@ +/* $Xorg: EVIstruct.h,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc. +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. +********************************************************/ +#ifndef EVI_STRUCT_H +#define EVI_STRUCT_H +/* + ****************************************************************************** + ** Per-ddx data + ****************************************************************************** + */ +typedef int (*GetVisualInfoProc)( +#if NeedNestedPrototypes + VisualID32*, + int, + xExtendedVisualInfo**, + int*, + VisualID32**, + int* +#endif +); +typedef void (*FreeVisualInfoProc)( +#if NeedNestedPrototypes + xExtendedVisualInfo*, + VisualID32* +#endif +); +typedef struct _EviPrivRec { + GetVisualInfoProc getVisualInfo; + FreeVisualInfoProc freeVisualInfo; +} EviPrivRec, *EviPrivPtr; +extern EviPrivPtr eviDDXInit(); +extern void eviDDXReset(); +#endif /* EVI_STRUCT_H */ diff --git a/Xext/README.xtest1-ddx b/Xext/README.xtest1-ddx new file mode 100644 index 000000000..bdf7943b7 --- /dev/null +++ b/Xext/README.xtest1-ddx @@ -0,0 +1,90 @@ +There are several code fragments that need to be placed in the device +dependent part of the server. These are described below. These code +fragments are device and implementation dependent. + +This code fragment should go in your ddx InitInput() routine: + +#ifdef XTESTEXT1 +extern KeyCode xtest_command_key; +#endif + +#ifdef XTESTEXT1 + xtest_command_key = <whatever-is-a-good-keycode-for-your-keyboard>; +#endif + +This code fragment should go at the front of the file that handles +keyboards: + +#ifdef XTESTEXT1 +/* + * defined in xtestext1di.c + */ +extern int on_steal_input; +extern Bool XTestStealKeyData(); +#endif XTESTEXT1 + +This code fragment should go in the function that parses input from the +keyboard or pointer after you know what input action has occurred, but before +you have told the server about it. If conditionalizes the actual function +call to pass the information on: + +#ifdef XTESTEXT1 + if (!on_steal_input || + XTestStealKeyData(code, direction, dev_type, x, y)) +#endif /* XTESTEXT1 */ + handle_device_event(...); + +This code fragment should go in the function that handles mouse motion after +you have figured out how much the mouse has moved: + +#ifdef XTESTEXT1 + if (on_steal_input) + XTestStealMotionData(dx, dy, dev, x, y); +#endif XTESTEXT1 + + +This code fragment should go at the front of the os-specific code where +you wait (by doing a select on the socket in our implementation) for +something to happen: + +#ifdef XTESTEXT1 +extern int playback_on; +void XTestComputeWaitTime(); +#endif XTESTEXT1 + +These code fragments should go in the os-specific code on both sides of +where you wait (by doing a select on the socket in our implementation) +for something to happen: + +#ifdef XTESTEXT1 + if (playback_on) + XTestComputeWaitTime(wt = &waittime); +#endif XTESTEXT1 + ... code to do select ... + WakeupHandler(i, LastSelectMask); +#ifdef XTESTEXT1 + if (playback_on) + i = XTestProcessInputAction(i, &waittime); +#endif XTESTEXT1 + + +You also need to implement the following routines (documentation +is needed; for now, see server/ddx/hp/hp/x_hil.c): + +void +XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey) + int dev_type; + int keycode; + int keystate; + int mousex; + int mousey; + +void +XTestGetPointerPos(fmousex, fmousey) + short *fmousex, *fmousey; + +void +XTestJumpPointer(jx, jy, dev_type) + int jx; + int jy; + int dev_type; diff --git a/Xext/SecurityPolicy b/Xext/SecurityPolicy new file mode 100644 index 000000000..cc521c263 --- /dev/null +++ b/Xext/SecurityPolicy @@ -0,0 +1,88 @@ +version-1 + +# $Xorg: SecurityPolicy,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ + +# The site policy fields are interpreted by the XC-QUERY-SECURITY-1 +# authorization protocol. The values are arbitrary and site-specific. +# Refer to the Security Extension Specification for the usage of the policies. +#sitepolicy A +#sitepolicy B +#sitepolicy C + +# Property access rules: +# property <property> <window> <permissions> +# <window> ::= any | root | <propertyselector> +# <propertyselector> ::= <property> | <property>=<value> +# <permissions> :== [ <operation> | <action> | <space> ]* +# <operation> :== r | w | d +# r read +# w write +# d delete +# <action> :== a | i | e +# a allow +# i ignore +# e error + +# Allow reading of application resources, but not writing. +property RESOURCE_MANAGER root ar iw +property SCREEN_RESOURCES root ar iw + +# Ignore attempts to use cut buffers. Giving errors causes apps to crash, +# and allowing access may give away too much information. +property CUT_BUFFER0 root irw +property CUT_BUFFER1 root irw +property CUT_BUFFER2 root irw +property CUT_BUFFER3 root irw +property CUT_BUFFER4 root irw +property CUT_BUFFER5 root irw +property CUT_BUFFER6 root irw +property CUT_BUFFER7 root irw + +# If you are using Motif, you probably want these. +property _MOTIF_DEFAULT_BINDINGS root ar iw +property _MOTIF_DRAG_WINDOW root ar iw +property _MOTIF_DRAG_TARGETS any ar iw +property _MOTIF_DRAG_ATOMS any ar iw +property _MOTIF_DRAG_ATOM_PAIRS any ar iw + +# If you are running CDE you also need these +property _MOTIF_WM_INFO root arw +property TT_SESSION root irw +property WM_ICON_SIZE root irw +property "SDT Pixel Set" any irw + +# The next two rules let xwininfo -tree work when untrusted. +property WM_NAME any ar + +# Allow read of WM_CLASS, but only for windows with WM_NAME. +# This might be more restrictive than necessary, but demonstrates +# the <required property> facility, and is also an attempt to +# say "top level windows only." +property WM_CLASS WM_NAME ar + +# These next three let xlsclients work untrusted. Think carefully +# before including these; giving away the client machine name and command +# may be exposing too much. +property WM_STATE WM_NAME ar +property WM_CLIENT_MACHINE WM_NAME ar +property WM_COMMAND WM_NAME ar + +# To let untrusted clients use the standard colormaps created by +# xstdcmap, include these lines. +property RGB_DEFAULT_MAP root ar +property RGB_BEST_MAP root ar +property RGB_RED_MAP root ar +property RGB_GREEN_MAP root ar +property RGB_BLUE_MAP root ar +property RGB_GRAY_MAP root ar + +# To let untrusted clients use the color management database created +# by xcmsdb, include these lines. +property XDCCC_LINEAR_RGB_CORRECTION root ar +property XDCCC_LINEAR_RGB_MATRICES root ar +property XDCCC_GRAY_SCREENWHITEPOINT root ar +property XDCCC_GRAY_CORRECTION root ar + +# To let untrusted clients use the overlay visuals that many vendors +# support, include this line. +property SERVER_OVERLAY_VISUALS root ar diff --git a/Xext/appgroup.c b/Xext/appgroup.c new file mode 100644 index 000000000..71e74da38 --- /dev/null +++ b/Xext/appgroup.c @@ -0,0 +1,810 @@ +/* +Copyright 1996, 1998, 2001 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. +*/ +/* $Xorg: appgroup.c,v 1.6 2001/02/09 02:04:32 xorgcvs Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "colormapst.h" +#include "servermd.h" +#define _XAG_SERVER_ +#include "Xagstr.h" +#define _SECURITY_SERVER +#include "security.h" +#include "Xfuncproto.h" + +#define XSERV_t +#include <X11/Xtrans.h> +#include "../os/osdep.h" + +#include <stdio.h> + +typedef struct _AppGroupRec { + struct _AppGroupRec* next; + XID appgroupId; + ClientPtr* clients; + int nclients; + ClientPtr leader; + Bool single_screen; + Window default_root; + VisualID root_visual; + Colormap default_colormap; + Pixel black_pixel; + Pixel white_pixel; + xConnSetupPrefix connSetupPrefix; + char* ConnectionInfo; +} AppGroupRec, *AppGroupPtr; + +static int ProcXagDispatch (), SProcXagDispatch (); +static void XagResetProc (); + +static unsigned char XagReqCode = 0; +static int XagErrorBase; +static int XagCallbackRefCount = 0; + +static RESTYPE RT_APPGROUP; +static AppGroupPtr appGrpList = NULL; + +extern WindowPtr* WindowTable; +extern xConnSetupPrefix connSetupPrefix; +extern char* ConnectionInfo; + +static +int XagAppGroupFree (what, id) + pointer what; + XID id; /* unused */ +{ + int i; + AppGroupPtr pAppGrp = (AppGroupPtr) what; + + if (pAppGrp->leader) + for (i = 0; i < pAppGrp->nclients; i++) { + pAppGrp->clients[i]->appgroup = NULL; + CloseDownClient (pAppGrp->clients[i]); + } + + if (pAppGrp == appGrpList) + appGrpList = appGrpList->next; + else { + AppGroupPtr tpAppGrp; + for (tpAppGrp = appGrpList; + tpAppGrp->next != NULL; + tpAppGrp = tpAppGrp->next) { + if (tpAppGrp->next == pAppGrp) { + tpAppGrp->next = tpAppGrp->next->next; + break; + } + } + } + (void) xfree (pAppGrp->clients); + (void) xfree (pAppGrp->ConnectionInfo); + (void) xfree (what); + return Success; +} + +/* static */ +void XagClientStateChange (pcbl, nulldata, calldata) + CallbackListPtr* pcbl; + pointer nulldata; + pointer calldata; +{ + SecurityAuthorizationPtr pAuth; + NewClientInfoRec* pci = (NewClientInfoRec*) calldata; + ClientPtr pClient = pci->client; + AppGroupPtr pAppGrp; + XID authId; + + if (!pClient->appgroup) { + switch (pClient->clientState) { + + case ClientStateAuthenticating: + case ClientStateRunning: + case ClientStateCheckingSecurity: + return; + + case ClientStateInitial: + case ClientStateCheckedSecurity: + /* + * If the client is connecting via a firewall proxy (which + * uses XC-QUERY-SECURITY-1, then the authId is available + * during ClientStateCheckedSecurity, otherwise it's + * available during ClientStateInitial. + * + * Don't get it from pClient because can't guarantee the order + * of the callbacks and the security extension might not have + * plugged it in yet. + */ + authId = AuthorizationIDOfClient(pClient); + break; + + case ClientStateGone: + case ClientStateRetained: + /* + * Don't get if from AuthorizationIDOfClient because can't + * guarantee the order of the callbacks and the security + * extension may have torn down the client's private data + */ + authId = pClient->authId; + break; + } + + if (authId == None) + return; + + pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(pClient, + authId, SecurityAuthorizationResType, SecurityReadAccess); + + if (pAuth == NULL) + return; + + for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next) + if (pAppGrp->appgroupId == pAuth->group) break; + } else { + pAppGrp = pClient->appgroup; + } + + if (!pAppGrp) + return; + + switch (pClient->clientState) { + case ClientStateAuthenticating: + case ClientStateRunning: + case ClientStateCheckingSecurity: + break; + + case ClientStateInitial: + case ClientStateCheckedSecurity: + /* see the comment above about Initial vs. CheckedSecurity */ + { + /* if this client already in AppGroup, don't add it again */ + int i; + for (i = 0; i < pAppGrp->nclients; i++) + if (pClient == pAppGrp->clients[i]) return; + } + pAppGrp->clients = (ClientPtr*) xrealloc (pAppGrp->clients, + ++pAppGrp->nclients * sizeof (ClientPtr)); + pAppGrp->clients[pAppGrp->nclients - 1] = pClient; + pClient->appgroup = pAppGrp; + break; + + case ClientStateGone: + case ClientStateRetained: /* client disconnected, dump it */ + { + int i; + for (i = 0; i < pAppGrp->nclients; i++) + if (pAppGrp->clients[i] == pClient) { + pAppGrp->clients[i] = NULL; + break; + } + for (i = 0; i < pAppGrp->nclients; i++) + if (pAppGrp->clients[i] == NULL && i + 1 < pAppGrp->nclients) + pAppGrp->clients[i] = pAppGrp->clients[i + 1]; + pAppGrp->nclients--; + } + pClient->appgroup = NULL; /* redundant, pClient will be freed */ + break; + } +} + +void +XagExtensionInit () +{ + ExtensionEntry* extEntry; + + if (extEntry = AddExtension (XAGNAME, + 0, + XagNumberErrors, + ProcXagDispatch, + SProcXagDispatch, + XagResetProc, + StandardMinorOpcode)) { + XagReqCode = (unsigned char)extEntry->base; + XagErrorBase = extEntry->errorBase; + RT_APPGROUP = CreateNewResourceType (XagAppGroupFree); + } +} + +/*ARGSUSED*/ +static +void XagResetProc (extEntry) + ExtensionEntry* extEntry; +{ + DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL); + XagCallbackRefCount = 0; + while (appGrpList) XagAppGroupFree ((pointer) appGrpList, 0); +} + +static +int ProcXagQueryVersion (client) + register ClientPtr client; +{ + REQUEST (xXagQueryVersionReq); + xXagQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xXagQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.server_major_version = XAG_MAJOR_VERSION; + rep.server_minor_version = XAG_MINOR_VERSION; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swaps (&rep.server_major_version, n); + swaps (&rep.server_minor_version, n); + } + WriteToClient (client, sizeof (xXagQueryVersionReply), (char *)&rep); + return client->noClientException; +} + +static +void ProcessAttr (pAppGrp, client, attrib_mask, attribs) + AppGroupPtr pAppGrp; + ClientPtr client; + unsigned int attrib_mask; + CARD32* attribs; +{ + int i; + + for (i = 0; i <= XagNappGroupLeader; i++) { + switch (attrib_mask & (1 << i)) { + case XagSingleScreenMask: + pAppGrp->single_screen = *attribs; + break; + case XagDefaultRootMask: + pAppGrp->default_root = *attribs; + break; + case XagRootVisualMask: + pAppGrp->root_visual = *attribs; + break; + case XagDefaultColormapMask: + pAppGrp->default_colormap = *attribs; + break; + case XagBlackPixelMask: + pAppGrp->black_pixel = *attribs; + break; + case XagWhitePixelMask: + pAppGrp->white_pixel = *attribs; + break; + case XagAppGroupLeaderMask: + pAppGrp->leader = client; + break; + default: continue; + } + attribs++; + } +} + +static +void CreateConnectionInfo (pAppGrp) + AppGroupPtr pAppGrp; +{ + extern int connBlockScreenStart; + xConnSetup *setup = (xConnSetup*) ConnectionInfo; + xWindowRoot* rootp; + xWindowRoot* roots[MAXSCREENS]; + unsigned int rootlens[MAXSCREENS]; + xDepth* depth; + int olen; + int snum, i; + + rootp = (xWindowRoot*) (ConnectionInfo + connBlockScreenStart); + for (snum = 0; snum < screenInfo.numScreens; snum++) { + + rootlens[snum] = sizeof (xWindowRoot); + roots[snum] = rootp; + + depth = (xDepth*) (rootp + 1); + for (i = 0; i < rootp->nDepths; i++) { + rootlens[snum] += sizeof (xDepth) + + depth->nVisuals * sizeof (xVisualType); + depth = (xDepth *)(((char*)(depth + 1)) + + depth->nVisuals * sizeof (xVisualType)); + } + rootp = (xWindowRoot*) depth; + } + snum = 0; + if (pAppGrp->default_root) { + for (; snum < screenInfo.numVideoScreens; snum++) { + if (roots[snum]->windowId == pAppGrp->default_root) + break; + } + } + olen = connBlockScreenStart + rootlens[snum]; + for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++) + olen += rootlens[i]; + pAppGrp->ConnectionInfo = (char*) xalloc (olen); + if (!pAppGrp->ConnectionInfo) + return; + memmove (pAppGrp->ConnectionInfo, ConnectionInfo, connBlockScreenStart); + ((xConnSetup*) (pAppGrp->ConnectionInfo))->numRoots = + 1 + screenInfo.numScreens - screenInfo.numVideoScreens; + memmove (pAppGrp->ConnectionInfo + connBlockScreenStart, + (void*) roots[snum], rootlens[snum]); + rootp = (xWindowRoot*) (pAppGrp->ConnectionInfo + connBlockScreenStart); + if (pAppGrp->default_colormap) { + rootp->defaultColormap = pAppGrp->default_colormap; + rootp->whitePixel = pAppGrp->white_pixel; + rootp->blackPixel = pAppGrp->black_pixel; + } + if (pAppGrp->root_visual) + rootp->rootVisualID = pAppGrp->root_visual; + rootp = (xWindowRoot*) (((char*)rootp) + rootlens[snum]); + for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++) { + memmove ((void*) rootp, (void*) roots[i], rootlens[i]); + rootp = (xWindowRoot*) (((char*) rootp) + rootlens[i]); + } + pAppGrp->connSetupPrefix = connSetupPrefix; + pAppGrp->connSetupPrefix.length = olen >> 2; +} + +static +AppGroupPtr CreateAppGroup (client, appgroupId, attrib_mask, attribs) + ClientPtr client; + XID appgroupId; + unsigned int attrib_mask; + CARD32* attribs; +{ + AppGroupPtr pAppGrp; + int i; + + pAppGrp = (AppGroupPtr) xalloc (sizeof(AppGroupRec)); + if (pAppGrp) { + pAppGrp->next = appGrpList; + appGrpList = pAppGrp; + pAppGrp->appgroupId = appgroupId; + pAppGrp->clients = (ClientPtr*) xalloc (0); + pAppGrp->nclients = 0; + pAppGrp->leader = NULL; + pAppGrp->default_root = 0; + pAppGrp->root_visual = 0; + pAppGrp->default_colormap = 0; + pAppGrp->black_pixel = -1; + pAppGrp->white_pixel = -1; + pAppGrp->ConnectionInfo = NULL; + ProcessAttr (pAppGrp, client, attrib_mask, attribs); + } + return pAppGrp; +} + +static +int AttrValidate (client, attrib_mask, pAppGrp) + ClientPtr client; + int attrib_mask; + AppGroupPtr pAppGrp; +{ + WindowPtr pWin; + int idepth, ivids, found; + ScreenPtr pScreen; + DepthPtr pDepth; + ColormapPtr pColormap; + + pWin = LookupWindow (pAppGrp->default_root, client); + /* XXX check that pWin is not NULL */ + pScreen = pWin->drawable.pScreen; + if (WindowTable[pScreen->myNum]->drawable.id != pAppGrp->default_root) + return BadWindow; + pDepth = pScreen->allowedDepths; + if (pAppGrp->root_visual) { + found = FALSE; + for (idepth = 0; idepth < pScreen->numDepths; idepth++, pDepth++) { + for (ivids = 0; ivids < pDepth->numVids; ivids++) { + if (pAppGrp->root_visual == pDepth->vids[ivids]) { + found = TRUE; + break; + } + } + } + if (!found) + return BadMatch; + } + if (pAppGrp->default_colormap) { + + pColormap = (ColormapPtr)LookupIDByType (pAppGrp->default_colormap, RT_COLORMAP); + /* XXX check that pColormap is not NULL */ + if (pColormap->pScreen != pScreen) + return BadColor; + if (pColormap->pVisual->vid != (pAppGrp->root_visual ? pAppGrp->root_visual : pScreen->rootVisual)) + return BadMatch; + } + return client->noClientException; +} + +/* static */ +int ProcXagCreate (client) + register ClientPtr client; +{ + REQUEST (xXagCreateReq); + AppGroupPtr pAppGrp; + int ret; + + REQUEST_AT_LEAST_SIZE (xXagCreateReq); + + LEGAL_NEW_RESOURCE (stuff->app_group, client); + pAppGrp = CreateAppGroup (client, stuff->app_group, + stuff->attrib_mask, (CARD32*) &stuff[1]); + if (!pAppGrp) + return BadAlloc; + ret = AttrValidate (client, stuff->attrib_mask, pAppGrp); + if (ret != Success) { + XagAppGroupFree ((pointer)pAppGrp, (XID)0); + return ret; + } + if (pAppGrp->single_screen) { + CreateConnectionInfo (pAppGrp); + if (!pAppGrp->ConnectionInfo) + return BadAlloc; + } + if (!AddResource (stuff->app_group, RT_APPGROUP, (pointer)pAppGrp)) + return BadAlloc; + if (XagCallbackRefCount++ == 0) + (void) AddCallback (&ClientStateCallback, XagClientStateChange, NULL); + return client->noClientException; +} + +/* static */ +int ProcXagDestroy (client) + register ClientPtr client; +{ + AppGroupPtr pAppGrp; + REQUEST (xXagDestroyReq); + + REQUEST_SIZE_MATCH (xXagDestroyReq); + pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client, + (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess); + if (!pAppGrp) return XagBadAppGroup; + FreeResource ((XID)stuff->app_group, RT_NONE); + if (--XagCallbackRefCount == 0) + (void) DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL); + return client->noClientException; +} + +static +int ProcXagGetAttr (client) + register ClientPtr client; +{ + AppGroupPtr pAppGrp; + REQUEST (xXagGetAttrReq); + xXagGetAttrReply rep; + int n; + + REQUEST_SIZE_MATCH (xXagGetAttrReq); + pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client, + (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess); + if (!pAppGrp) return XagBadAppGroup; + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.default_root = pAppGrp->default_root; + rep.root_visual = pAppGrp->root_visual; + rep.default_colormap = pAppGrp->default_colormap; + rep.black_pixel = pAppGrp->black_pixel; + rep.white_pixel = pAppGrp->white_pixel; + rep.single_screen = pAppGrp->single_screen; + rep.app_group_leader = (pAppGrp->leader) ? 1 : 0; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swapl (&rep.default_root, n); + swapl (&rep.root_visual, n); + swapl (&rep.default_colormap, n); + swapl (&rep.black_pixel, n); + swapl (&rep.white_pixel, n); + } + WriteToClient (client, sizeof (xXagGetAttrReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcXagQuery (client) + register ClientPtr client; +{ + ClientPtr pClient; + AppGroupPtr pAppGrp; + REQUEST (xXagQueryReq); + int n; + + REQUEST_SIZE_MATCH (xXagQueryReq); + pClient = LookupClient (stuff->resource, client); + for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next) + for (n = 0; n < pAppGrp->nclients; n++) + if (pAppGrp->clients[n] == pClient) { + xXagQueryReply rep; + + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.app_group = pAppGrp->appgroupId; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swapl (&rep.app_group, n); + } + WriteToClient (client, sizeof (xXagQueryReply), (char *)&rep); + return client->noClientException; + } + + return BadMatch; +} + +static +int ProcXagCreateAssoc (client) + register ClientPtr client; +{ + REQUEST (xXagCreateAssocReq); + + REQUEST_SIZE_MATCH (xXagCreateAssocReq); +#ifdef WIN32 + if (stuff->window_type != XagWindowTypeWin32) +#else + if (stuff->window_type != XagWindowTypeX11) +#endif + return BadMatch; +#ifdef WIN32 /* and Mac, etc */ + if (!LocalClient (client)) + return BadAccess; +#endif + +/* Macintosh, OS/2, and MS-Windows servers have some work to do here */ + + return client->noClientException; +} + +static +int ProcXagDestroyAssoc (client) + register ClientPtr client; +{ + REQUEST (xXagDestroyAssocReq); + + REQUEST_SIZE_MATCH (xXagDestroyAssocReq); +/* Macintosh, OS/2, and MS-Windows servers have some work to do here */ + return client->noClientException; +} + +static +int ProcXagDispatch (client) + register ClientPtr client; +{ + REQUEST (xReq); + switch (stuff->data) + { + case X_XagQueryVersion: + return ProcXagQueryVersion (client); + case X_XagCreate: + return ProcXagCreate (client); + case X_XagDestroy: + return ProcXagDestroy (client); + case X_XagGetAttr: + return ProcXagGetAttr (client); + case X_XagQuery: + return ProcXagQuery (client); + case X_XagCreateAssoc: + return ProcXagCreateAssoc (client); + case X_XagDestroyAssoc: + return ProcXagDestroyAssoc (client); + default: + return BadRequest; + } +} + +static +int SProcXagQueryVersion (client) + register ClientPtr client; +{ + register int n; + REQUEST(xXagQueryVersionReq); + swaps(&stuff->length, n); + return ProcXagQueryVersion(client); +} + +static +int SProcXagCreate (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagCreateReq); + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXagCreateReq); + swapl (&stuff->app_group, n); + swapl (&stuff->attrib_mask, n); + SwapRestL (stuff); + return ProcXagCreate (client); +} + +static +int SProcXagDestroy (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagDestroyReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagDestroyReq); + swapl (&stuff->app_group, n); + return ProcXagDestroy (client); +} + +static +int SProcXagGetAttr (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagGetAttrReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagGetAttrReq); + swapl (&stuff->app_group, n); + return ProcXagGetAttr (client); +} + +static +int SProcXagQuery (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagQueryReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagQueryReq); + swapl (&stuff->resource, n); + return ProcXagQuery (client); +} + +static +int SProcXagCreateAssoc (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagCreateAssocReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagCreateAssocReq); + swapl (&stuff->window, n); + swapl (&stuff->window_type, n); + swaps (&stuff->system_window_len, n); + return ProcXagCreateAssoc (client); +} + +static +int SProcXagDestroyAssoc (client) + ClientPtr client; +{ + register int n; + REQUEST (xXagDestroyAssocReq); + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xXagDestroyAssocReq); + swapl (&stuff->window, n); + return ProcXagDestroyAssoc (client); +} + +static +int SProcXagDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XagQueryVersion: + return SProcXagQueryVersion (client); + case X_XagCreate: + return SProcXagCreate (client); + case X_XagDestroy: + return SProcXagDestroy (client); + case X_XagGetAttr: + return SProcXagGetAttr (client); + case X_XagQuery: + return SProcXagQuery (client); + case X_XagCreateAssoc: + return SProcXagCreateAssoc (client); + case X_XagDestroyAssoc: + return SProcXagDestroyAssoc (client); + default: + return BadRequest; + } +} + +Colormap XagDefaultColormap (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->default_colormap : None); +} + +VisualID XagRootVisual (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->root_visual : 0); +} + +ClientPtr XagLeader (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->leader : NULL); +} + +/* + * Return whether the Map request event should be sent to the appgroup leader. + * We don't want to send it to the leader when the window is on a different + * screen, e.g. a print screen. + */ +Bool XagIsControlledRoot (client, pParent) + ClientPtr client; + WindowPtr pParent; +{ + if (client->appgroup) { + if (client->appgroup->single_screen && + pParent->drawable.id == client->appgroup->default_root) + return TRUE; + else if (!pParent->parent) + return TRUE; + else + return FALSE; + } + return FALSE; +} + +void XagConnectionInfo (client, conn_prefix, conn_info, num_screen) + ClientPtr client; + xConnSetupPrefix** conn_prefix; + char** conn_info; + int* num_screen; +{ + if (client->appgroup && client->appgroup->ConnectionInfo) { + *conn_prefix = &client->appgroup->connSetupPrefix; + *conn_info = client->appgroup->ConnectionInfo; + *num_screen = ((xConnSetup*)(client->appgroup->ConnectionInfo))->numRoots; + } +} + +XID XagId (client) + ClientPtr client; +{ + return (client->appgroup ? client->appgroup->appgroupId : 0); +} + +void XagGetDeltaInfo (client, buf) + ClientPtr client; + CARD32* buf; +{ + *buf++ = (CARD32) client->appgroup->default_root; + *buf++ = (CARD32) client->appgroup->root_visual; + *buf++ = (CARD32) client->appgroup->default_colormap; + *buf++ = (CARD32) client->appgroup->black_pixel; + *buf = (CARD32) client->appgroup->white_pixel; +} + +void XagCallClientStateChange (client) + ClientPtr client; +{ + if (appGrpList) { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + XagClientStateChange (NULL, NULL, (pointer)&clientinfo); + } +} diff --git a/Xext/bigreq.c b/Xext/bigreq.c new file mode 100644 index 000000000..4f4bf5c02 --- /dev/null +++ b/Xext/bigreq.c @@ -0,0 +1,86 @@ +/* $Xorg: bigreq.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +/* + +Copyright 1992, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "bigreqstr.h" + +static unsigned char XBigReqCode; +static int ProcBigReqDispatch(); +static void BigReqResetProc(); + +void +BigReqExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(XBigReqExtensionName, 0, 0, + ProcBigReqDispatch, ProcBigReqDispatch, + BigReqResetProc, StandardMinorOpcode)) + XBigReqCode = (unsigned char)extEntry->base; + DeclareExtensionSecurity(XBigReqExtensionName, TRUE); +} + +/*ARGSUSED*/ +static void +BigReqResetProc (extEntry) + ExtensionEntry *extEntry; +{ +} + +static int +ProcBigReqDispatch (client) + register ClientPtr client; +{ + REQUEST(xBigReqEnableReq); + xBigReqEnableReply rep; + register int n; + + if (client->swapped) { + swaps(&stuff->length, n); + } + if (stuff->brReqType != X_BigReqEnable) + return BadRequest; + REQUEST_SIZE_MATCH(xBigReqEnableReq); + client->big_requests = TRUE; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.max_request_size = MAX_BIG_REQUEST_SIZE; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.max_request_size, n); + } + WriteToClient(client, sizeof(xBigReqEnableReply), (char *)&rep); + return(client->noClientException); +} diff --git a/Xext/cup.c b/Xext/cup.c new file mode 100644 index 000000000..4e8cf66b4 --- /dev/null +++ b/Xext/cup.c @@ -0,0 +1,340 @@ +/* $Xorg: cup.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +/* + +Copyright 1997, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XCUP_SERVER_ +#include "Xcupstr.h" +#include "Xfuncproto.h" + +#include "../os/osdep.h" + +static int ProcDispatch (), SProcDispatch (); +static void ResetProc (); + +static unsigned char ReqCode = 0; +static int ErrorBase; + +#if defined(WIN32) || defined(TESTWIN32) +#define HAVE_SPECIAL_DESKTOP_COLORS +#endif + +static xColorItem citems[] = { +#ifndef HAVE_SPECIAL_DESKTOP_COLORS +#define CUP_BLACK_PIXEL 0 +#define CUP_WHITE_PIXEL 1 + /* pix red green blue */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 0xffff, 0xffff, 0xffff, 0, 0 } +#else +#ifndef WIN32 + /* + This approximates the MS-Windows desktop colormap for testing + purposes but has black and white pixels in the typical Unix + locations, which should be switched if necessary if your system + has blackPixel and whitePixel swapped. No entries are provided + for colormap entries 254 and 255 because AllocColor/FindColor + will reuse entries zero and one. + */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 0xffff, 0xffff, 0xffff, 0, 0 }, + { 2, 0x8000, 0, 0, 0, 0 }, + { 3, 0, 0x8000, 0, 0, 0 }, + { 4, 0x8000, 0x8000, 0, 0, 0 }, + { 5, 0, 0, 0x8000, 0, 0 }, + { 6, 0x8000, 0, 0x8000, 0, 0 }, + { 7, 0, 0x8000, 0x8000, 0, 0 }, + { 8, 0xc000, 0xc000, 0xc000, 0, 0 }, + { 9, 0xc000, 0xdc00, 0xc000, 0, 0 }, + { 246, 0xa000, 0xa000, 0xa000, 0, 0 }, + { 247, 0x8000, 0x8000, 0x8000, 0, 0 }, + { 248, 0xffff, 0, 0, 0, 0 }, + { 249, 0, 0xffff, 0, 0, 0 }, + { 250, 0xffff, 0xffff, 0, 0, 0 }, + { 251, 0, 0, 0xffff, 0, 0 }, + { 252, 0xffff, 0, 0xffff, 0, 0 }, + { 253, 0, 0xffff, 0xffff, 0, 0 } +#else + /* + this is the MS-Windows desktop, adjusted for X's 16-bit color + specifications. + */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 0x8000, 0, 0, 0, 0 }, + { 2, 0, 0x8000, 0, 0, 0 }, + { 3, 0x8000, 0x8000, 0, 0, 0 }, + { 4, 0, 0, 0x8000, 0, 0 }, + { 5, 0x8000, 0, 0x8000, 0, 0 }, + { 6, 0, 0x8000, 0x8000, 0, 0 }, + { 7, 0xc000, 0xc000, 0xc000, 0, 0 }, + { 8, 0xc000, 0xdc00, 0xc000, 0, 0 }, + { 9, 0xa600, 0xca00, 0xf000, 0, 0 }, + { 246, 0xff00, 0xfb00, 0xf000, 0, 0 }, + { 247, 0xa000, 0xa000, 0xa400, 0, 0 }, + { 248, 0x8000, 0x8000, 0x8000, 0, 0 }, + { 249, 0xff00, 0, 0, 0, 0 }, + { 250, 0, 0xff00, 0, 0, 0 }, + { 251, 0xff00, 0xff00, 0, 0, 0 }, + { 252, 0, 0, 0xff00, 0, 0 }, + { 253, 0xff00, 0, 0xff00, 0, 0 }, + { 254, 0, 0xff00, 0xff00, 0, 0 }, + { 255, 0xff00, 0xff00, 0xff00, 0, 0 } +#endif +#endif +}; +#define NUM_DESKTOP_COLORS (sizeof citems / sizeof citems[0]) + +void +XcupExtensionInit () +{ + ExtensionEntry* extEntry; + + if (extEntry = AddExtension (XCUPNAME, + 0, + XcupNumberErrors, + ProcDispatch, + SProcDispatch, + ResetProc, + StandardMinorOpcode)) { + ReqCode = (unsigned char)extEntry->base; + ErrorBase = extEntry->errorBase; + } + + /* PC servers initialize the desktop colors (citems) here! */ +} + +/*ARGSUSED*/ +static +void ResetProc (extEntry) + ExtensionEntry* extEntry; +{ +} + +static +int ProcQueryVersion (client) + register ClientPtr client; +{ + REQUEST (xXcupQueryVersionReq); + xXcupQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xXcupQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.server_major_version = XCUP_MAJOR_VERSION; + rep.server_minor_version = XCUP_MINOR_VERSION; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + swaps (&rep.server_major_version, n); + swaps (&rep.server_minor_version, n); + } + WriteToClient (client, sizeof (xXcupQueryVersionReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcGetReservedColormapEntries (client) + register ClientPtr client; +{ + REQUEST (xXcupGetReservedColormapEntriesReq); + xXcupGetReservedColormapEntriesReply rep; + xColorItem* cptr; + register int n; + + REQUEST_SIZE_MATCH (xXcupGetReservedColormapEntriesReq); + +#ifndef HAVE_SPECIAL_DESKTOP_COLORS + citems[CUP_BLACK_PIXEL].pixel = + screenInfo.screens[stuff->screen]->blackPixel; + citems[CUP_WHITE_PIXEL].pixel = + screenInfo.screens[stuff->screen]->whitePixel; +#endif + + rep.type = X_Reply; + rep.sequence_number = client->sequence; + rep.length = NUM_DESKTOP_COLORS * 3; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + } + WriteToClient (client, sizeof (xXcupGetReservedColormapEntriesReply), (char *)&rep); + for (n = 0, cptr = citems; n < NUM_DESKTOP_COLORS; n++, cptr++) { + if (client->swapped) SwapColorItem (cptr); + WriteToClient (client, SIZEOF(xColorItem), (char *)cptr); + } + return client->noClientException; +} + +static +int ProcStoreColors (client) + register ClientPtr client; +{ + REQUEST (xXcupStoreColorsReq); + ColormapPtr pcmp; + + REQUEST_AT_LEAST_SIZE (xXcupStoreColorsReq); + pcmp = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + + if (pcmp) { + int ncolors, n; + xXcupStoreColorsReply rep; + xColorItem* cptr; + Pixel pixel; + + if (!(pcmp->class & DynamicClass)) + return BadMatch; + + ncolors = (client->req_len << 2) - SIZEOF (xXcupStoreColorsReq); + if (ncolors % SIZEOF(xColorItem)) + return BadLength; + + ncolors /= SIZEOF (xColorItem); + + + for (n = 0, cptr = (xColorItem*) &stuff[1]; n < ncolors; n++) { + Pixel pixel = cptr->pixel; + + if (AllocColor (pcmp, + &cptr->red, &cptr->green, &cptr->blue, + &pixel, client->index) == Success) { + cptr->pixel = pixel; + cptr->flags = 0x08; + } else + cptr->flags = 0; + cptr = (xColorItem*) (((char*)cptr) + SIZEOF(xColorItem)); + } + + rep.type = X_Reply; + rep.sequence_number = client->sequence; + rep.length = ncolors * 3; + if (client->swapped) { + swaps (&rep.sequence_number, n); + swapl (&rep.length, n); + } + WriteToClient (client, sizeof (xXcupGetReservedColormapEntriesReply), (char *)&rep); + for (n = 0, cptr = (xColorItem*) &stuff[1]; n < ncolors; n++) { + if (client->swapped) SwapColorItem (cptr); + WriteToClient (client, SIZEOF(xColorItem), (char *)cptr); + cptr = (xColorItem*) (((char*)cptr) + SIZEOF(xColorItem)); + } + return client->noClientException; + } else { + client->errorValue = stuff->cmap; + return BadColor; + } +} + +static +int ProcDispatch (client) + register ClientPtr client; +{ + REQUEST (xReq); + switch (stuff->data) + { + case X_XcupQueryVersion: + return ProcQueryVersion (client); + case X_XcupGetReservedColormapEntries: + return ProcGetReservedColormapEntries (client); + case X_XcupStoreColors: + return ProcStoreColors (client); + default: + return BadRequest; + } +} + +static +int SProcQueryVersion (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xXcupQueryVersionReq); + swaps(&stuff->length, n); + return ProcQueryVersion(client); +} + +static +int SProcGetReservedColormapEntries (client) + ClientPtr client; +{ + register int n; + + REQUEST (xXcupGetReservedColormapEntriesReq); + swaps (&stuff->length, n); + swapl (&stuff->screen, n); + REQUEST_AT_LEAST_SIZE (xXcupGetReservedColormapEntriesReq); + return ProcGetReservedColormapEntries (client); +} + +static +int SProcStoreColors (client) + ClientPtr client; +{ + register int n; + int count; + xColorItem* pItem; + + REQUEST (xXcupStoreColorsReq); + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXcupStoreColorsReq); + swapl(&stuff->cmap, n); + pItem = (xColorItem*) &stuff[1]; + for(count = LengthRestB(stuff)/sizeof(xColorItem); --count >= 0; ) + SwapColorItem(pItem++); + return ProcStoreColors (client); +} + +static +int SProcDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XcupQueryVersion: + return SProcQueryVersion (client); + case X_XcupGetReservedColormapEntries: + return SProcGetReservedColormapEntries (client); + case X_XcupStoreColors: + return SProcStoreColors (client); + default: + return BadRequest; + } +} + + diff --git a/Xext/dpms.c b/Xext/dpms.c new file mode 100644 index 000000000..ebc992dc2 --- /dev/null +++ b/Xext/dpms.c @@ -0,0 +1,433 @@ +/* $Xorg: dpms.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */ +/***************************************************************** + +Copyright (c) 1996 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. + +******************************************************************/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "dpms.h" +#include "dpmsstr.h" +#include <stdio.h> + +static unsigned char DPMSCode; +static int ProcDPMSDispatch(), SProcDPMSDispatch(); +static void DPMSResetProc(); +static int ProcDPMSGetVersion(), SProcDPMSGetVersion(); +static int ProcDPMSGetTimeouts(), SProcDPMSGetTimeouts(); +static int ProcDPMSSetTimeouts(), ProcDPMSSetTimeouts(); +static int ProcDPMSEnable(), ProcDPMSEnable(); +static int ProcDPMSDisable(), ProcDPMSDisable(); +static int ProcDPMSForceLevel(), ProcDPMSForceLevel(); + +extern void Swap32Write(); /* XXX should be in header file */ +extern CARD32 ScreenSaverTime; +extern CARD32 DPMSStandbyTime; +extern CARD32 DPMSSuspendTime; +extern CARD32 DPMSOffTime; +extern BOOL DPMSCapableFlag; +extern BOOL DPMSEnabled; +extern CARD16 DPMSPowerLevel; + +void +DPMSExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(DPMSExtensionName, 0, 0, + ProcDPMSDispatch, SProcDPMSDispatch, + DPMSResetProc, StandardMinorOpcode)) + DPMSCode = (unsigned char)extEntry->base; + return; +} + +/*ARGSUSED*/ +static void +DPMSResetProc (extEntry) + ExtensionEntry *extEntry; +{ +} + +static int +ProcDPMSGetVersion(client) + register ClientPtr client; +{ + REQUEST(xDPMSGetVersionReq); + xDPMSGetVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = DPMSMajorVersion; + rep.minorVersion = DPMSMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xDPMSGetVersionReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSCapable(client) + register ClientPtr client; +{ + REQUEST(xDPMSCapableReq); + xDPMSCapableReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.capable = DPMSCapableFlag; + + WriteToClient(client, sizeof(xDPMSCapableReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSGetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSGetTimeoutsReq); + xDPMSGetTimeoutsReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.standby = DPMSStandbyTime / MILLI_PER_SECOND; + rep.suspend = DPMSSuspendTime / MILLI_PER_SECOND; + rep.off = DPMSOffTime / MILLI_PER_SECOND; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.standby, n); + swaps(&rep.suspend, n); + swaps(&rep.off, n); + } + WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSSetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSSetTimeoutsReq); + register int n; + + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + if ((stuff->off != 0)&&(stuff->off < stuff->suspend)) + { + client->errorValue = stuff->off; + return BadValue; + } + if ((stuff->suspend != 0)&&(stuff->suspend < stuff->standby)) + { + client->errorValue = stuff->suspend; + return BadValue; + } + + DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND; + DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND; + DPMSOffTime = stuff->off * MILLI_PER_SECOND; + + return(client->noClientException); +} + +static int +ProcDPMSEnable(client) + register ClientPtr client; +{ + REQUEST(xDPMSEnableReq); + + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + if (DPMSCapableFlag) + DPMSEnabled = TRUE; + + return(client->noClientException); +} + +static int +ProcDPMSDisable(client) + register ClientPtr client; +{ + REQUEST(xDPMSDisableReq); + + REQUEST_SIZE_MATCH(xDPMSDisableReq); + +#ifdef DPMSExtension + DPMSSet(DPMSModeOn); +#endif + + DPMSEnabled = FALSE; + + return(client->noClientException); +} + +static int +ProcDPMSForceLevel(client) + register ClientPtr client; +{ + REQUEST(xDPMSForceLevelReq); + + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + if (!DPMSEnabled) + return BadMatch; + + if (stuff->level == DPMSModeOn) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis(); + } +#if 0 + else if (stuff->level == DPMSModeStandby) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis() - DPMSStandbyTime; + } else if (stuff->level == DPMSModeSuspend) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis() - DPMSSuspendTime; + } else if (stuff->level == DPMSModeOff) { + lastDeviceEventTime.milliseconds = + GetTimeInMillis() - DPMSOffTime; + } else { + client->errorValue = stuff->level; + return BadValue; + } +#endif + +#ifdef DPMSExtension + DPMSSet(stuff->level); +#endif + + return(client->noClientException); +} + +static int +ProcDPMSInfo(client) + register ClientPtr client; +{ + REQUEST(xDPMSInfoReq); + xDPMSInfoReply rep; + register int n; + + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.power_level = DPMSPowerLevel; + rep.state = DPMSEnabled; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.power_level, n); + } + WriteToClient(client, sizeof(xDPMSInfoReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcDPMSDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_DPMSGetVersion: + return ProcDPMSGetVersion(client); + case X_DPMSCapable: + return ProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return ProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return ProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return ProcDPMSEnable(client); + case X_DPMSDisable: + return ProcDPMSDisable(client); + case X_DPMSForceLevel: + return ProcDPMSForceLevel(client); + case X_DPMSInfo: + return ProcDPMSInfo(client); + default: + return BadRequest; + } +} + +static int +SProcDPMSGetVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xDPMSGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return ProcDPMSGetVersion(client); +} + +static int +SProcDPMSCapable(client) + register ClientPtr client; +{ + REQUEST(xDPMSCapableReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + return ProcDPMSCapable(client); +} + +static int +SProcDPMSGetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSGetTimeoutsReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + return ProcDPMSGetTimeouts(client); +} + +static int +SProcDPMSSetTimeouts(client) + register ClientPtr client; +{ + REQUEST(xDPMSSetTimeoutsReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + swaps(&stuff->standby, n); + swaps(&stuff->suspend, n); + swaps(&stuff->off, n); + return ProcDPMSSetTimeouts(client); +} + +static int +SProcDPMSEnable(client) + register ClientPtr client; +{ + REQUEST(xDPMSEnableReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + return ProcDPMSEnable(client); +} + +static int +SProcDPMSDisable(client) + register ClientPtr client; +{ + REQUEST(xDPMSDisableReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSDisableReq); + + return ProcDPMSDisable(client); +} + +static int +SProcDPMSForceLevel(client) + register ClientPtr client; +{ + REQUEST(xDPMSForceLevelReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + swaps(&stuff->level, n); + + return ProcDPMSForceLevel(client); +} + +static int +SProcDPMSInfo(client) + register ClientPtr client; +{ + REQUEST(xDPMSInfoReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + return ProcDPMSInfo(client); +} + +static int +SProcDPMSDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_DPMSGetVersion: + return SProcDPMSGetVersion(client); + case X_DPMSCapable: + return SProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return SProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return SProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return SProcDPMSEnable(client); + case X_DPMSDisable: + return SProcDPMSDisable(client); + case X_DPMSForceLevel: + return SProcDPMSForceLevel(client); + case X_DPMSInfo: + return SProcDPMSInfo(client); + default: + return BadRequest; + } +} diff --git a/Xext/dpmsstubs.c b/Xext/dpmsstubs.c new file mode 100644 index 000000000..6f635f42b --- /dev/null +++ b/Xext/dpmsstubs.c @@ -0,0 +1,48 @@ +/* $Xorg: dpmsstubs.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */ +/***************************************************************** + +Copyright (c) 1996 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. + +******************************************************************/ + +typedef int Bool; + +#define FALSE 0 + +Bool DPMSSupported() +{ + return FALSE; +} + +int DPSMGet(level) + int *level; +{ + return -1; +} + +void DPMSSet(level) +{ + +} diff --git a/Xext/mbuf.c b/Xext/mbuf.c new file mode 100644 index 000000000..c65ed3dd2 --- /dev/null +++ b/Xext/mbuf.c @@ -0,0 +1,2041 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mbuf.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +#define NEED_REPLIES +#define NEED_EVENTS +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#include "multibufst.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" +#ifndef WIN32 +#include <sys/time.h> +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#endif + +/* given an OtherClientPtr obj, get the ClientPtr */ +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +/* given a MultibufferPtr b, get the ClientPtr */ +#define bClient(b) (clients[CLIENT_ID(b->pPixmap->drawable.id)]) + +#define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask) + +#ifdef PANORAMIX +extern int PanoramiXNumScreens; +extern Bool noPanoramiXExtension; +extern PanoramiXWindow *PanoramiXWinRoot; +extern PanoramiXPmap *PanoramiXPmapRoot; +extern PanoramiXData *panoramiXdataPtr; +#endif + +/* The _Multibuffer and _Multibuffers structures below refer to each other, + * so we need this forward declaration + */ + +typedef struct _Multibuffers *MultibuffersPtr; + +/* + * per-Multibuffer data + */ + +typedef struct _Multibuffer { + MultibuffersPtr pMultibuffers; /* associated window data */ + Mask eventMask; /* MultibufferClobberNotifyMask|ExposureMask|MultibufferUpdateNotifyMask */ + Mask otherEventMask; /* mask of all other clients event masks */ + OtherClients *otherClients; /* other clients that want events */ + int number; /* index of this buffer into array */ + int side; /* always Mono */ + int clobber; /* Unclobbered, PartiallyClobbered, FullClobbered */ + PixmapPtr pPixmap; /* associated pixmap */ +} MultibufferRec, *MultibufferPtr; + +/* + * per-window data + */ + +typedef struct _Multibuffers { + WindowPtr pWindow; /* associated window */ + int numMultibuffer; /* count of buffers */ + int refcnt; /* ref count for delete */ + int displayedMultibuffer; /* currently active buffer */ + int updateAction; /* Undefined, Background, Untouched, Copied */ + int updateHint; /* Frequent, Intermittent, Static */ + int windowMode; /* always Mono */ + + TimeStamp lastUpdate; /* time of last update */ + + unsigned short width, height; /* last known window size */ + short x, y; /* for static gravity */ + + MultibufferPtr buffers; /* array of numMultibuffer buffers */ +} MultibuffersRec; + +/* + * per-screen data + */ +typedef struct _MultibufferScreen { + Bool (*PositionWindow)(); +} MultibufferScreenRec, *MultibufferScreenPtr; + +/* + * per display-image-buffers request data. + */ + +typedef struct _DisplayRequest { + struct _DisplayRequest *next; + TimeStamp activateTime; + ClientPtr pClient; + XID id; +} DisplayRequestRec, *DisplayRequestPtr; + +static unsigned char MultibufferReqCode; +static int MultibufferEventBase; +static int MultibufferErrorBase; +int MultibufferScreenIndex = -1; +int MultibufferWindowIndex = -1; + +static void PerformDisplayRequest (); +static void DisposeDisplayRequest (); +static Bool QueueDisplayRequest (); + +static void BumpTimeStamp (); + +void MultibufferExpose (); +void MultibufferUpdate (); +static void AliasMultibuffer (); +int CreateImageBuffers (); +void DestroyImageBuffers (); +int DisplayImageBuffers (); +static void RecalculateMultibufferOtherEvents (); +static int EventSelectForMultibuffer(); + + +/* + * The Pixmap associated with a buffer can be found as a resource + * with this type + */ +RESTYPE MultibufferDrawableResType; +static int MultibufferDrawableDelete (); +/* + * The per-buffer data can be found as a resource with this type. + * the resource id of the per-buffer data is the same as the resource + * id of the pixmap + */ +static RESTYPE MultibufferResType; +static int MultibufferDelete (); +/* + * The per-window data can be found as a resource with this type, + * using the window resource id + */ +static RESTYPE MultibuffersResType; +static int MultibuffersDelete (); +/* + * Clients other than the buffer creator attach event masks in + * OtherClient structures; each has a resource of this type. + */ +static RESTYPE OtherClientResType; +static int OtherClientDelete (); + +/**************** + * MultibufferExtensionInit + * + * Called from InitExtensions in main() + * + ****************/ + +static int ProcMultibufferDispatch(), SProcMultibufferDispatch(); +static void MultibufferResetProc(); +static void SClobberNotifyEvent(), SUpdateNotifyEvent(); +static Bool MultibufferPositionWindow(); + +void +MultibufferExtensionInit() +{ + ExtensionEntry *extEntry; + int i, j; + ScreenPtr pScreen; + MultibufferScreenPtr pMultibufferScreen; + + /* + * allocate private pointers in windows and screens. Allocating + * window privates may seem like an unnecessary expense, but every + * PositionWindow call must check to see if the window is + * multi-buffered; a resource lookup is too expensive. + */ + MultibufferScreenIndex = AllocateScreenPrivateIndex (); + if (MultibufferScreenIndex < 0) + return; + MultibufferWindowIndex = AllocateWindowPrivateIndex (); + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + if (!AllocateWindowPrivate (pScreen, MultibufferWindowIndex, 0) || + !(pMultibufferScreen = (MultibufferScreenPtr) xalloc (sizeof (MultibufferScreenRec)))) + { + for (j = 0; j < i; j++) + xfree (screenInfo.screens[j]->devPrivates[MultibufferScreenIndex].ptr); + return; + } + pScreen->devPrivates[MultibufferScreenIndex].ptr = (pointer) pMultibufferScreen; + /* + * wrap PositionWindow to resize the pixmap when the window + * changes size + */ + pMultibufferScreen->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = MultibufferPositionWindow; + } + /* + * create the resource types + */ + MultibufferDrawableResType = + CreateNewResourceType(MultibufferDrawableDelete)|RC_CACHED|RC_DRAWABLE; + MultibufferResType = CreateNewResourceType(MultibufferDelete); + MultibuffersResType = CreateNewResourceType(MultibuffersDelete); + OtherClientResType = CreateNewResourceType(OtherClientDelete); + if (MultibufferDrawableResType && MultibufferResType && + MultibuffersResType && OtherClientResType && + (extEntry = AddExtension(MULTIBUFFER_PROTOCOL_NAME, + MultibufferNumberEvents, + MultibufferNumberErrors, + ProcMultibufferDispatch, SProcMultibufferDispatch, + MultibufferResetProc, StandardMinorOpcode))) + { + MultibufferReqCode = (unsigned char)extEntry->base; + MultibufferEventBase = extEntry->eventBase; + MultibufferErrorBase = extEntry->errorBase; + EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = SClobberNotifyEvent; + EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = SUpdateNotifyEvent; + } +} + +/*ARGSUSED*/ +static void +MultibufferResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + ScreenPtr pScreen; + MultibufferScreenPtr pMultibufferScreen; + + if (MultibufferScreenIndex < 0) + return; + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + if (pScreen->devPrivates[MultibufferScreenIndex].ptr) + { + pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr; + pScreen->PositionWindow = pMultibufferScreen->PositionWindow; + xfree (pMultibufferScreen); + } + } +} + +static int +ProcGetBufferVersion (client) + register ClientPtr client; +{ + REQUEST(xMbufGetBufferVersionReq); + xMbufGetBufferVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = MULTIBUFFER_MAJOR_VERSION; + rep.minorVersion = MULTIBUFFER_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof (xMbufGetBufferVersionReply), (char *)&rep); + return (client->noClientException); +} + +static void +SetupBackgroundPainter (pWin, pGC) + WindowPtr pWin; + GCPtr pGC; +{ + pointer gcvalues[4]; + int ts_x_origin, ts_y_origin; + PixUnion background; + int backgroundState; + Mask gcmask; + + /* + * First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + + ts_x_origin = ts_y_origin = 0; + while (pWin->backgroundState == ParentRelative) { + ts_x_origin -= pWin->origin.x; + ts_y_origin -= pWin->origin.y; + pWin = pWin->parent; + } + backgroundState = pWin->backgroundState; + background = pWin->background; + + switch (backgroundState) + { + case BackgroundPixel: + gcvalues[0] = (pointer) background.pixel; + gcvalues[1] = (pointer) FillSolid; + gcmask = GCForeground|GCFillStyle; + break; + + case BackgroundPixmap: + gcvalues[0] = (pointer) FillTiled; + gcvalues[1] = (pointer) background.pixmap; + gcvalues[2] = (pointer) ts_x_origin; + gcvalues[3] = (pointer) ts_y_origin; + gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; + break; + + default: + gcvalues[0] = (pointer) GXnoop; + gcmask = GCFunction; + } + DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE); +} + +int +CreateImageBuffers (pWin, nbuf, ids, action, hint) + WindowPtr pWin; + int nbuf; + XID *ids; + int action; + int hint; +{ + MultibuffersPtr pMultibuffers; + MultibufferPtr pMultibuffer; + ScreenPtr pScreen; + int width, height, depth; + int i; + GCPtr pClearGC = NULL; + xRectangle clearRect; + + DestroyImageBuffers(pWin); + pMultibuffers = (MultibuffersPtr) xalloc (sizeof (MultibuffersRec) + + nbuf * sizeof (MultibufferRec)); + if (!pMultibuffers) + return BadAlloc; + pMultibuffers->pWindow = pWin; + pMultibuffers->buffers = (MultibufferPtr) (pMultibuffers + 1); + pMultibuffers->refcnt = pMultibuffers->numMultibuffer = 0; + if (!AddResource (pWin->drawable.id, MultibuffersResType, (pointer) pMultibuffers)) + return BadAlloc; + width = pWin->drawable.width; + height = pWin->drawable.height; + depth = pWin->drawable.depth; + pScreen = pWin->drawable.pScreen; + + if (pWin->backgroundState != None) + { + pClearGC = GetScratchGC (pWin->drawable.depth, pScreen); + SetupBackgroundPainter (pWin, pClearGC); + clearRect.x = clearRect.y = 0; + clearRect.width = width; + clearRect.height = height; + } + + for (i = 0; i < nbuf; i++) + { + pMultibuffer = &pMultibuffers->buffers[i]; + pMultibuffer->eventMask = 0L; + pMultibuffer->otherEventMask = 0L; + pMultibuffer->otherClients = (OtherClientsPtr) NULL; + pMultibuffer->number = i; + pMultibuffer->side = MultibufferSideMono; + pMultibuffer->clobber = MultibufferUnclobbered; + pMultibuffer->pMultibuffers = pMultibuffers; + if (!AddResource (ids[i], MultibufferResType, (pointer) pMultibuffer)) + break; + pMultibuffer->pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth); + if (!pMultibuffer->pPixmap) + break; + if (!AddResource (ids[i], MultibufferDrawableResType, (pointer) pMultibuffer->pPixmap)) + { + FreeResource (ids[i], MultibufferResType); + (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap); + break; + } + pMultibuffer->pPixmap->drawable.id = ids[i]; + + if (i > 0 && pClearGC) + { + ValidateGC((DrawablePtr)pMultibuffer->pPixmap, pClearGC); + (*pClearGC->ops->PolyFillRect)((DrawablePtr)pMultibuffer->pPixmap, + pClearGC, 1, &clearRect); + } + } + pMultibuffers->numMultibuffer = i; + pMultibuffers->refcnt = i; + pMultibuffers->displayedMultibuffer = -1; + if (i > 0) + AliasMultibuffer (pMultibuffers, 0); + pMultibuffers->updateAction = action; + pMultibuffers->updateHint = hint; + pMultibuffers->windowMode = MultibufferModeMono; + pMultibuffers->lastUpdate.months = 0; + pMultibuffers->lastUpdate.milliseconds = 0; + pMultibuffers->width = width; + pMultibuffers->height = height; + pWin->devPrivates[MultibufferWindowIndex].ptr = (pointer) pMultibuffers; + if (pClearGC) FreeScratchGC(pClearGC); + return Success; +} + +#ifdef PANORAMIX +static int +ProcPanoramiXCreateImageBuffers (client) + register ClientPtr client; +{ + REQUEST(xMbufCreateImageBuffersReq); + + register int result; + int i, j, k, len; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *next; + PanoramiXWindow *pPanoramiXids; + PanoramiXWindow *pPanoramiXPrev_ids; + PanoramiXPmap *local; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + CARD32 *value, *orig_ids; + XID *ids; + XID ID; + DrawablePtr pDrawable; + + REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->window); + IF_RETURN(!pPanoramiXWin, BadRequest); + len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2); + ids = (XID *)ALLOCATE_LOCAL(sizeof(XID)*len); + orig_ids = (XID *)ALLOCATE_LOCAL(sizeof(XID)*len); + if (!ids) + return BadAlloc; + memcpy((char *)orig_ids, (char *) &stuff[1], len * sizeof(XID)); + value = (CARD32 *)&stuff[1]; + /* New resources are pixmaps */ + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->window = pPanoramiXWin->info[j].id; + for (i = 0; i < len; i++) { + ids[i] = (XID)orig_ids[i]; + /* These will be MultibufferDrawableResType & MultibufferResType */ + pPanoramiXPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXPmap, ids[i]); + if (!pPanoramiXPmap) { + local = (PanoramiXWindow *)Xcalloc(sizeof(PanoramiXWindow)); + for (k = 0; k <= PanoramiXNumScreens - 1; k++) { + ID = k ? FakeClientID(client->index) : ids[i]; + local->info[k].id = ID; + } + local->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot); + pPanoramiXPmap->next = local; + value[i] = local->info[j].id; + }else + value[i] = pPanoramiXPmap->info[j].id; + } + if (!j) + noPanoramiXExtension = TRUE; + result = ProcCreateImageBuffers (client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + if (result != Success) { + if (ids) + Xfree(ids); + if (orig_ids) + Xfree(orig_ids); + if (local) + Xfree(local); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcCreateImageBuffers (client) + register ClientPtr client; +{ + REQUEST(xMbufCreateImageBuffersReq); + xMbufCreateImageBuffersReply rep; + register int n; + WindowPtr pWin; + XID *ids; + int len, nbuf; + int i; + int err; + + REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq); + len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2); + if (len == 0) + return BadLength; + if (!(pWin = LookupWindow (stuff->window, client))) + return BadWindow; + if (pWin->drawable.class == InputOnly) + return BadMatch; + switch (stuff->updateAction) + { + case MultibufferUpdateActionUndefined: + case MultibufferUpdateActionBackground: + case MultibufferUpdateActionUntouched: + case MultibufferUpdateActionCopied: + break; + default: + client->errorValue = stuff->updateAction; + return BadValue; + } + switch (stuff->updateHint) + { + case MultibufferUpdateHintFrequent: + case MultibufferUpdateHintIntermittent: + case MultibufferUpdateHintStatic: + break; + default: + client->errorValue = stuff->updateHint; + return BadValue; + } + nbuf = len; + ids = (XID *) &stuff[1]; + for (i = 0; i < nbuf; i++) + { + LEGAL_NEW_RESOURCE(ids[i], client); + } + err = CreateImageBuffers (pWin, nbuf, ids, + stuff->updateAction, stuff->updateHint); + if (err != Success) + return err; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.numberBuffer = ((MultibuffersPtr) (pWin->devPrivates[MultibufferWindowIndex].ptr))->numMultibuffer; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.numberBuffer, n); + } +#ifdef PANORAMIX + if (noPanoramiXExtension) +#endif + WriteToClient(client, sizeof (xMbufCreateImageBuffersReply), (char*)&rep); + return (client->noClientException); +} + +static int +ProcDisplayImageBuffers (client) + register ClientPtr client; +{ + REQUEST(xMbufDisplayImageBuffersReq); + MultibufferPtr *pMultibuffer; + MultibuffersPtr *ppMultibuffers; + int nbuf; + XID *ids; + int i, j; + CARD32 minDelay; + TimeStamp activateTime, bufferTime; + +#ifdef PANORAMIX + WindowPtr pWndw; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + MultibufferPtr *pScrn0Multibuffer; + MultibuffersPtr *ppScrn0Multibuffers; + int k; + int panoramiX_buf = 0; + Bool FoundScreen; + +#endif + + REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq); + nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2); + if (!nbuf) + return Success; + minDelay = stuff->minDelay; + ids = (XID *) &stuff[1]; +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + int maxbuf = 0; + maxbuf = nbuf * PanoramiXNumScreens; + ppScrn0Multibuffers = (MultibuffersPtr *) xalloc(maxbuf * sizeof (MultibuffersPtr)); + pScrn0Multibuffer = (MultibufferPtr *) xalloc (maxbuf * sizeof(MultibufferPtr)); + if (!ppScrn0Multibuffers || !pScrn0Multibuffer) + { + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + xfree (ppScrn0Multibuffers); + xfree (pScrn0Multibuffer); + client->errorValue = 0; + return BadAlloc; + } + } +#endif + ppMultibuffers = (MultibuffersPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibuffersPtr)); + pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibufferPtr)); + if (!ppMultibuffers || !pMultibuffer) + { + if (ppMultibuffers) DEALLOCATE_LOCAL(ppMultibuffers); + if (pMultibuffer) DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = 0; + return BadAlloc; + } + activateTime.months = 0; + activateTime.milliseconds = 0; + for (i = 0; i < nbuf; i++) + { +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + pPanoramiXPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXPmap, ids[i]); + if (!pPanoramiXPmap){ + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + xfree (ppMultibuffers); + xfree (pMultibuffer); + client->errorValue = ids[i]; + return MultibufferErrorBase + MultibufferBadBuffer; + } + FoundScreen = FALSE; + pScrn0Multibuffer[panoramiX_buf] = (MultibufferPtr) + LookupIDByType (ids[i], MultibufferResType); + ppScrn0Multibuffers[i] = pScrn0Multibuffer[i]->pMultibuffers; + pWndw = ppScrn0Multibuffers[i]->pWindow; + for (k = 0; (k < PanoramiXNumScreens && !FoundScreen); k++) { + pMultibuffer[panoramiX_buf] = (MultibufferPtr) + LookupIDByType (pPanoramiXPmap->info[k].id, MultibufferResType); + if (!pMultibuffer[i]) + { + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + xfree (ppMultibuffers); + xfree (pMultibuffer); + client->errorValue = ids[i]; + return MultibufferErrorBase + MultibufferBadBuffer; + } + ppMultibuffers[panoramiX_buf] = pMultibuffer[panoramiX_buf]->pMultibuffers; + /* Figure out where the buffer resides, which screens */ + if ( ((pWndw->drawable.x < 0) && + (pWndw->drawable.x + pWndw->drawable.width < 0)) + || ( (pWndw->drawable.x > + panoramiXdataPtr[k].x + panoramiXdataPtr[k].width) && + (pWndw->drawable.x + pWndw->drawable.width > + panoramiXdataPtr[k].x + panoramiXdataPtr[k].width))) + /* its not on screen - k -, try next screen */ + continue; + if ( ((pWndw->drawable.y < 0) && + (pWndw->drawable.y + pWndw->drawable.height < 0)) + || ( (pWndw->drawable.y > + panoramiXdataPtr[k].y + panoramiXdataPtr[k].height) && + (pWndw->drawable.y + pWndw->drawable.height > + panoramiXdataPtr[k].y + panoramiXdataPtr[k].height))) + /* its not on screen - k -, try next screen */ + continue; + + /* The window resides on screen k, which means we need to + keep the buffer information for this screen */ + panoramiX_buf++; + + /* Is it only on this screen, or does it enter onto another + screen */ + if ( ((pWndw->drawable.x + pWndw->drawable.width) <= + (panoramiXdataPtr[k].x + panoramiXdataPtr[k].width)) && + ((pWndw->drawable.y + pWndw->drawable.height) <= + (panoramiXdataPtr[k].y + + panoramiXdataPtr[k].height )) ) + FoundScreen = TRUE; + } /* for each screen k */ + for (j = 0; j < i; j++) + { + if (ppScrn0Multibuffers[i] == ppScrn0Multibuffers[j]) + { + if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids); + DEALLOCATE_LOCAL(ppScrn0Multibuffers); + DEALLOCATE_LOCAL(pScrn0Multibuffer); + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = ids[i]; + return BadMatch; + } + } + bufferTime = ppScrn0Multibuffers[i]->lastUpdate; + }else { +#endif + pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], +MultibufferResType); + if (!pMultibuffer[i]) + { + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = ids[i]; + return MultibufferErrorBase + MultibufferBadBuffer; + } + ppMultibuffers[i] = pMultibuffer[i]->pMultibuffers; + for (j = 0; j < i; j++) + { + if (ppMultibuffers[i] == ppMultibuffers[j]) + { + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + client->errorValue = ids[i]; + return BadMatch; + } + } + bufferTime = ppMultibuffers[i]->lastUpdate; +#ifdef PANORAMIX + } +#endif + BumpTimeStamp (&bufferTime, minDelay); + if (CompareTimeStamps (bufferTime, activateTime) == LATER) + activateTime = bufferTime; + } + UpdateCurrentTime (); + if (CompareTimeStamps (activateTime, currentTime) == LATER && + QueueDisplayRequest (client, activateTime)) + { + ; + } + else +#ifdef PANORAMIX + if (!noPanoramiXExtension){ + PerformDisplayRequest (ppMultibuffers, pMultibuffer, panoramiX_buf); + }else +#endif + PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf); + +#ifdef PANORAMIX + if (!noPanoramiXExtension){ + DEALLOCATE_LOCAL(ppScrn0Multibuffers); + DEALLOCATE_LOCAL(pScrn0Multibuffer); + } +#endif + + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + return Success; +} + +#ifdef PANORAMIX +static int +ProcPanoramiXDestroyImageBuffers (client) + ClientPtr client; +{ + REQUEST (xMbufDestroyImageBuffersReq); + WindowPtr pWin; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->window); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->window = pPanoramiXWin->info[j].id; + result = ProcDestroyImageBuffers (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcDestroyImageBuffers (client) + register ClientPtr client; +{ + REQUEST (xMbufDestroyImageBuffersReq); + WindowPtr pWin; + + REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq); + if (!(pWin = LookupWindow (stuff->window, client))) + return BadWindow; + DestroyImageBuffers (pWin); + return Success; +} + +#ifdef PANORAMIX +static int +ProcPanoramiXSetMBufferAttributes (client) + ClientPtr client; +{ + REQUEST (xMbufSetMBufferAttributesReq); + WindowPtr pWin; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH (xMbufSetMBufferAttributesReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->window); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->window = pPanoramiXWin->info[j].id; + result = ProcSetMBufferAttributes (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif +#ifdef PANORAMIX +int +#else +static int +#endif +ProcSetMBufferAttributes (client) + register ClientPtr client; +{ + REQUEST (xMbufSetMBufferAttributesReq); + WindowPtr pWin; + MultibuffersPtr pMultibuffers; + int len; + Mask vmask; + Mask index; + CARD32 updateHint; + XID *vlist; + + REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType); + if (!pMultibuffers) + return BadMatch; + len = stuff->length - (sizeof (xMbufSetMBufferAttributesReq) >> 2); + vmask = stuff->valueMask; + if (len != Ones (vmask)) + return BadLength; + vlist = (XID *) &stuff[1]; + while (vmask) + { + index = (Mask) lowbit (vmask); + vmask &= ~index; + switch (index) + { + case MultibufferWindowUpdateHint: + updateHint = (CARD32) *vlist; + switch (updateHint) + { + case MultibufferUpdateHintFrequent: + case MultibufferUpdateHintIntermittent: + case MultibufferUpdateHintStatic: + pMultibuffers->updateHint = updateHint; + break; + default: + client->errorValue = updateHint; + return BadValue; + } + vlist++; + break; + default: + client->errorValue = stuff->valueMask; + return BadValue; + } + } + return Success; +} + +static int +ProcGetMBufferAttributes (client) + ClientPtr client; +{ + REQUEST (xMbufGetMBufferAttributesReq); + WindowPtr pWin; + MultibuffersPtr pMultibuffers; + XID *ids; + xMbufGetMBufferAttributesReply rep; + int i, n; + + REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType); + if (!pMultibuffers) + return BadAccess; + ids = (XID *) ALLOCATE_LOCAL (pMultibuffers->numMultibuffer * sizeof (XID)); + if (!ids) + return BadAlloc; + for (i = 0; i < pMultibuffers->numMultibuffer; i++) + ids[i] = pMultibuffers->buffers[i].pPixmap->drawable.id; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = pMultibuffers->numMultibuffer; + rep.displayedBuffer = pMultibuffers->displayedMultibuffer; + rep.updateAction = pMultibuffers->updateAction; + rep.updateHint = pMultibuffers->updateHint; + rep.windowMode = pMultibuffers->windowMode; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.displayedBuffer, n); + SwapLongs (ids, pMultibuffers->numMultibuffer); + } + WriteToClient (client, sizeof(xMbufGetMBufferAttributesReply), + (char *)&rep); + WriteToClient (client, (int)(pMultibuffers->numMultibuffer * sizeof (XID)), + (char *)ids); + DEALLOCATE_LOCAL((pointer) ids); + return client->noClientException; +} + +static int +ProcSetBufferAttributes (client) + register ClientPtr client; +{ + REQUEST(xMbufSetBufferAttributesReq); + MultibufferPtr pMultibuffer; + int len; + Mask vmask, index; + XID *vlist; + Mask eventMask; + int result; + + REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq); + pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType); + if (!pMultibuffer) + return MultibufferErrorBase + MultibufferBadBuffer; + len = stuff->length - (sizeof (xMbufSetBufferAttributesReq) >> 2); + vmask = stuff->valueMask; + if (len != Ones (vmask)) + return BadLength; + vlist = (XID *) &stuff[1]; + while (vmask) + { + index = (Mask) lowbit (vmask); + vmask &= ~index; + switch (index) + { + case MultibufferBufferEventMask: + eventMask = (Mask) *vlist; + vlist++; + result = EventSelectForMultibuffer (pMultibuffer, client, eventMask); + if (result != Success) + return result; + break; + default: + client->errorValue = stuff->valueMask; + return BadValue; + } + } + return Success; +} + +ProcGetBufferAttributes (client) + register ClientPtr client; +{ + REQUEST(xMbufGetBufferAttributesReq); + MultibufferPtr pMultibuffer; + xMbufGetBufferAttributesReply rep; + OtherClientsPtr other; + int n; + + REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq); + pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType); + if (!pMultibuffer) + return MultibufferErrorBase + MultibufferBadBuffer; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.window = pMultibuffer->pMultibuffers->pWindow->drawable.id; + if (bClient (pMultibuffer) == client) + rep.eventMask = pMultibuffer->eventMask; + else + { + rep.eventMask = (Mask) 0L; + for (other = pMultibuffer->otherClients; other; other = other->next) + if (SameClient (other, client)) + { + rep.eventMask = other->mask; + break; + } + } + rep.bufferIndex = pMultibuffer->number; + rep.side = pMultibuffer->side; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.window, n); + swapl(&rep.eventMask, n); + swaps(&rep.bufferIndex, n); + } + WriteToClient(client, sizeof (xMbufGetBufferAttributesReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcGetBufferInfo (client) + register ClientPtr client; +{ + REQUEST (xMbufGetBufferInfoReq); + DrawablePtr pDrawable; + xMbufGetBufferInfoReply rep; + ScreenPtr pScreen; + int i, j, k; + int n; + xMbufBufferInfo *pInfo; + int nInfo; + DepthPtr pDepth; + + pDrawable = (DrawablePtr) LookupDrawable (stuff->drawable, client); + if (!pDrawable) + return BadDrawable; + pScreen = pDrawable->pScreen; + nInfo = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + nInfo += pDepth->numVids; + } + pInfo = (xMbufBufferInfo *) + ALLOCATE_LOCAL (nInfo * sizeof (xMbufBufferInfo)); + if (!pInfo) + return BadAlloc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = nInfo * (sizeof (xMbufBufferInfo) >> 2); + rep.normalInfo = nInfo; + rep.stereoInfo = 0; + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.normalInfo, n); + swaps(&rep.stereoInfo, n); + } + + k = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + for (j = 0; j < pDepth->numVids; j++) + { + pInfo[k].visualID = pDepth->vids[j]; + pInfo[k].maxBuffers = 0; + pInfo[k].depth = pDepth->depth; + if (client->swapped) + { + swapl (&pInfo[k].visualID, n); + swaps (&pInfo[k].maxBuffers, n); + } + k++; + } + } + WriteToClient (client, sizeof (xMbufGetBufferInfoReply), (pointer) &rep); + WriteToClient (client, (int) nInfo * sizeof (xMbufBufferInfo), (pointer) pInfo); + DEALLOCATE_LOCAL ((pointer) pInfo); + return client->noClientException; +} + +static int +ProcClearImageBufferArea (client) + register ClientPtr client; +{ + REQUEST (xMbufClearImageBufferAreaReq); + MultibufferPtr pMultibuffer; + WindowPtr pWin; + xRectangle clearRect; + int width, height; + DrawablePtr pDrawable; + ScreenPtr pScreen; + + REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq); + pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType); + if (!pMultibuffer) + return MultibufferErrorBase + MultibufferBadBuffer; + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + pWin = pMultibuffer->pMultibuffers->pWindow; + width = pWin->drawable.width; + height = pWin->drawable.height; + pScreen = pWin->drawable.pScreen; + + clearRect.x = stuff->x; + clearRect.y = stuff->y; + clearRect.width = stuff->width ? stuff->width : width; + clearRect.height = stuff->height ? stuff->height : height; + + if (pWin->backgroundState != None) + { + GCPtr pClearGC; + pClearGC = GetScratchGC (pWin->drawable.depth, pScreen); + SetupBackgroundPainter (pWin, pClearGC); + + if (pMultibuffer->number == pMultibuffer->pMultibuffers->displayedMultibuffer) + pDrawable = (DrawablePtr)pWin; + else + pDrawable = (DrawablePtr)pMultibuffer->pPixmap; + + ValidateGC(pDrawable, pClearGC); + (*pClearGC->ops->PolyFillRect) (pDrawable, pClearGC, 1, &clearRect); + FreeScratchGC(pClearGC); + } + + if (stuff->exposures) + { + RegionRec region; + BoxRec box; + box.x1 = clearRect.x; + box.y1 = clearRect.y; + box.x2 = clearRect.x + clearRect.width; + box.y2 = clearRect.y + clearRect.height; + REGION_INIT(pScreen, ®ion, &box, 1); + MultibufferExpose(pMultibuffer, ®ion); + REGION_UNINIT(pScreen, ®ion); + } + return Success; +} + +static int +ProcMultibufferDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_MbufGetBufferVersion: + return ProcGetBufferVersion (client); + case X_MbufCreateImageBuffers: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXCreateImageBuffers (client); + else + return ProcCreateImageBuffers (client); +#else + return ProcCreateImageBuffers (client); +#endif + case X_MbufDisplayImageBuffers: + return ProcDisplayImageBuffers (client); + case X_MbufDestroyImageBuffers: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXDestroyImageBuffers (client); + else + return ProcDestroyImageBuffers (client); +#else + return ProcDestroyImageBuffers (client); +#endif + case X_MbufSetMBufferAttributes: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXSetMBufferAttributes (client); + else + return ProcSetMBufferAttributes (client); +#else + return ProcSetMBufferAttributes (client); +#endif + case X_MbufGetMBufferAttributes: + return ProcGetMBufferAttributes (client); + case X_MbufSetBufferAttributes: + return ProcSetBufferAttributes (client); + case X_MbufGetBufferAttributes: + return ProcGetBufferAttributes (client); + case X_MbufGetBufferInfo: + return ProcGetBufferInfo (client); + case X_MbufClearImageBufferArea: + return ProcClearImageBufferArea (client); + default: + return BadRequest; + } +} + +static int +SProcGetBufferVersion (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetBufferVersionReq); + + swaps (&stuff->length, n); + return ProcGetBufferVersion (client); +} + +static int +SProcCreateImageBuffers (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufCreateImageBuffersReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq); + swapl (&stuff->window, n); + SwapRestL(stuff); + return ProcCreateImageBuffers (client); +} + +static int +SProcDisplayImageBuffers (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufDisplayImageBuffersReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq); + swaps (&stuff->minDelay, n); + swaps (&stuff->maxDelay, n); + SwapRestL(stuff); + return ProcDisplayImageBuffers (client); +} + +static int +SProcDestroyImageBuffers (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufDestroyImageBuffersReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq); + swapl (&stuff->window, n); + return ProcDestroyImageBuffers (client); +} + +static int +SProcSetMBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufSetMBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq); + swapl (&stuff->window, n); + swapl (&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSetMBufferAttributes (client); +} + +static int +SProcGetMBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetMBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq); + swapl (&stuff->window, n); + return ProcGetMBufferAttributes (client); +} + +static int +SProcSetBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufSetBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq); + swapl (&stuff->buffer, n); + swapl (&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSetBufferAttributes (client); +} + +static int +SProcGetBufferAttributes (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetBufferAttributesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq); + swapl (&stuff->buffer, n); + return ProcGetBufferAttributes (client); +} + +static int +SProcGetBufferInfo (client) + register ClientPtr client; +{ + register int n; + REQUEST (xMbufGetBufferInfoReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq); + swapl (&stuff->drawable, n); + return ProcGetBufferInfo (client); +} + +static int +SProcClearImageBufferArea(client) + register ClientPtr client; +{ + register char n; + REQUEST(xMbufClearImageBufferAreaReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq); + swapl(&stuff->buffer, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcClearImageBufferArea(client); +} + +static int +SProcMultibufferDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_MbufGetBufferVersion: + return SProcGetBufferVersion (client); + case X_MbufCreateImageBuffers: + return SProcCreateImageBuffers (client); + case X_MbufDisplayImageBuffers: + return SProcDisplayImageBuffers (client); + case X_MbufDestroyImageBuffers: + return SProcDestroyImageBuffers (client); + case X_MbufSetMBufferAttributes: + return SProcSetMBufferAttributes (client); + case X_MbufGetMBufferAttributes: + return SProcGetMBufferAttributes (client); + case X_MbufSetBufferAttributes: + return SProcSetBufferAttributes (client); + case X_MbufGetBufferAttributes: + return SProcGetBufferAttributes (client); + case X_MbufGetBufferInfo: + return SProcGetBufferInfo (client); + case X_MbufClearImageBufferArea: + return SProcClearImageBufferArea (client); + default: + return BadRequest; + } +} + +static void +SUpdateNotifyEvent (from, to) + xMbufUpdateNotifyEvent *from, *to; +{ + to->type = from->type; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->buffer, to->buffer); + cpswapl (from->timeStamp, to->timeStamp); +} + +static void +SClobberNotifyEvent (from, to) + xMbufClobberNotifyEvent *from, *to; +{ + to->type = from->type; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->buffer, to->buffer); + to->state = from->state; +} + +static void +PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf) + MultibufferPtr *pMultibuffer; + MultibuffersPtr *ppMultibuffers; + int nbuf; +{ + GCPtr pGC; + PixmapPtr pPrevPixmap, pNewPixmap; + xRectangle clearRect; + WindowPtr pWin; + RegionPtr pExposed; + int i; + MultibufferPtr pPrevMultibuffer; + XID graphicsExpose; + + UpdateCurrentTime (); + for (i = 0; i < nbuf; i++) + { + pWin = ppMultibuffers[i]->pWindow; + pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen); + pPrevMultibuffer = + &ppMultibuffers[i]->buffers[ppMultibuffers[i]->displayedMultibuffer]; + pPrevPixmap = pPrevMultibuffer->pPixmap; + pNewPixmap = pMultibuffer[i]->pPixmap; + switch (ppMultibuffers[i]->updateAction) + { + case MultibufferUpdateActionUndefined: + break; + case MultibufferUpdateActionBackground: + SetupBackgroundPainter (pWin, pGC); + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = pPrevPixmap->drawable.width; + clearRect.height = pPrevPixmap->drawable.height; + (*pGC->ops->PolyFillRect) ((DrawablePtr)pPrevPixmap, pGC, + 1, &clearRect); + break; + case MultibufferUpdateActionUntouched: + /* copy the window to the pixmap that represents the + * currently displayed buffer + */ + if (pPrevMultibuffer->eventMask & ExposureMask) + { + graphicsExpose = TRUE; + DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE); + } + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + pExposed = (*pGC->ops->CopyArea) + ((DrawablePtr) pWin, + (DrawablePtr) pPrevPixmap, + pGC, + 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + + /* if we couldn't copy the whole window to the buffer, + * send expose events (if any client wants them) + */ + if (pPrevMultibuffer->eventMask & ExposureMask) + { /* some client wants expose events */ + if (pExposed) + { + RegionPtr pWinSize; + ScreenPtr pScreen = pWin->drawable.pScreen; + extern RegionPtr CreateUnclippedWinSize(); + + pWinSize = CreateUnclippedWinSize (pWin); + /* pExposed is window-relative, but at this point + * pWinSize is screen-relative. Make pWinSize be + * window-relative so that region ops involving + * pExposed and pWinSize behave sensibly. + */ + REGION_TRANSLATE(pScreen, pWinSize, + -pWin->drawable.x, + -pWin->drawable.y); + REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize); + REGION_DESTROY(pScreen, pWinSize); + MultibufferExpose (pPrevMultibuffer, pExposed); + REGION_DESTROY(pScreen, pExposed); + } + graphicsExpose = FALSE; + DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE); + } + break; /* end case MultibufferUpdateActionUntouched */ + + case MultibufferUpdateActionCopied: + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, + (DrawablePtr)pPrevPixmap, pGC, + 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + break; + } /* end switch on update action */ + + /* display the new buffer */ + ValidateGC ((DrawablePtr)pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin, pGC, + 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + ppMultibuffers[i]->lastUpdate = currentTime; + MultibufferUpdate (pMultibuffer[i], + ppMultibuffers[i]->lastUpdate.milliseconds); + AliasMultibuffer (ppMultibuffers[i], + pMultibuffer[i] - ppMultibuffers[i]->buffers); + FreeScratchGC (pGC); + } +} + +DrawablePtr +GetBufferPointer (pWin, i) + WindowPtr pWin; + int i; +{ + MultibuffersPtr pMultibuffers; + + if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr)) + return NULL; + return (DrawablePtr) pMultibuffers->buffers[i].pPixmap; +} + +int +DisplayImageBuffers (ids, nbuf) + XID *ids; + int nbuf; +{ + MultibufferPtr *pMultibuffer; + MultibuffersPtr *pMultibuffers; + int i, j; + + pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL (nbuf * sizeof *pMultibuffer + + nbuf * sizeof *pMultibuffers); + if (!pMultibuffer) + return BadAlloc; + pMultibuffers = (MultibuffersPtr *) (pMultibuffer + nbuf); + for (i = 0; i < nbuf; i++) + { + pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], MultibufferResType); + if (!pMultibuffer[i]) + { + DEALLOCATE_LOCAL (pMultibuffer); + return MultibufferErrorBase + MultibufferBadBuffer; + } + pMultibuffers[i] = pMultibuffer[i]->pMultibuffers; + for (j = 0; j < i; j++) + if (pMultibuffers[i] == pMultibuffers[j]) + { + DEALLOCATE_LOCAL (pMultibuffer); + return BadMatch; + } + } + PerformDisplayRequest (pMultibuffers, pMultibuffer, nbuf); + DEALLOCATE_LOCAL (pMultibuffer); + return Success; +} + + +static Bool +QueueDisplayRequest (client, activateTime) + ClientPtr client; + TimeStamp activateTime; +{ + /* see xtest.c:ProcXTestFakeInput for code similar to this */ + + if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) + { + return FALSE; + } + /* swap the request back so we can simply re-execute it */ + if (client->swapped) + { + register int n; + REQUEST (xMbufDisplayImageBuffersReq); + + SwapRestL(stuff); + swaps (&stuff->length, n); + swaps (&stuff->minDelay, n); + swaps (&stuff->maxDelay, n); + } + ResetCurrentRequest (client); + client->sequence--; + return TRUE; +} + + +/* + * Deliver events to a buffer + */ + +static int +DeliverEventsToMultibuffer (pMultibuffer, pEvents, count, filter) + MultibufferPtr pMultibuffer; + xEvent *pEvents; + int count; + Mask filter; +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + OtherClients *other; + + /* if nobody wants the event, we're done */ + if (!((pMultibuffer->otherEventMask|pMultibuffer->eventMask) & filter)) + return 0; + + /* maybe send event to owner */ + if (attempt = TryClientEvents( + bClient(pMultibuffer), pEvents, count, pMultibuffer->eventMask, filter, (GrabPtr) 0)) + { + if (attempt > 0) + deliveries++; + else + nondeliveries--; + } + + /* maybe send event to other clients */ + for (other = pMultibuffer->otherClients; other; other=other->next) + { + if (attempt = TryClientEvents( + rClient(other), pEvents, count, other->mask, filter, (GrabPtr) 0)) + { + if (attempt > 0) + deliveries++; + else + nondeliveries--; + } + } + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* + * Send Expose events to interested clients + */ + +void +MultibufferExpose (pMultibuffer, pRegion) + MultibufferPtr pMultibuffer; + RegionPtr pRegion; +{ + if (pRegion && !REGION_NIL(pRegion)) + { + xEvent *pEvent; + PixmapPtr pPixmap; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + pPixmap = pMultibuffer->pPixmap; + REGION_TRANSLATE(pPixmap->drawable.pScreen, pRegion, + -pPixmap->drawable.x, -pPixmap->drawable.y); + /* XXX MultibufferExpose "knows" the region representation */ + numRects = REGION_NUM_RECTS(pRegion); + pBox = REGION_RECTS(pRegion); + + pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)); + if (pEvent) { + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pPixmap->drawable.id; + pe->u.expose.x = pBox->x1; + pe->u.expose.y = pBox->y1; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = (numRects - i); + } + (void) DeliverEventsToMultibuffer (pMultibuffer, pEvent, numRects, + ExposureMask); + DEALLOCATE_LOCAL(pEvent); + } + } +} + +/* send UpdateNotify event */ +void +MultibufferUpdate (pMultibuffer, time) + MultibufferPtr pMultibuffer; + CARD32 time; +{ + xMbufUpdateNotifyEvent event; + + event.type = MultibufferEventBase + MultibufferUpdateNotify; + event.buffer = pMultibuffer->pPixmap->drawable.id; + event.timeStamp = time; + (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event, + 1, (Mask)MultibufferUpdateNotifyMask); +} + +/* + * The sample implementation will never generate MultibufferClobberNotify + * events + */ + +void +MultibufferClobber (pMultibuffer) + MultibufferPtr pMultibuffer; +{ + xMbufClobberNotifyEvent event; + + event.type = MultibufferEventBase + MultibufferClobberNotify; + event.buffer = pMultibuffer->pPixmap->drawable.id; + event.state = pMultibuffer->clobber; + (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event, + 1, (Mask)MultibufferClobberNotifyMask); +} + +/* + * make the resource id for buffer i refer to the window + * drawable instead of the pixmap; + */ + +static void +AliasMultibuffer (pMultibuffers, i) + MultibuffersPtr pMultibuffers; + int i; +{ + MultibufferPtr pMultibuffer; + + if (i == pMultibuffers->displayedMultibuffer) + return; + /* + * remove the old association + */ + if (pMultibuffers->displayedMultibuffer >= 0) + { + pMultibuffer = &pMultibuffers->buffers[pMultibuffers->displayedMultibuffer]; + ChangeResourceValue (pMultibuffer->pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pMultibuffer->pPixmap); + } + /* + * make the new association + */ + pMultibuffer = &pMultibuffers->buffers[i]; + ChangeResourceValue (pMultibuffer->pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pMultibuffers->pWindow); + pMultibuffers->displayedMultibuffer = i; +} + +/* + * free everything associated with multibuffering for this + * window + */ + +void +DestroyImageBuffers (pWin) + WindowPtr pWin; +{ + FreeResourceByType (pWin->drawable.id, MultibuffersResType, FALSE); + /* Zero out the window's pointer to the buffers so they won't be reused */ + pWin->devPrivates[MultibufferWindowIndex].ptr = NULL; +} + +/* + * resize the buffers when the window is resized + */ + +static Bool +MultibufferPositionWindow (pWin, x, y) + WindowPtr pWin; + int x, y; +{ + ScreenPtr pScreen; + MultibufferScreenPtr pMultibufferScreen; + MultibuffersPtr pMultibuffers; + MultibufferPtr pMultibuffer; + int width, height; + int i; + int dx, dy, dw, dh; + int sourcex, sourcey; + int destx, desty; + PixmapPtr pPixmap; + GCPtr pGC; + int savewidth, saveheight; + xRectangle clearRect; + Bool clear; + + pScreen = pWin->drawable.pScreen; + pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr; + (*pMultibufferScreen->PositionWindow) (pWin, x, y); + + /* if this window is not multibuffered, we're done */ + if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr)) + return TRUE; + + /* if new size is same as old, we're done */ + if (pMultibuffers->width == pWin->drawable.width && + pMultibuffers->height == pWin->drawable.height) + return TRUE; + + width = pWin->drawable.width; + height = pWin->drawable.height; + dx = pWin->drawable.x - pMultibuffers->x; + dy = pWin->drawable.x - pMultibuffers->y; + dw = width - pMultibuffers->width; + dh = height - pMultibuffers->height; + GravityTranslate (0, 0, -dx, -dy, dw, dh, + pWin->bitGravity, &destx, &desty); + + /* if the window grew, remember to paint the window background, + * and maybe send expose events, for the new areas of the buffers + */ + clear = pMultibuffers->width < width || pMultibuffers->height < height || + pWin->bitGravity == ForgetGravity; + + sourcex = 0; + sourcey = 0; + savewidth = pMultibuffers->width; + saveheight = pMultibuffers->height; + /* clip rectangle to source and destination */ + if (destx < 0) + { + savewidth += destx; + sourcex -= destx; + destx = 0; + } + if (destx + savewidth > width) + savewidth = width - destx; + if (desty < 0) + { + saveheight += desty; + sourcey -= desty; + desty = 0; + } + if (desty + saveheight > height) + saveheight = height - desty; + + pMultibuffers->width = width; + pMultibuffers->height = height; + pMultibuffers->x = pWin->drawable.x; + pMultibuffers->y = pWin->drawable.y; + + pGC = GetScratchGC (pWin->drawable.depth, pScreen); + if (clear) + { + SetupBackgroundPainter (pWin, pGC); + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = width; + clearRect.height = height; + } + for (i = 0; i < pMultibuffers->numMultibuffer; i++) + { + pMultibuffer = &pMultibuffers->buffers[i]; + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pWin->drawable.depth); + if (!pPixmap) + { + DestroyImageBuffers (pWin); + break; + } + ValidateGC ((DrawablePtr)pPixmap, pGC); + /* + * I suppose this could avoid quite a bit of work if + * it computed the minimal area required. + */ + if (clear) + (*pGC->ops->PolyFillRect) ((DrawablePtr)pPixmap, pGC, 1, &clearRect); + if (pWin->bitGravity != ForgetGravity) + { + (*pGC->ops->CopyArea) ((DrawablePtr)pMultibuffer->pPixmap, + (DrawablePtr)pPixmap, pGC, + sourcex, sourcey, savewidth, saveheight, + destx, desty); + } + pPixmap->drawable.id = pMultibuffer->pPixmap->drawable.id; + (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap); + pMultibuffer->pPixmap = pPixmap; + if (i != pMultibuffers->displayedMultibuffer) + { + ChangeResourceValue (pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pPixmap); + } + } + FreeScratchGC (pGC); + return TRUE; +} + +/* Resource delete func for MultibufferDrawableResType */ +/*ARGSUSED*/ +static int +MultibufferDrawableDelete (value, id) + pointer value; + XID id; +{ + DrawablePtr pDrawable = (DrawablePtr)value; + WindowPtr pWin; + MultibuffersPtr pMultibuffers; + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW) + { + pWin = (WindowPtr) pDrawable; + pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr; + pPixmap = pMultibuffers->buffers[pMultibuffers->displayedMultibuffer].pPixmap; + } + else + { + pPixmap = (PixmapPtr) pDrawable; + } + (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); + return Success; +} + +/* Resource delete func for MultibufferResType */ +/*ARGSUSED*/ +static int +MultibufferDelete (value, id) + pointer value; + XID id; +{ + MultibufferPtr pMultibuffer = (MultibufferPtr)value; + MultibuffersPtr pMultibuffers; + + pMultibuffers = pMultibuffer->pMultibuffers; + if (--pMultibuffers->refcnt == 0) + { + FreeResourceByType (pMultibuffers->pWindow->drawable.id, + MultibuffersResType, TRUE); + xfree (pMultibuffers); + } + return Success; +} + +/* Resource delete func for MultibuffersResType */ +/*ARGSUSED*/ +static int +MultibuffersDelete (value, id) + pointer value; + XID id; +{ + MultibuffersPtr pMultibuffers = (MultibuffersPtr)value; + int i; + + if (pMultibuffers->refcnt == pMultibuffers->numMultibuffer) + { + for (i = pMultibuffers->numMultibuffer; --i >= 0; ) + FreeResource (pMultibuffers->buffers[i].pPixmap->drawable.id, 0); + } + return Success; +} + +/* Resource delete func for OtherClientResType */ +static int +OtherClientDelete (value, id) + pointer value; + XID id; +{ + MultibufferPtr pMultibuffer = (MultibufferPtr)value; + register OtherClientsPtr other, prev; + + prev = 0; + for (other = pMultibuffer->otherClients; other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + pMultibuffer->otherClients = other->next; + xfree (other); + RecalculateMultibufferOtherEvents (pMultibuffer); + break; + } + prev = other; + } + return Success; +} + +static int +EventSelectForMultibuffer (pMultibuffer, client, mask) + MultibufferPtr pMultibuffer; + ClientPtr client; + Mask mask; +{ + OtherClientsPtr other; + + if (mask & ~ValidEventMasks) + { + client->errorValue = mask; + return BadValue; + } + if (bClient (pMultibuffer) == client) + { + pMultibuffer->eventMask = mask; + } + else /* some other client besides the creator wants events */ + { + for (other = pMultibuffer->otherClients; other; other = other->next) + { + if (SameClient (other, client)) + { + if (mask == 0) + { + FreeResource (other->resource, RT_NONE); + break; + } + other->mask = mask; + break; + } + } + if (!other) + { /* new client that never selected events on this buffer before */ + other = (OtherClients *) xalloc (sizeof (OtherClients)); + if (!other) + return BadAlloc; + other->mask = mask; + other->resource = FakeClientID (client->index); + if (!AddResource (other->resource, OtherClientResType, (pointer) pMultibuffer)) + { + xfree (other); + return BadAlloc; + } + other->next = pMultibuffer->otherClients; + pMultibuffer->otherClients = other; + } + RecalculateMultibufferOtherEvents (pMultibuffer); + } + return (client->noClientException); +} + +/* or together all the otherClients event masks */ +static void +RecalculateMultibufferOtherEvents (pMultibuffer) + MultibufferPtr pMultibuffer; +{ + Mask otherEventMask; + OtherClients *other; + + otherEventMask = 0L; + for (other = pMultibuffer->otherClients; other; other = other->next) + otherEventMask |= other->mask; + pMultibuffer->otherEventMask = otherEventMask; +} + +/* add milliseconds to a timestamp, handling overflow */ +static void +BumpTimeStamp (ts, inc) +TimeStamp *ts; +CARD32 inc; +{ + CARD32 newms; + + newms = ts->milliseconds + inc; + if (newms < ts->milliseconds) + ts->months++; + ts->milliseconds = newms; +} diff --git a/Xext/mbufbf.c b/Xext/mbufbf.c new file mode 100644 index 000000000..3c873086f --- /dev/null +++ b/Xext/mbufbf.c @@ -0,0 +1,1052 @@ +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* $Xorg: mbufbf.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" +#include "validate.h" +#include <sys/time.h> + +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#define _MULTIBUF_BUFFER_ +#include "multibufst.h" + +/* +Support for doublebuffer hardare + +This code is designed to support doublebuffer hardware where the +displayed buffer is selected on a per-pixel basis by an additional bit +plane, called the select plane. It could probably be easily modified +to work with systems that use window-id planes. + +This is done by creating a new drawable type, DRAWABLE_BUFFER. The +type has the same exact layout as a window drawable. Your code should +treat a DRAWABLE_BUFFER the same as it would tread a DRAWABLE_WINDOW +when handling the gc drawing functions. In addition, PaintWindowBackground, +CopyWindow, and all of the gc drawing functions to be able to draw into both +framebuffers. Which framebuffer to draw into is selected by the contents of + pWin->devPrivates[frameWindowPrivateIndex]. +The content of the devPrivate is either from frameBuffer[0] or +frameBuffer[1], depending on which buffer is being drawn into. When + pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[0], +the functions should draw into the front framebuffer. When + pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[1], +the functions should draw into the back framebuffer. + +In addition, you need to provide a function that allows you to copy +bits between the buffers (optional since CopyArea can be used) and a +function that draws into the select plane. Then, you need to register +your functions and other information, by calling: + +void +RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane, + CopyBufferBitsFunc, DrawSelectPlaneFunc) + int nInfo; + xMbufBufferInfo *pInfo; + DevUnion *frameBuffer; + DevUnion selectPlane; + +"pInfo" is an array indicating which visuals and depths that double +buffering is supported on. "nInfo" is the length of the array. + +"frameBuffer" is array of length 2. The contents of the array element +is ddx-specific. The content of frameBuffer[0] should, when placed in +the window private, indicate that framebuffer 0 should be drawn into. +The contents of frameBuffer[1], when placed into the window private, +should indicate that framebuffer 1 should be drawn into. + +"selectPlane" is ddx-specific. It should contain information +neccessary for your displayProc to access the select plane. +It is passed to DrawSelectPlaneFunc. + +"CopyBufferBitsFunc" is a ddx-specific function that copies from one +buffer of a multibuffered window to another buffer. If the CopyBufferBitsFunc +is NULL, a default function will be used that calls pScreen->CopyArea. + + void CopyBufferBitsFunc(pMBWindow, srcBufferNum, dstBufferNum) + mbufWindowPtr pMBWindow; + int srcBufferNum, dstBufferNum; + +"DrawSelectPlaneFunc" is a ddx-specific function that fills the +regions "prgn" of select plane with the value "bufferNum". If +selectPlane is a DrawablePtr (such as a PixmapPtr), you can pass +NULL for DrawSelectPlaneFunc, a default function will be used that +calls FillRectangle on the selectPlane. + + void DrawSelectPlaneFunc(pScreen, selectPlane, prgn, bufferNum) + ScreenPtr pScreen; + DevUnion selectPlane; + RegionPtr prgn; + long bufferNum; + +... +... +... + +*/ + +#define MAX_BUFFERS 2 /* Only supports 2 buffers */ +#define FRONT_BUFFER 0 +#define BACK_BUFFER 1 + + +/* Buffer drawables have the same structure as window drawables */ +typedef WindowRec BufferRec; +typedef WindowPtr BufferPtr; + + +/* + * Call RegisterHdwrBuffer for every screen that has doublebuffer hardware. + */ + +static int bufNumInfo[MAXSCREENS]; +static xMbufBufferInfo *bufInfo[MAXSCREENS]; +static DevUnion *bufFrameBuffer[MAXSCREENS]; +static DevUnion bufselectPlane[MAXSCREENS]; +static void (* bufCopyBufferBitsFunc[MAXSCREENS])(); +static void (* bufDrawSelectPlaneFunc[MAXSCREENS])(); + +static Bool bufMultibufferInit(); + + +void +RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane, + CopyBufferBitsFunc, DrawSelectPlaneFunc) + ScreenPtr pScreen; + int nInfo; + xMbufBufferInfo *pInfo; + DevUnion *frameBuffer; + DevUnion selectPlane; + void (* CopyBufferBitsFunc)(); + void (* DrawSelectPlaneFunc)(); +{ + bufNumInfo[pScreen->myNum] = nInfo; + bufInfo[pScreen->myNum] = pInfo; + bufFrameBuffer[pScreen->myNum] = frameBuffer; + bufselectPlane[pScreen->myNum] = selectPlane; + + bufCopyBufferBitsFunc[pScreen->myNum] = CopyBufferBitsFunc; + bufDrawSelectPlaneFunc[pScreen->myNum] = DrawSelectPlaneFunc; + + /* Register ourselves with device-independent multibuffers code */ + RegisterMultibufferInit(pScreen, bufMultibufferInit); +} + + +/* + * Called by Multibuffer extension initialization. + * Initializes mbufScreenRec and its devPrivate. + */ + +static Bool NoopDDA_True() { return TRUE; } +static Bool bufPositionWindow(); +static int bufCreateImageBuffers(); +static void bufDestroyImageBuffers(); +static void bufDisplayImageBuffers(); +static void bufClearImageBufferArea(); +static void bufDestroyBuffer(); +static void bufCopyBufferBits(); +static void bufDrawSelectPlane(); +static void bufWrapScreenFuncs(); +static void bufResetProc(); + +static void bufPostValidateTree(); +static void bufClipNotify(); +static void bufWindowExposures(); +static Bool bufChangeWindowAttributes(); +static void bufClearToBackground(); +static void bufCopyWindow(); + +extern WindowPtr *WindowTable; + +static Bool +bufMultibufferInit(pScreen, pMBScreen) + ScreenPtr pScreen; + mbufScreenPtr pMBScreen; +{ + mbufBufferPrivPtr pMBPriv; + BoxRec box; + + /* Multibuffer info */ + pMBScreen->nInfo = bufNumInfo[pScreen->myNum]; + pMBScreen->pInfo = bufInfo[pScreen->myNum]; + + /* Hooks */ + pMBScreen->CreateImageBuffers = bufCreateImageBuffers; + pMBScreen->DestroyImageBuffers = bufDestroyImageBuffers; + pMBScreen->DisplayImageBuffers = bufDisplayImageBuffers; + pMBScreen->ClearImageBufferArea = bufClearImageBufferArea; + pMBScreen->ChangeMBufferAttributes = NoopDDA_True; + pMBScreen->ChangeBufferAttributes = NoopDDA_True; + pMBScreen->DeleteBufferDrawable = bufDestroyBuffer; + pMBScreen->WrapScreenFuncs = bufWrapScreenFuncs; + pMBScreen->ResetProc = bufResetProc; + /* Create devPrivate part */ + pMBPriv = (mbufBufferPrivPtr) xalloc(sizeof *pMBPriv); + if (!pMBPriv) + return (FALSE); + + pMBScreen->devPrivate.ptr = (pointer) pMBPriv; + pMBPriv->frameBuffer = bufFrameBuffer[pScreen->myNum]; + pMBPriv->selectPlane = bufselectPlane[pScreen->myNum]; + + /* + * Initializing the subtractRgn to the screen area will ensure that + * the selectPlane will get cleared on the first PostValidateTree. + */ + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + + pMBPriv->rgnChanged = TRUE; + REGION_INIT(pScreen, &pMBPriv->backBuffer, &box, 1); + REGION_INIT(pScreen, &pMBPriv->subtractRgn, &box, 1); + REGION_INIT(pScreen, &pMBPriv->unionRgn, NullBox, 0); + + /* Misc functions */ + pMBPriv->CopyBufferBits = bufCopyBufferBitsFunc[pScreen->myNum]; + pMBPriv->DrawSelectPlane = bufDrawSelectPlaneFunc[pScreen->myNum]; + + if (!pMBPriv->CopyBufferBits) + pMBPriv->CopyBufferBits = bufCopyBufferBits; + + if (!pMBPriv->DrawSelectPlane) + pMBPriv->DrawSelectPlane = bufDrawSelectPlane; + + /* screen functions */ + pMBPriv->funcsWrapped = 0; + pMBPriv->inClearToBackground = FALSE; + pMBPriv->WindowExposures = NULL; + pMBPriv->CopyWindow = NULL; + pMBPriv->ClearToBackground = NULL; + pMBPriv->ClipNotify = NULL; + pMBPriv->ChangeWindowAttributes = NULL; + + /* Start out wrapped to clear select plane */ + WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree); + return TRUE; +} + +static void +UpdateBufferFromWindow(pBuffer, pWin) + BufferPtr pBuffer; + WindowPtr pWin; +{ + pBuffer->drawable.x = pWin->drawable.x; + pBuffer->drawable.y = pWin->drawable.y; + pBuffer->drawable.width = pWin->drawable.width; + pBuffer->drawable.height = pWin->drawable.height; + + pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + /* Update for PaintWindowBackground */ + pBuffer->parent = pWin->parent; + + /* + * Make the borderClip the same as the clipList so + * NotClippedByChildren comes out with just clipList. + */ + + pBuffer->clipList = pWin->clipList; + pBuffer->borderClip = pWin->clipList; + pBuffer->winSize = pWin->winSize; + pBuffer->borderSize = pWin->borderSize; + + pBuffer->origin = pWin->origin; +} + +static BufferPtr +bufCreateBuffer(pScreen, pWin, bufferNum) + ScreenPtr pScreen; + WindowPtr pWin; + int bufferNum; +{ + mbufBufferPrivPtr pMBPriv; + DevUnion *devPrivates; + BufferPtr pBuffer; + int i; + + pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + pBuffer = AllocateWindow(pWin->drawable.pScreen); + if (!pBuffer) + return (NULL); + + /* XXX- Until we know what is needed, copy everything. */ + devPrivates = pBuffer->devPrivates; + *pBuffer = *pWin; + pBuffer->devPrivates = devPrivates; + + pBuffer->drawable.type = DRAWABLE_BUFFER; + pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pBuffer->nextSib = NULL; + pBuffer->prevSib = NULL; + pBuffer->firstChild = NULL; + pBuffer->lastChild = NULL; + + /* XXX - Worry about backingstore later */ + pBuffer->backStorage = NULL; + pBuffer->backingStore = NotUseful; + + /* XXX - Need to call pScreen->CreateWindow for tile/stipples + * or should I just copy the devPrivates? + */ + + for (i=0; i < pScreen->WindowPrivateLen; i++) + pBuffer->devPrivates[i] = pWin->devPrivates[i]; + + pBuffer->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[bufferNum]; + + return pBuffer; +} + +static void +bufDestroyBuffer(pDrawable) + DrawablePtr pDrawable; +{ + xfree(pDrawable); +} + +/*ARGSUSED*/ +static int +bufCreateImageBuffers (pWin, nbuf, ids, action, hint) + WindowPtr pWin; + int nbuf; + XID *ids; + int action; + int hint; +{ + ScreenPtr pScreen; + mbufScreenPtr pMBScreen; + mbufWindowPtr pMBWindow; + mbufBufferPtr pMBBuffer; + int i; + + pScreen = pWin->drawable.pScreen; + pMBScreen = MB_SCREEN_PRIV(pScreen); + pMBWindow = MB_WINDOW_PRIV(pWin); + + pMBWindow->devPrivate.ptr = (pointer) REGION_CREATE(pScreen, 0,0); + if (!pMBWindow->devPrivate.ptr) + return(0); + REGION_COPY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr, + &pWin->clipList); + + for (i = 0; i < nbuf; i++) + { + pMBBuffer = pMBWindow->buffers + i; + pMBBuffer->pDrawable = (DrawablePtr) bufCreateBuffer(pScreen,pWin,i); + + if (!pMBBuffer->pDrawable) + break; + + if (!AddResource (ids[i], MultibufferDrawableResType, + (pointer) pMBBuffer->pDrawable)) + { + bufDestroyBuffer((BufferPtr) pMBBuffer->pDrawable); + break; + } + pMBBuffer->pDrawable->id = ids[i]; + + /* + * If window is already mapped, generate exposures and + * clear the area of the newly buffers. + */ + + if ((pWin->realized) && (i != pMBWindow->displayedMultibuffer)) + (* pMBScreen->ClearImageBufferArea)(pMBBuffer, 0,0, 0,0, TRUE); + } + + return i; +} + +static void +bufDestroyImageBuffers(pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen; + mbufWindowPtr pMBWindow; + + pScreen = pWin->drawable.pScreen; + + if (pMBWindow = MB_WINDOW_PRIV(pWin)) + { + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + /* + * if the backbuffer is currently being displayed, move the bits + * to the frontbuffer and display it instead. + */ + + if (pWin->realized && (pMBWindow->displayedMultibuffer == BACK_BUFFER)) + { + (* pMBPriv->CopyBufferBits)(pMBWindow, BACK_BUFFER, FRONT_BUFFER); + REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, + &pMBPriv->backBuffer, &pWin->clipList); + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &pWin->clipList, FRONT_BUFFER); + } + + /* Switch window rendering to front buffer */ + pWin->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[FRONT_BUFFER]; + + REGION_DESTROY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr); + pMBWindow->devPrivate.ptr = NULL; + } +} + +/* + * Can be replaced by pScreen->ClearToBackground if pBuffer->eventMask + * and wOtherEventsMasks(pBuffer) were setup. + */ + +static void +bufClearImageBufferArea(pMBBuffer, x,y, w,h, generateExposures) + mbufBufferPtr pMBBuffer; + short x,y; + unsigned short w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + BufferPtr pBuffer; + + pBuffer = (BufferPtr) pMBBuffer->pDrawable; + /* compute everything using ints to avoid overflow */ + + x1 = pBuffer->drawable.x + x; + y1 = pBuffer->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pBuffer->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pBuffer->drawable.height - (int) y; + + extents = &pBuffer->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pBuffer->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pBuffer->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pBuffer, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pBuffer->clipList); + if (pBuffer->backgroundState != None) + (*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND); + if (generateExposures) + MultibufferExpose(pMBBuffer, ®); +#ifdef _notdef + /* XXBS - This is the original miClearToBackground code. + * WindowExposures needs to be called (or the functionality emulated) + * in order for backingStore to work, but first, pBuffer->eventMask + * and wOtherEventsMasks(pBuffer) need to be setup correctly. + */ + + if (generateExposures) + (*pScreen->WindowExposures)(pBuffer, ®, pBSReg); + else if (pBuffer->backgroundState != None) + (*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND); +#endif + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +static void +bufWrapScreenFuncs(pScreen) + ScreenPtr pScreen; +{ + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClipNotify, bufClipNotify); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,WindowExposures,bufWindowExposures); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,ChangeWindowAttributes, bufChangeWindowAttributes); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClearToBackground,bufClearToBackground); + WRAP_SCREEN_FUNC(pScreen,pMBPriv,CopyWindow,bufCopyWindow); +} + +static void +bufResetProc(pScreen) + ScreenPtr pScreen; +{ + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + /* + * frameBuffer, selectPlane, and pInfo should be freed by + * whoever called RegisterDoubleBufferHardware + */ + + REGION_UNINIT(pScreen, &pMBPriv->backBuffer); + REGION_UNINIT(pScreen, &pMBPriv->subtractRgn); + REGION_UNINIT(pScreen, &pMBPriv->unionRgn); + xfree(pMBPriv); +} + +/*---------------------------------------------------------------------------*/ + +/* + * Used if CopyBufferBitsFunc is not provided when registering. + * This should work for everybody since CopyArea needs to support + * copying between buffers anyway. + */ + +static void +bufCopyBufferBits(pMBWindow, srcBufferNum, dstBufferNum) + mbufWindowPtr pMBWindow; + int srcBufferNum, dstBufferNum; +{ + DrawablePtr pSrcBuffer, pDstBuffer; + GCPtr pGC; + + pSrcBuffer = pMBWindow->buffers[srcBufferNum].pDrawable; + pDstBuffer = pMBWindow->buffers[dstBufferNum].pDrawable; + + pGC = GetScratchGC (pDstBuffer->depth, pDstBuffer->pScreen); + if (!pGC) + return; + + ValidateGC (pDstBuffer, pGC); + (* pGC->ops->CopyArea) (pSrcBuffer, pDstBuffer, pGC, + 0,0, pDstBuffer->width, pDstBuffer->height, 0,0); + FreeScratchGC (pGC); +} + +/* + * Used if DrawSelectPlanFunc is not provided for when registering. + * However, it only works if selectPlane.ptr is a drawable. Also + * assumes that painting with color 0 selects the front buffer, + * while color 1 selects the back buffer. + */ + +static void +bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum) + ScreenPtr pScreen; + DevUnion selectPlane; + RegionPtr prgn; + long bufferNum; +{ + DrawablePtr pDrawable; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register xRectangle *prect; + int numRects; + XID value; + + if (REGION_NUM_RECTS(prgn) == 0) + return; + + pDrawable = (DrawablePtr) selectPlane.ptr; + pGC = GetScratchGC (pDrawable->depth, pScreen); + if (!pGC) + return; + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + { + FreeScratchGC(pGC); + return; + } + + value = (XID) bufferNum; + DoChangeGC(pGC, GCForeground, &value, 0); + ValidateGC(pDrawable, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1; + prect->y = pbox->y1; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (* pGC->ops->PolyFillRect)(pDrawable, pGC, numRects, prect); + + DEALLOCATE_LOCAL(prect); + FreeScratchGC (pGC); +} + + +static void +bufDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf) + ScreenPtr pScreen; + mbufBufferPtr *ppMBBuffer; + mbufWindowPtr *ppMBWindow; + int nbuf; +{ + WindowPtr pWin; + BufferPtr pPrevBuffer, pNewBuffer; + int i, number; + mbufBufferPrivPtr pMBPriv; + mbufBufferPtr pPrevMBBuffer; + + pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + for (i = 0; i < nbuf; i++) + { + number = ppMBBuffer[i]->number; /* 0=frontbuffer, 1=backbuffer */ + pWin = ppMBWindow[i]->pWindow; + pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]); + + pPrevBuffer = (BufferPtr) pPrevMBBuffer->pDrawable; + pNewBuffer = (BufferPtr) ppMBBuffer[i]->pDrawable; + + if (pPrevBuffer != pNewBuffer) + { + RegionPtr backBuffer = &pMBPriv->backBuffer; + + /* + * Update the select plane and the backBuffer region. + */ + + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &pWin->clipList, number); + + if (number == BACK_BUFFER) + REGION_UNION(pScreen, backBuffer, backBuffer, + &pWin->clipList); + else + REGION_SUBTRACT(pScreen, backBuffer, backBuffer, + &pWin->clipList); + + /* Switch which framebuffer the window draws into */ + pWin->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[number]; + } + + switch (ppMBWindow[i]->updateAction) + { + case MultibufferUpdateActionUndefined: + break; + case MultibufferUpdateActionBackground: + (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea) + (pPrevMBBuffer, 0,0, 0,0, FALSE); + break; + case MultibufferUpdateActionUntouched: + break; + case MultibufferUpdateActionCopied: + if (pPrevBuffer != pNewBuffer) + { + (* pMBPriv->CopyBufferBits) (ppMBWindow[i], + ppMBBuffer[i]->number, pPrevMBBuffer->number); + } + break; + } + } +} + +/* Updates the backBuffer region and paints the selectPlane. */ + +static void +bufPostValidateTree(pParent, pChild, kind) + WindowPtr pParent, pChild; + VTKind kind; +{ + ScreenPtr pScreen; + mbufBufferPrivPtr pMBPriv; + + if (pParent) + pScreen = pParent->drawable.pScreen; + else if (pChild) + pScreen = pChild->drawable.pScreen; + else + return; /* Hopeless */ + + pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree); + if (pScreen->PostValidateTree) + (* pScreen->PostValidateTree)(pParent, pChild, kind); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree); + + /* Does backBuffer need to change? */ + if (pMBPriv->rgnChanged) + { + RegionRec exposed; + RegionPtr pSubtractRgn, pUnionRgn; + Bool overlap; + + pMBPriv->rgnChanged = FALSE; + + pSubtractRgn = &pMBPriv->subtractRgn; + pUnionRgn = &pMBPriv->unionRgn; + REGION_VALIDATE(pScreen, pSubtractRgn, &overlap); +#ifdef DEBUG + if (overlap) + FatalError("bufPostValidateTree: subtractRgn overlaps"); +#endif + REGION_VALIDATE(pScreen, pUnionRgn, &overlap); +#ifdef DEBUG + if (overlap) + FatalError("bufPostValidateTree: unionRgn overlaps"); +#endif + + /* Update backBuffer: subtract must come before union */ + REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer, + pSubtractRgn); + REGION_UNION(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer, + pUnionRgn); + + /* Paint gained and lost backbuffer areas in select plane */ + REGION_INIT(pScreen, &exposed, NullBox, 0); + REGION_SUBTRACT(pScreen, &exposed, pSubtractRgn, pUnionRgn); + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &exposed, FRONT_BUFFER); + + REGION_SUBTRACT(pScreen, &exposed, pUnionRgn, pSubtractRgn); + (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane, + &exposed, BACK_BUFFER); + + REGION_UNINIT(pScreen, &exposed); + REGION_EMPTY(pScreen, pSubtractRgn); + REGION_EMPTY(pScreen, pUnionRgn); + } +} + +/* XXX - Knows region internals. */ + +static Bool +RegionsEqual(reg1, reg2) + RegionPtr reg1; + RegionPtr reg2; +{ + int i; + BoxPtr rects1, rects2; + + if (reg1->extents.x1 != reg2->extents.x1) return FALSE; + if (reg1->extents.x2 != reg2->extents.x2) return FALSE; + if (reg1->extents.y1 != reg2->extents.y1) return FALSE; + if (reg1->extents.y2 != reg2->extents.y2) return FALSE; + if (REGION_NUM_RECTS(reg1) != REGION_NUM_RECTS(reg2)) return FALSE; + + rects1 = REGION_RECTS(reg1); + rects2 = REGION_RECTS(reg2); + for (i = 0; i != REGION_NUM_RECTS(reg1); i++) { + if (rects1[i].x1 != rects2[i].x1) return FALSE; + if (rects1[i].x2 != rects2[i].x2) return FALSE; + if (rects1[i].y1 != rects2[i].y1) return FALSE; + if (rects1[i].y2 != rects2[i].y2) return FALSE; + } + return TRUE; +} + +/* + * If the window is multibuffered and displaying the backbuffer, + * add the old clipList to the subtractRgn and add the new clipList + * to the unionRgn. PostValidateTree will use subtractRgn and unionRgn + * to update the backBuffer region and the selectPlane. + * + * Copy changes to the window structure into the buffers. + * Send ClobberNotify events. + */ + +static void +bufClipNotify(pWin, dx,dy) + WindowPtr pWin; + int dx,dy; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + mbufWindowPtr pMBWindow; + int i; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify); + if (pScreen->ClipNotify) + (* pScreen->ClipNotify)(pWin, dx,dy); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify); + + if (pMBWindow = MB_WINDOW_PRIV(pWin)) + { + RegionPtr pOldClipList = (RegionPtr) pMBWindow->devPrivate.ptr; + + if (! RegionsEqual(pOldClipList, &pWin->clipList)) + { + if (pMBWindow->displayedMultibuffer == BACK_BUFFER) + { + pMBPriv->rgnChanged = TRUE; + REGION_APPEND(pScreen, &pMBPriv->subtractRgn, pOldClipList); + REGION_APPEND(pScreen, &pMBPriv->unionRgn, &pWin->clipList); + } + + REGION_COPY(pScreen, pOldClipList,&pWin->clipList); + } + + /* Update buffer x,y,w,h, and clipList */ + for (i=0; i<pMBWindow->numMultibuffer; i++) + { + mbufBufferPtr pMBBuffer = pMBWindow->buffers + i; + if (pMBBuffer->clobber != pWin->visibility) + { + pMBBuffer->clobber = pWin->visibility; + MultibufferClobber(pMBBuffer); + } + UpdateBufferFromWindow(pMBBuffer->pDrawable, pWin); + } + } +} + +/* + * Updates buffer's background fields when the window's changes. + * This is necessary because pScreen->PaintWindowBackground + * is used to paint the buffer. + * + * XXBS - Backingstore state will have be tracked too if it is supported. + */ + +static Bool +bufChangeWindowAttributes(pWin, mask) + WindowPtr pWin; + unsigned long mask; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + mbufWindowPtr pMBWindow; + Bool ret; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes); + ret = (* pScreen->ChangeWindowAttributes)(pWin, mask); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes); + + if (pMBWindow = MB_WINDOW_PRIV(pWin)) + { + if (mask & (CWBackPixmap | CWBackPixel)) + { + BufferPtr pBuffer; + int i; + + for (i=0; i<pMBWindow->displayedMultibuffer; i++) + { + pBuffer = (BufferPtr) pMBWindow->buffers[i].pDrawable; + pBuffer->backgroundState = pWin->backgroundState; + pBuffer->background = pWin->background; + } + } + } + return ret; +} + +/* + * Send exposures and clear the background for a buffer whenever + * its corresponding window is exposed, except when called by + * ClearToBackground. + */ + +static void +bufWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin); + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + RegionRec tmp_rgn; + int i; + Bool handleBuffers; + + handleBuffers = (!pMBPriv->inClearToBackground) && + (pWin->drawable.type == DRAWABLE_WINDOW) && + pMBWindow && (prgn && !REGION_NIL(prgn)); + + /* miWindowExposures munges prgn and other_exposed. */ + if (handleBuffers) + { + REGION_INIT(pScreen, &tmp_rgn, NullBox, 0); + REGION_COPY(pScreen, &tmp_rgn,prgn); + } + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures); + (* pScreen->WindowExposures) (pWin, prgn, other_exposed); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures); + + if (!handleBuffers) + return; + + /* + * Send expose events to all clients. Paint the exposed region for all + * buffers except the displayed buffer since it is handled when the + * window is painted. + * + * XXBS - Will have to be re-written to handle BackingStore on buffers. + */ + + for (i=0; i<pMBWindow->numMultibuffer; i++) + { + mbufBufferPtr pMBBuffer; + BufferPtr pBuffer; + + pMBBuffer = pMBWindow->buffers + i; + pBuffer = (BufferPtr) pMBBuffer->pDrawable; + + if (i != pMBWindow->displayedMultibuffer) + (* pScreen->PaintWindowBackground)(pBuffer,&tmp_rgn,PW_BACKGROUND); + if ((pMBBuffer->otherEventMask | pMBBuffer->eventMask) & ExposureMask) + MultibufferExpose(pMBBuffer, &tmp_rgn); + } + + REGION_UNINIT(pScreen, &tmp_rgn); +} + +/* + * Set ``inClearToBackground'' so that WindowExposures does not attempt + * to send expose events or clear the background on the buffers. + */ + +static void +bufClearToBackground(pWin, x,y,w,h, sendExpose) + WindowPtr pWin; + int x,y, w,h; + Bool sendExpose; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + + pMBPriv->inClearToBackground = TRUE; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground); + (* pScreen->ClearToBackground)(pWin, x,y,w,h, sendExpose); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground); + + pMBPriv->inClearToBackground = FALSE; +} + +/* + * Move bits in both buffers. It does this by calling pScreen->CopyWindow + * twice, once with the root window's devPrivate[frameWindowPrivateIndex] + * pointing to the frontbuffer pixmap and once with it pointed to the + * backbuffer pixmap. It does this if there are *any* existing multibuffered + * window... a possible optimization is to copy the backbuffer only if this + * window or its inferiors are multibuffered. May be faster, maybe not. + * + * XXX - Only works if your CopyWindow checks the root window's devPrivate + * to see which buffer to draw into. Works for cfbPaintWindow. + */ + +/*ARGSUSED*/ +static void +bufCopyWindow(pWin, ptOldOrg, prgnSrc) + WindowPtr pWin; + DDXPointRec ptOldOrg; + RegionPtr prgnSrc; +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen); + WindowPtr pwinroot; + DevUnion save; + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow); + + pwinroot = WindowTable[pScreen->myNum]; + save = pwinroot->devPrivates[frameWindowPrivateIndex]; + + /* + * Copy front buffer + */ + + pwinroot->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[FRONT_BUFFER]; + (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* + * Copy back buffer + */ + + /* CopyWindow translates prgnSrc... translate it back for 2nd call. */ + REGION_TRANSLATE(pScreen, prgnSrc, + ptOldOrg.x - pWin->drawable.x, + ptOldOrg.y - pWin->drawable.y); + pwinroot->devPrivates[frameWindowPrivateIndex] = + pMBPriv->frameBuffer[BACK_BUFFER]; + (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + pwinroot->devPrivates[frameWindowPrivateIndex] = save; + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow); +} diff --git a/Xext/mbufpx.c b/Xext/mbufpx.c new file mode 100644 index 000000000..9474cc9aa --- /dev/null +++ b/Xext/mbufpx.c @@ -0,0 +1,646 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: mbufpx.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +#define NEED_REPLIES +#define NEED_EVENTS +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" +#include <sys/time.h> + +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#define _MULTIBUF_PIXMAP_ +#include "multibufst.h" + + +static Bool NoopDDA_True() { return TRUE; } + +static Bool pixPositionWindow(); +static int pixCreateImageBuffers(); +static void pixDisplayImageBuffers(); +static void pixClearImageBufferArea(); +static void pixDeleteBufferDrawable(); +static void pixWrapScreenFuncs(); +static void pixResetProc(); + +Bool +pixMultibufferInit(pScreen, pMBScreen) + ScreenPtr pScreen; + mbufScreenPtr pMBScreen; +{ + int i, j, k; + xMbufBufferInfo *pInfo; + int nInfo; + DepthPtr pDepth; + mbufPixmapPrivPtr pMBPriv; + + pMBScreen->CreateImageBuffers = pixCreateImageBuffers; + pMBScreen->DestroyImageBuffers = (void (*)())NoopDDA; + pMBScreen->DisplayImageBuffers = pixDisplayImageBuffers; + pMBScreen->ClearImageBufferArea = pixClearImageBufferArea; + pMBScreen->ChangeMBufferAttributes = NoopDDA_True; + pMBScreen->ChangeBufferAttributes = NoopDDA_True; + pMBScreen->DeleteBufferDrawable = pixDeleteBufferDrawable; + pMBScreen->WrapScreenFuncs = pixWrapScreenFuncs; + pMBScreen->ResetProc = pixResetProc; + + /* Support every depth and visual combination that the screen does */ + + nInfo = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + nInfo += pDepth->numVids; + } + + pInfo = (xMbufBufferInfo *) xalloc (nInfo * sizeof (xMbufBufferInfo)); + if (!pInfo) + return FALSE; + + k = 0; + for (i = 0; i < pScreen->numDepths; i++) + { + pDepth = &pScreen->allowedDepths[i]; + for (j = 0; j < pDepth->numVids; j++) + { + pInfo[k].visualID = pDepth->vids[j]; + pInfo[k].maxBuffers = 0; + pInfo[k].depth = pDepth->depth; + k++; + } + } + + pMBScreen->nInfo = nInfo; + pMBScreen->pInfo = pInfo; + + /* + * Setup the devPrivate to mbufScreenRec + */ + + pMBPriv = (mbufPixmapPrivPtr) xalloc(sizeof(* pMBPriv)); + if (!pMBPriv) + { + xfree(pInfo); + return (FALSE); + } + pMBScreen->devPrivate.ptr = (pointer) pMBPriv; + pMBPriv->PositionWindow = NULL; + pMBPriv->funcsWrapped = 0; + + return TRUE; +} + +/*ARGSUSED*/ +static int +pixCreateImageBuffers (pWin, nbuf, ids, action, hint) + WindowPtr pWin; + int nbuf; + XID *ids; + int action; + int hint; +{ + mbufWindowPtr pMBWindow; + mbufBufferPtr pMBBuffer; + ScreenPtr pScreen; + int width, height, depth; + int i; + + pMBWindow = MB_WINDOW_PRIV(pWin); + + width = pWin->drawable.width; + height = pWin->drawable.height; + depth = pWin->drawable.depth; + pScreen = pWin->drawable.pScreen; + + for (i = 0; i < nbuf; i++) + { + pMBBuffer = &pMBWindow->buffers[i]; + pMBBuffer->pDrawable = (DrawablePtr) + (*pScreen->CreatePixmap) (pScreen, width, height, depth); + if (!pMBBuffer->pDrawable) + break; + + if (!AddResource (ids[i], MultibufferDrawableResType, + (pointer) pMBBuffer->pDrawable)) + { + (*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable); + break; + } + pMBBuffer->pDrawable->id = ids[i]; + + /* + * In the description of the CreateImageBuffers request: + * "If the window is mapped, or if these image buffers have + * backing store, their contents will be tiled with the window + * background, and zero or more expose events will be generated + * for each of these buffers." + */ + + (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea) + (pMBBuffer, 0,0, 0,0, TRUE); + } + + return i; +} + +/* + * set up the gc to clear the pixmaps; + */ +static Bool +SetupBackgroundPainter (pWin, pGC) + WindowPtr pWin; + GCPtr pGC; +{ + XID gcvalues[4]; + int ts_x_origin, ts_y_origin; + PixUnion background; + int backgroundState; + Mask gcmask; + + /* + * First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + + ts_x_origin = ts_y_origin = 0; + while (pWin->backgroundState == ParentRelative) { + ts_x_origin -= pWin->origin.x; + ts_y_origin -= pWin->origin.y; + pWin = pWin->parent; + } + backgroundState = pWin->backgroundState; + background = pWin->background; + + switch (backgroundState) + { + case BackgroundPixel: + gcvalues[0] = (XID) background.pixel; + gcvalues[1] = FillSolid; + gcmask = GCForeground|GCFillStyle; + break; + + case BackgroundPixmap: + gcvalues[0] = FillTiled; + gcvalues[1] = (XID) background.pixmap; + gcvalues[2] = ts_x_origin; + gcvalues[3] = ts_y_origin; + gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; + break; + + default: + return FALSE; + } + DoChangeGC(pGC, gcmask, gcvalues, TRUE); + return TRUE; +} + +static void +MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects) + WindowPtr pWin; + DrawablePtr pDrawable; + int nrects; + xRectangle *pRects; +{ + GCPtr pGC; + + pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen); + if (SetupBackgroundPainter(pWin, pGC)) + { + ValidateGC(pDrawable, pGC); + (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, pRects); + } + FreeScratchGC(pGC); +} + +static void +MultibufferPaintBackgroundRegion(pWin, pDrawable, pRegion) + WindowPtr pWin; + DrawablePtr pDrawable; + RegionPtr pRegion; +{ + xRectangle *pRects; + int nrects = REGION_NUM_RECTS(pRegion); + BoxPtr pbox = REGION_RECTS(pRegion); + + pRects = (xRectangle *)ALLOCATE_LOCAL(nrects * sizeof(xRectangle)); + if (pRects) + { + int i; + for (i = 0; i < nrects; i++) + { + pRects[i].x = pbox->x1; + pRects[i].y = pbox->y1; + pRects[i].width = pbox->x2 - pbox->x1; + pRects[i].height = pbox->y2 - pbox->y1; + } + MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects); + DEALLOCATE_LOCAL(pRects); + } +} + +static void +pixDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf) + mbufBufferPtr *ppMBBuffer; + mbufWindowPtr *ppMBWindow; + int nbuf; +{ + GCPtr pGC = NULL; + PixmapPtr pPrevPixmap, pNewPixmap; + WindowPtr pWin; + RegionPtr pExposed; + int i; + mbufBufferPtr pPrevMBBuffer; + XID bool; + xRectangle r; + + UpdateCurrentTime (); + for (i = 0; i < nbuf; i++) + { + pWin = ppMBWindow[i]->pWindow; + + /* Time to get a different scratch GC? */ + + if (!pGC + || pGC->depth != pWin->drawable.depth + || pGC->pScreen != pWin->drawable.pScreen) + { + if (pGC) FreeScratchGC(pGC); + pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen); + } + pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]); + pPrevPixmap = (PixmapPtr) pPrevMBBuffer->pDrawable; + pNewPixmap = (PixmapPtr) ppMBBuffer[i]->pDrawable; + + if (pPrevPixmap == pNewPixmap) + { + /* "If a specified buffer is already displayed, any delays and + * update action will still be performed for that buffer." + * + * We special-case this because applications do occasionally + * request a redundant DisplayImageBuffers, and we can save + * strokes by recognizing that the only update action that will + * change the buffer contents in this case is Background. + */ + if (ppMBWindow[i]->updateAction == MultibufferUpdateActionBackground) + { + r.x = r.y = 0; + r.width = pWin->drawable.width; + r.height = pWin->drawable.height; + MultibufferPaintBackgroundRectangles(pWin, (DrawablePtr)pWin, + 1, &r); + } + } + else /* different buffer is being displayed */ + { + /* perform update action */ + + switch (ppMBWindow[i]->updateAction) + { + case MultibufferUpdateActionUndefined: + break; + + case MultibufferUpdateActionBackground: + + r.x = r.y = 0; + r.width = pPrevPixmap->drawable.width; + r.height = pPrevPixmap->drawable.height; + MultibufferPaintBackgroundRectangles(pWin, + (DrawablePtr)pPrevPixmap, + 1, &r); + break; + + case MultibufferUpdateActionUntouched: + + /* copy the window to the pixmap that represents the + * currently displayed buffer + */ + + if (pPrevMBBuffer->eventMask & ExposureMask) + { + bool = TRUE; + DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE); + } + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + pExposed = (*pGC->ops->CopyArea)((DrawablePtr) pWin, + (DrawablePtr) pPrevPixmap, + pGC, + 0, 0, + pWin->drawable.width, + pWin->drawable.height, + 0, 0); + + /* if we couldn't copy the whole window to the buffer, + * send expose events (if any client wants them) + */ + + if (pPrevMBBuffer->eventMask & ExposureMask) + { /* some client wants expose events */ + if (pExposed) + { + RegionPtr pWinSize; + extern RegionPtr CreateUnclippedWinSize(); + ScreenPtr pScreen = pWin->drawable.pScreen; + pWinSize = CreateUnclippedWinSize (pWin); + /* + * pExposed is window-relative, but at this point + * pWinSize is screen-relative. Make pWinSize be + * window-relative so that region ops involving + * pExposed and pWinSize behave sensibly. + */ + REGION_TRANSLATE(pScreen, pWinSize, + -pWin->drawable.x, + -pWin->drawable.y); + REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize); + REGION_DESTROY(pScreen, pWinSize); + MultibufferExpose (pPrevMBBuffer, pExposed); + REGION_DESTROY(pScreen, pExposed); + } + bool = FALSE; + DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE); + } /* end some client wants expose events */ + + break; /* end case MultibufferUpdateActionUntouched */ + + case MultibufferUpdateActionCopied: + + ValidateGC ((DrawablePtr)pPrevPixmap, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, + (DrawablePtr)pPrevPixmap, pGC, + 0, 0, pWin->drawable.width, + pWin->drawable.height, 0, 0); + break; + + } /* end switch on update action */ + + /* display the new buffer */ + + ValidateGC ((DrawablePtr)pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin, + pGC, 0, 0, + pWin->drawable.width, pWin->drawable.height, + 0, 0); + } + + ppMBWindow[i]->lastUpdate = currentTime; + } + + if (pGC) FreeScratchGC (pGC); + return; +} + +/* + * resize the buffers when the window is resized + */ + +static Bool +pixPositionWindow (pWin, x, y) + WindowPtr pWin; + int x, y; +{ + ScreenPtr pScreen; + mbufPixmapPrivPtr pMBPriv; + mbufWindowPtr pMBWindow; + mbufBufferPtr pMBBuffer; + int width, height; + int i; + int dx, dy, dw, dh; + int sourcex, sourcey; + int destx, desty; + PixmapPtr pPixmap; + GCPtr pGC; + int savewidth, saveheight; + Bool clear; + RegionRec exposedRegion; + Bool ret; + + pScreen = pWin->drawable.pScreen; + pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen); + + UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow); + ret = (* pScreen->PositionWindow) (pWin, x, y); + REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow); + + if (!(pMBWindow = MB_WINDOW_PRIV(pWin))) + return ret; + + /* if new size is same as old, we're done */ + + if (pMBWindow->width == pWin->drawable.width && + pMBWindow->height == pWin->drawable.height) + return ret; + + width = pWin->drawable.width; + height = pWin->drawable.height; + dx = pWin->drawable.x - pMBWindow->x; + dy = pWin->drawable.x - pMBWindow->y; + dw = width - pMBWindow->width; + dh = height - pMBWindow->height; + GravityTranslate (0, 0, -dx, -dy, dw, dh, + pWin->bitGravity, &destx, &desty); + + /* if the window grew, remember to paint the window background, + * and maybe send expose events, for the new areas of the buffers + */ + + clear = pMBWindow->width < width || pMBWindow->height < height || + pWin->bitGravity == ForgetGravity; + + sourcex = 0; + sourcey = 0; + savewidth = pMBWindow->width; + saveheight = pMBWindow->height; + /* clip rectangle to source and destination */ + if (destx < 0) + { + savewidth += destx; + sourcex -= destx; + destx = 0; + } + if (destx + savewidth > width) + savewidth = width - destx; + if (desty < 0) + { + saveheight += desty; + sourcey -= desty; + desty = 0; + } + if (desty + saveheight > height) + saveheight = height - desty; + + pMBWindow->width = width; + pMBWindow->height = height; + pMBWindow->x = pWin->drawable.x; + pMBWindow->y = pWin->drawable.y; + + if (clear) + { + BoxRec box; + + box.x1 = box.y1 = 0; + box.x2 = width; + box.y2 = height; + REGION_INIT(pScreen, &exposedRegion, &box, 1); + if (pWin->bitGravity != ForgetGravity) + { + RegionRec preservedRegion; + box.x1 = destx; + box.y1 = desty; + box.x2 = destx + savewidth; + box.y2 = desty + saveheight; + REGION_INIT(pScreen, &preservedRegion, &box, 1); + REGION_SUBTRACT(pScreen, &exposedRegion, &exposedRegion, &preservedRegion); + REGION_UNINIT(pScreen, &preservedRegion); + } + + } /* end if (clear) */ + + pGC = GetScratchGC (pWin->drawable.depth, pScreen); + + /* create buffers with new window size */ + + for (i = 0; i < pMBWindow->numMultibuffer; i++) + { + pMBBuffer = &pMBWindow->buffers[i]; + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, pWin->drawable.depth); + if (!pPixmap) + { + (* MB_SCREEN_PRIV(pScreen)->DestroyImageBuffers)(pWin); + break; + } + if (clear) + { + MultibufferPaintBackgroundRegion(pWin, (DrawablePtr)pPixmap, &exposedRegion); + MultibufferExpose(pMBBuffer, &exposedRegion); + } + if (pWin->bitGravity != ForgetGravity) + { + ValidateGC ((DrawablePtr)pPixmap, pGC); + (*pGC->ops->CopyArea) (pMBBuffer->pDrawable, (DrawablePtr)pPixmap, + pGC, + sourcex, sourcey, savewidth, saveheight, + destx, desty); + } + pPixmap->drawable.id = pMBBuffer->pDrawable->id; + (*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable); + pMBBuffer->pDrawable = (DrawablePtr) pPixmap; + if (i != pMBWindow->displayedMultibuffer) + { + ChangeResourceValue (pPixmap->drawable.id, + MultibufferDrawableResType, + (pointer) pPixmap); + } + } + FreeScratchGC (pGC); + if (clear) + REGION_UNINIT(pScreen, &exposedRegion); + return TRUE; +} + +static void +pixWrapScreenFuncs(pScreen) + ScreenPtr pScreen; +{ + mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen); + WRAP_SCREEN_FUNC(pScreen, pMBPriv, PositionWindow, pixPositionWindow); +} + +static void +pixResetProc(pScreen) + ScreenPtr pScreen; +{ + mbufScreenPtr pMBScreen = MB_SCREEN_PRIV(pScreen); + mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen); + + xfree(pMBScreen->pInfo); + xfree(pMBPriv); +} + +static void +pixClearImageBufferArea(pMBBuffer, x,y, width,height, exposures) + mbufBufferPtr pMBBuffer; + short x, y; + unsigned short width, height; + Bool exposures; +{ + WindowPtr pWin; + ScreenPtr pScreen; + BoxRec box; + RegionRec region; + int w_width, w_height; + DrawablePtr pDrawable; + + pWin = pMBBuffer->pMBWindow->pWindow; + pScreen = pWin->drawable.pScreen; + + w_width = pWin->drawable.width; + w_height = pWin->drawable.height; + + box.x1 = x; + box.y1 = y; + box.x2 = width ? (box.x1 + width) : w_width; + box.y2 = height ? (box.y1 + height) : w_height; + + if (box.x1 < 0) box.x1 = 0; + if (box.y1 < 0) box.y1 = 0; + if (box.x2 > w_width) box.x2 = w_width; + if (box.y2 > w_height) box.y2 = w_height; + + REGION_INIT(pScreen, ®ion, &box, 1); + + if (pMBBuffer->number == pMBBuffer->pMBWindow->displayedMultibuffer) + pDrawable = (DrawablePtr) pWin; + else + pDrawable = pMBBuffer->pDrawable; + + MultibufferPaintBackgroundRegion(pWin, pDrawable, ®ion); + + if (exposures) + MultibufferExpose(pMBBuffer, ®ion); + + REGION_UNINIT(pScreen, ®ion); +} + +static void +pixDeleteBufferDrawable(pDrawable) + DrawablePtr pDrawable; +{ + (* pDrawable->pScreen->DestroyPixmap)((PixmapPtr) pDrawable); +} diff --git a/Xext/mitmisc.c b/Xext/mitmisc.c new file mode 100644 index 000000000..63e496209 --- /dev/null +++ b/Xext/mitmisc.c @@ -0,0 +1,153 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* RANDOM CRUFT! THIS HAS NO OFFICIAL X CONSORTIUM OR X PROJECT TEAM BLESSING */ + +/* $Xorg: mitmisc.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#define _MITMISC_SERVER_ +#include "mitmiscstr.h" + +extern Bool permitOldBugs; + +static unsigned char MITReqCode; +static int ProcMITDispatch(), SProcMITDispatch(); +static void MITResetProc(); + +void +MITMiscExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + if (extEntry = AddExtension(MITMISCNAME, 0, 0, + ProcMITDispatch, SProcMITDispatch, + MITResetProc, StandardMinorOpcode)) + MITReqCode = (unsigned char)extEntry->base; +} + +/*ARGSUSED*/ +static void +MITResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcMITSetBugMode(client) + register ClientPtr client; +{ + REQUEST(xMITSetBugModeReq); + + REQUEST_SIZE_MATCH(xMITSetBugModeReq); + if ((stuff->onOff != xTrue) && (stuff->onOff != xFalse)) + { + client->errorValue = stuff->onOff; + return BadValue; + } + permitOldBugs = stuff->onOff; + return(client->noClientException); +} + +static int +ProcMITGetBugMode(client) + register ClientPtr client; +{ + REQUEST(xMITGetBugModeReq); + xMITGetBugModeReply rep; + register int n; + + REQUEST_SIZE_MATCH(xMITGetBugModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.onOff = permitOldBugs; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xMITGetBugModeReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcMITDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_MITSetBugMode: + return ProcMITSetBugMode(client); + case X_MITGetBugMode: + return ProcMITGetBugMode(client); + default: + return BadRequest; + } +} + +static int +SProcMITSetBugMode(client) + register ClientPtr client; +{ + register int n; + REQUEST(xMITSetBugModeReq); + + swaps(&stuff->length, n); + return ProcMITSetBugMode(client); +} + +static int +SProcMITGetBugMode(client) + register ClientPtr client; +{ + register int n; + REQUEST(xMITGetBugModeReq); + + swaps(&stuff->length, n); + return ProcMITGetBugMode(client); +} + +static int +SProcMITDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_MITSetBugMode: + return SProcMITSetBugMode(client); + case X_MITGetBugMode: + return SProcMITGetBugMode(client); + default: + return BadRequest; + } +} diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c new file mode 100644 index 000000000..2d3eb7c42 --- /dev/null +++ b/Xext/panoramiX.c @@ -0,0 +1,780 @@ +/* $Xorg: panoramiX.c,v 1.5 2000/08/17 19:47:57 cpqbld Exp $ */ +/***************************************************************** +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. +******************************************************************/ + +#define NEED_REPLIES +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "gc.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "window.h" +#include "windowstr.h" +#include "pixmapstr.h" +#if 0 +#include <sys/workstation.h> +#include <X11/Xserver/ws.h> +#endif +#include "panoramiX.h" +#include "panoramiXproto.h" + +static unsigned char PanoramiXReqCode = 0; +/* + * PanoramiX data declarations + */ + +int PanoramiXPixWidth; +int PanoramiXPixHeight; +int PanoramiXNumScreens; + +PanoramiXData *panoramiXdataPtr; +PanoramiXWindow *PanoramiXWinRoot; +PanoramiXGC *PanoramiXGCRoot; +PanoramiXCmap *PanoramiXCmapRoot; +PanoramiXPmap *PanoramiXPmapRoot; + +PanoramiXEdge panoramiXEdgePtr[MAXSCREENS]; +RegionRec PanoramiXScreenRegion[MAXSCREENS]; +PanoramiXCDT PanoramiXColorDepthTable[MAXSCREENS]; +PanoramiXDepth PanoramiXLargestScreenDepth; + +int (* SavedProcVector[256]) (); +ScreenInfo *GlobalScrInfo; + +static int panoramiXGeneration; +static int ProcPanoramiXDispatch(); +/* + * Function prototypes + */ + +static void locate_neighbors(int); +static void PanoramiXResetProc(ExtensionEntry*); + +/* + * External references for data variables + */ + +extern int SProcPanoramiXDispatch(); +extern Bool noPanoramiXExtension; +extern Bool PanoramiXVisibilityNotifySent; +extern WindowPtr *WindowTable; +#if 0 +extern ScreenArgsRec screenArgs[MAXSCREENS]; +#endif +extern int defaultBackingStore; +extern char *ConnectionInfo; +extern int connBlockScreenStart; +extern int (* ProcVector[256]) (); + +/* + * Server dispatcher function replacements + */ + +int PanoramiXCreateWindow(), PanoramiXChangeWindowAttributes(); +int PanoramiXDestroyWindow(), PanoramiXDestroySubwindows(); +int PanoramiXChangeSaveSet(), PanoramiXReparentWindow(); +int PanoramiXMapWindow(), PanoramiXMapSubwindows(); +int PanoramiXUnmapWindow(), PanoramiXUnmapSubwindows(); +int PanoramiXConfigureWindow(), PanoramiXCirculateWindow(); +int PanoramiXGetGeometry(), PanoramiXChangeProperty(); +int PanoramiXDeleteProperty(), PanoramiXSendEvent(); +int PanoramiXCreatePixmap(), PanoramiXFreePixmap(); +int PanoramiXCreateGC(), PanoramiXChangeGC(); +int PanoramiXCopyGC(); +int PanoramiXSetDashes(), PanoramiXSetClipRectangles(); +int PanoramiXFreeGC(), PanoramiXClearToBackground(); +int PanoramiXCopyArea(), PanoramiXCopyPlane(); +int PanoramiXPolyPoint(), PanoramiXPolyLine(); +int PanoramiXPolySegment(), PanoramiXPolyRectangle(); +int PanoramiXPolyArc(), PanoramiXFillPoly(); +int PanoramiXPolyFillArc(), PanoramiXPolyFillRectangle(); +int PanoramiXPutImage(), PanoramiXGetImage(); +int PanoramiXPolyText8(), PanoramiXPolyText16(); +int PanoramiXImageText8(), PanoramiXImageText16(); +int PanoramiXCreateColormap(), PanoramiXFreeColormap(); +int PanoramiXInstallColormap(), PanoramiXUninstallColormap(); +int PanoramiXAllocColor(), PanoramiXAllocNamedColor(); +int PanoramiXAllocColorCells(); +int PanoramiXFreeColors(), PanoramiXStoreColors(); + +/* + * PanoramiXExtensionInit(): + * Called from InitExtensions in main(). + * Register PanoramiXeen Extension + * Initialize global variables. + */ + +void PanoramiXExtensionInit(int argc, char *argv[]) +{ + int i, j, PhyScrNum, ArgScrNum; + Bool success = FALSE; + ExtensionEntry *extEntry, *AddExtension(); + PanoramiXData *panoramiXtempPtr; + ScreenPtr pScreen; + + if (!noPanoramiXExtension) + { + GlobalScrInfo = &screenInfo; /* For debug visibility */ + PanoramiXNumScreens = screenInfo.numScreens; + if (PanoramiXNumScreens == 1) { /* Only 1 screen */ + noPanoramiXExtension = TRUE; + return; + } + + while (panoramiXGeneration != serverGeneration) { + extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, + ProcPanoramiXDispatch, + SProcPanoramiXDispatch, PanoramiXResetProc, + StandardMinorOpcode); + if (!extEntry) { + ErrorF("PanoramiXExtensionInit(): failed to AddExtension\n"); + break; + } + PanoramiXReqCode = (unsigned char)extEntry->base; + + /* + * First make sure all the basic allocations succeed. If not, + * run in non-PanoramiXeen mode. + */ + + panoramiXdataPtr = (PanoramiXData *) Xcalloc(PanoramiXNumScreens * sizeof(PanoramiXData)); + PanoramiXWinRoot = (PanoramiXWindow *) Xcalloc(sizeof(PanoramiXWindow)); + PanoramiXGCRoot = (PanoramiXGC *) Xcalloc(sizeof(PanoramiXGC)); + PanoramiXCmapRoot = (PanoramiXCmap *) Xcalloc(sizeof(PanoramiXCmap)); + PanoramiXPmapRoot = (PanoramiXPmap *) Xcalloc(sizeof(PanoramiXPmap)); + BREAK_IF(!(panoramiXdataPtr && PanoramiXWinRoot && PanoramiXGCRoot && + PanoramiXCmapRoot && PanoramiXPmapRoot)); + + panoramiXGeneration = serverGeneration; + success = TRUE; + } + + if (!success) { + noPanoramiXExtension = TRUE; + ErrorF("%s Extension failed to initialize\n", PANORAMIX_PROTOCOL_NAME); + return; + } + + /* Set up a default configuration base on horizontal ordering */ + for (i = PanoramiXNumScreens -1; i >= 0 ; i--) { + panoramiXdataPtr[i].above = panoramiXdataPtr[i].below = -1; + panoramiXdataPtr[i].left = panoramiXdataPtr[i].right = -1; + panoramiXEdgePtr[i].no_edges = TRUE; + } + for (i = PanoramiXNumScreens - 1; i >= 0; i--) { + panoramiXdataPtr[i].left = i - 1; + panoramiXdataPtr[i].right = i + 1; + } + panoramiXdataPtr[PanoramiXNumScreens - 1].right = -1; + + /* + * Position the screens relative to each other based on + * command line options. + */ + +#if 0 + for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) { + if (wsRemapPhysToLogScreens) + i = wsPhysToLogScreens[PhyScrNum]; + else + i = PhyScrNum; + if (i < 0) + continue; + panoramiXdataPtr[i].width = (screenInfo.screens[i])->width; + panoramiXdataPtr[i].height = (screenInfo.screens[i])->height; + if (screenArgs[i].flags & ARG_EDGE_L) { + ArgScrNum = screenArgs[PhyScrNum].edge_left; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].left = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].right = i; + else { + if ( i >= 1 ) + panoramiXdataPtr[i - 1].right = -1; + } + } + if (screenArgs[i].flags & ARG_EDGE_R) { + ArgScrNum = screenArgs[PhyScrNum].edge_right; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].right = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].left = i; + } + if (screenArgs[i].flags & ARG_EDGE_T) { + ArgScrNum = screenArgs[PhyScrNum].edge_top; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].above = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].below = i; + } + if (screenArgs[i].flags & ARG_EDGE_B) { + ArgScrNum = screenArgs[PhyScrNum].edge_bottom; + if (ArgScrNum < 0) + j = -1; + else { + if (wsRemapPhysToLogScreens) + j = wsPhysToLogScreens[ArgScrNum]; + else + j = ArgScrNum; + } + panoramiXdataPtr[i].below = j; + panoramiXEdgePtr[i].no_edges = FALSE; + if ( j >= 0) + panoramiXdataPtr[j].above = i; + } + } +#else + for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) { + i = PhyScrNum; + if (i < 0) + continue; + panoramiXdataPtr[i].width = (screenInfo.screens[i])->width; + panoramiXdataPtr[i].height = (screenInfo.screens[i])->height; + } +#endif + + /* + * Find the upper-left screen and then locate all the others + */ + panoramiXtempPtr = panoramiXdataPtr; + for (i = PanoramiXNumScreens; i; i--, panoramiXtempPtr++) + if (panoramiXtempPtr->above == -1 && panoramiXtempPtr->left == -1) + break; + locate_neighbors(PanoramiXNumScreens - i); + + /* + * Put our processes into the ProcVector + */ + + for (i = 256; i--; ) + SavedProcVector[i] = ProcVector[i]; + + ProcVector[X_CreateWindow] = PanoramiXCreateWindow; + ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes; + ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow; + ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows; + ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet; + ProcVector[X_ReparentWindow] = PanoramiXReparentWindow; + ProcVector[X_MapWindow] = PanoramiXMapWindow; + ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows; + ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow; + ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows; + ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; + ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; + ProcVector[X_GetGeometry] = PanoramiXGetGeometry; + ProcVector[X_ChangeProperty] = PanoramiXChangeProperty; + ProcVector[X_DeleteProperty] = PanoramiXDeleteProperty; + ProcVector[X_SendEvent] = PanoramiXSendEvent; + ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; + ProcVector[X_FreePixmap] = PanoramiXFreePixmap; + ProcVector[X_CreateGC] = PanoramiXCreateGC; + ProcVector[X_ChangeGC] = PanoramiXChangeGC; + ProcVector[X_CopyGC] = PanoramiXCopyGC; + ProcVector[X_SetDashes] = PanoramiXSetDashes; + ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles; + ProcVector[X_FreeGC] = PanoramiXFreeGC; + ProcVector[X_ClearArea] = PanoramiXClearToBackground; + ProcVector[X_CopyArea] = PanoramiXCopyArea;; + ProcVector[X_CopyPlane] = PanoramiXCopyPlane;; + ProcVector[X_PolyPoint] = PanoramiXPolyPoint; + ProcVector[X_PolyLine] = PanoramiXPolyLine; + ProcVector[X_PolySegment] = PanoramiXPolySegment; + ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle; + ProcVector[X_PolyArc] = PanoramiXPolyArc; + ProcVector[X_FillPoly] = PanoramiXFillPoly; + ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle; + ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc; + ProcVector[X_PutImage] = PanoramiXPutImage; + ProcVector[X_GetImage] = PanoramiXGetImage; + ProcVector[X_PolyText8] = PanoramiXPolyText8; + ProcVector[X_PolyText16] = PanoramiXPolyText16; + ProcVector[X_ImageText8] = PanoramiXImageText8; + ProcVector[X_ImageText16] = PanoramiXImageText16; + ProcVector[X_CreateColormap] = PanoramiXCreateColormap; + ProcVector[X_FreeColormap] = PanoramiXFreeColormap; + ProcVector[X_InstallColormap] = PanoramiXInstallColormap; + ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; + ProcVector[X_AllocColor] = PanoramiXAllocColor; + ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; + ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; + ProcVector[X_FreeColors] = PanoramiXFreeColors; + ProcVector[X_StoreColors] = PanoramiXStoreColors; + + } + else + return; +} +extern +Bool PanoramiXCreateConnectionBlock(void) +{ + int i; + int old_width, old_height; + int width_mult, height_mult; + xWindowRoot *root; + xConnSetup *setup; + + /* + * Do normal CreateConnectionBlock but faking it for only one screen + */ + + if (!CreateConnectionBlock()) { + return FALSE; + } + + /* + * OK, change some dimensions so it looks as if it were one big screen + */ + + setup = (xConnSetup *) ConnectionInfo; + setup->numRoots = 1; + root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); + + old_width = root->pixWidth; + old_height = root->pixHeight; + for (i = PanoramiXNumScreens - 1; i >= 0; i--) { + if (panoramiXdataPtr[i].right == -1 ) + root->pixWidth = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; + if (panoramiXdataPtr[i].below == -1) + root->pixHeight = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; + } + PanoramiXPixWidth = root->pixWidth; + PanoramiXPixHeight = root->pixHeight; + width_mult = root->pixWidth / old_width; + height_mult = root->pixHeight / old_height; + root->mmWidth *= width_mult; + root->mmHeight *= height_mult; + return TRUE; +} + +extern +Bool PanoramiXCreateScreenRegion(pWin) +WindowPtr pWin; +{ + ScreenPtr pScreen; + BoxRec box; + int i; + Bool ret; + + pScreen = pWin->drawable.pScreen; + for (i = 0; i < PanoramiXNumScreens; i++) { + box.x1 = 0 - panoramiXdataPtr[i].x; + box.x2 = box.x1 + PanoramiXPixWidth; + box.y1 = 0 - panoramiXdataPtr[i].y; + box.y2 = box.y1 + PanoramiXPixHeight; + REGION_INIT(pScreen, &PanoramiXScreenRegion[i], &box, 1); + ret = REGION_NOTEMPTY(pScreen, &PanoramiXScreenRegion[i]); + if (!ret) + return ret; + } + return ret; +} + +extern +void PanoramiXDestroyScreenRegion(pWin) +WindowPtr pWin; +{ + ScreenPtr pScreen; + int i; + Bool ret; + + pScreen = pWin->drawable.pScreen; + for (i = 0; i < PanoramiXNumScreens; i++) + REGION_DESTROY(pScreen, &PanoramiXScreenRegion[i]); +} + +/* + * Assign the Root window and colormap ID's in the PanoramiXScreen Root + * linked lists. Note: WindowTable gets setup in dix_main by + * InitRootWindow, and GlobalScrInfo is screenInfo which gets setup + * by InitOutput. + */ +extern +void PanoramiXConsolidate(void) +{ + int i,j,k,v,d,n, thisMaxDepth; + int depthIndex; + DepthPtr pDepth, pLargeDepth; + VisualPtr pVisual; + VisualID it; + register WindowPtr pWin, pLargeWin; + Bool SameDepth; + + PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[PanoramiXNumScreens -1])->numDepths; + PanoramiXLargestScreenDepth.screenNum = PanoramiXNumScreens - 1; + SameDepth = TRUE; + for (i = 0; i < 2; i++) + { + for (j =0; j < 6; j++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].numDepths=0; + for (n = 0; n < 6; n++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].listDepths[n]=0; + } + for (k = 0; k < 33; k++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].numVids=0; + for (v = 0; v < 10; v++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].vid[v]=0; + } + } + } + } + for (i = PanoramiXNumScreens - 1; i >= 0; i--) + { + PanoramiXWinRoot->info[i].id = WindowTable[i]->drawable.id; + PanoramiXCmapRoot->info[i].id = (screenInfo.screens[i])->defColormap; + + /* Create a Color-Depth-Table, this will help us deal + with mixing graphics boards and visuals, of course + given that the boards support multi-screen to begin + with. Fill the panoramiXCDT table by screen, then + visual type and allowable depths. + */ + pWin = WindowTable[i]; + if ( (screenInfo.screens[i])->numDepths > + PanoramiXLargestScreenDepth.numDepths ) + { + PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[i])->numDepths; + PanoramiXLargestScreenDepth.screenNum = i; + SameDepth = FALSE; + } + for (v = 0, pVisual = pWin->drawable.pScreen->visuals; + v < pWin->drawable.pScreen->numVisuals; v++, pVisual++) + { + PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].numDepths = (screenInfo.screens[i])->numDepths; + for ( j = 0; j < (screenInfo.screens[i])->numDepths; j++) + { + pDepth = (DepthPtr) &pWin->drawable.pScreen->allowedDepths[j]; + PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].listDepths[j] = pDepth->depth; + for (d = 0; d < pDepth->numVids; d++) + { + if (pVisual->vid == pDepth->vids[d]) + { + PanoramiXColorDepthTable[i]. + panoramiXScreenMap[pVisual->class].vmap[pDepth->depth]. + vid[ + PanoramiXColorDepthTable[i]. + panoramiXScreenMap[pVisual->class]. + vmap[pDepth->depth].numVids++ + ] + = pDepth->vids[d]; + } + } + } + } + PanoramiXColorDepthTable[i].numVisuals = 6; + } /* for each screen */ + /* Fill in ColorDepthTable for mixed visuals with varying depth. + Can't do that until we figure out how to handle mixed visuals + and varying card visual/depth initialization. If we can decide + how to map the relationship, then we can use this table to + shove the information into and use for cross-referencing when + necessary. + + In the meantime, check to see if the screens are the same, + if they don't then disable panoramiX, print out a message, + don't support this mode. + */ +} + +/* Since locate_neighbors is recursive, a quick simple example + is in order.This mostly so you can see what the initial values are. + + Given 3 screens: + upperleft screen[0] + panoramiXdataPtr[0].x = 0 + panoramiXdataPtr[0].y = 0 + panoramiXdataPtr[0].width = 640 + panoramiXdataPtr[0].height = 480 + panoramiXdataPtr[0].below = -1 + panoramiXdataPtr[0].right = 1 + panoramiXdataPtr[0].above = -1 + panoramiXdataPtr[0].left = -1 + middle screen[1] + panoramiXdataPtr[1].x = 0 + panoramiXdataPtr[1].y = 0 + panoramiXdataPtr[1].width = 640 + panoramiXdataPtr[1].height = 480 + panoramiXdataPtr[1].below = -1 + panoramiXdataPtr[1].right = 2 + panoramiXdataPtr[1].above = -1 + panoramiXdataPtr[1].left = 0 + last right screen[2] + panoramiXdataPtr[2].x = 0 + panoramiXdataPtr[2].y = 0 + panoramiXdataPtr[2].width = 640 + panoramiXdataPtr[2].height = 480 + panoramiXdataPtr[2].below = -1 + panoramiXdataPtr[2].right = -1 + panoramiXdataPtr[2].above = -1 + panoramiXdataPtr[2].left = 1 + + Calling locate_neighbors(0) results in: + panoramiXdataPtr[0].x = 0 + panoramiXdataPtr[0].y = 0 + panoramiXdataPtr[1].x = 640 + panoramiXdataPtr[1].y = 0 + panoramiXdataPtr[2].x = 1280 + panoramiXdataPtr[2].y = 0 +*/ + +static void locate_neighbors(int i) +{ + int j; + + j = panoramiXdataPtr[i].right; + if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) { + panoramiXdataPtr[j].x = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; + panoramiXdataPtr[j].y = panoramiXdataPtr[i].y; + locate_neighbors(j); + } + j = panoramiXdataPtr[i].below; + if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) { + panoramiXdataPtr[j].y = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; + panoramiXdataPtr[j].x = panoramiXdataPtr[i].x; + locate_neighbors(j); + } +} + + + +/* + * PanoramiXResetProc() + * Exit, deallocating as needed. + */ + +static void PanoramiXResetProc(extEntry) + ExtensionEntry* extEntry; +{ + int i; + PanoramiXList *pPanoramiXList; + PanoramiXList *tempList; + + for (pPanoramiXList = PanoramiXPmapRoot; pPanoramiXList; pPanoramiXList = tempList){ + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + for (pPanoramiXList = PanoramiXCmapRoot; pPanoramiXList; pPanoramiXList = tempList){ + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + for (pPanoramiXList = PanoramiXGCRoot; pPanoramiXList; pPanoramiXList = tempList) { + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + for (pPanoramiXList = PanoramiXWinRoot; pPanoramiXList; pPanoramiXList = tempList) { + tempList = pPanoramiXList->next; + Xfree(pPanoramiXList); + } + screenInfo.numScreens = PanoramiXNumScreens; + for (i = 256; i--; ) + ProcVector[i] = SavedProcVector[i]; + Xfree(panoramiXdataPtr); + +} + + +int +#if NeedFunctionPrototypes +ProcPanoramiXQueryVersion (ClientPtr client) +#else +ProcPanoramiXQueryVersion (client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXQueryVersionReq); + xPanoramiXQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = PANORAMIX_MAJOR_VERSION; + rep.minorVersion = PANORAMIX_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +int +#if NeedFunctionPrototypes +ProcPanoramiXGetState(ClientPtr client) +#else +ProcPanoramiXGetState(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPanoramiXExtension; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.state, n); + } + WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); + return client->noClientException; + +} + +int +#if NeedFunctionPrototypes +ProcPanoramiXGetScreenCount(ClientPtr client) +#else +ProcPanoramiXGetScreenCount(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = PanoramiXNumScreens; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.ScreenCount, n); + } + WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcPanoramiXGetScreenSize(ClientPtr client) +#else +ProcPanoramiXGetScreenSize(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + /* screen dimensions */ + rep.width = panoramiXdataPtr[stuff->screen].width; + rep.height = panoramiXdataPtr[stuff->screen].height; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (rep.width, n); + swaps (rep.height, n); + } + WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); + return client->noClientException; +} + + +void PrintList(PanoramiXList *head) +{ + int i = 0; + + for (; head; i++, head = head->next) + fprintf(stderr, "%2d next = 0x%010lx, id[0] = 0x%08x, id[1] = 0x%08x\n", + i, head->next, head->info[0].id, head->info[1].id); +} +static int +#if NeedFunctionPrototypes +ProcPanoramiXDispatch (ClientPtr client) +#else +ProcPanoramiXDispatch (client) + ClientPtr client; +#endif +{ REQUEST(xReq); + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return ProcPanoramiXQueryVersion(client); + case X_PanoramiXGetState: + return ProcPanoramiXGetState(client); + case X_PanoramiXGetScreenCount: + return ProcPanoramiXGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return ProcPanoramiXGetScreenSize(client); + } + return BadRequest; +} diff --git a/Xext/panoramiXSwap.c b/Xext/panoramiXSwap.c new file mode 100644 index 000000000..c6bb5071e --- /dev/null +++ b/Xext/panoramiXSwap.c @@ -0,0 +1,158 @@ +/* $Xorg: panoramiXSwap.c,v 1.4 2000/08/17 19:47:57 cpqbld Exp $ */ +/***************************************************************** +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. +******************************************************************/ + +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "gc.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "window.h" +#include "windowstr.h" +#include "pixmapstr.h" +#if 0 +#include <sys/workstation.h> +#include <X11/Xserver/ws.h> +#endif +#include "panoramiX.h" +#include "panoramiXproto.h" + + +/* +/* + * External references for data variables + */ + +extern Bool noPanoramiXExtension; +extern Bool PanoramiXVisibilityNotifySent; +extern WindowPtr *WindowTable; +extern int defaultBackingStore; +extern char *ConnectionInfo; +extern int connBlockScreenStart; +extern int (* ProcVector[256]) (); + +#if NeedFunctionPrototypes +#define PROC_EXTERN(pfunc) extern int pfunc(ClientPtr) +#else +#define PROC_EXTERN(pfunc) extern int pfunc() +#endif + +PROC_EXTERN(ProcPanoramiXQueryVersion); +PROC_EXTERN(ProcPanoramiXGetState); +PROC_EXTERN(ProcPanoramiXGetScreenCount); +PROC_EXTERN(PropPanoramiXGetScreenSize); + +static int +#if NeedFunctionPrototypes +SProcPanoramiXQueryVersion (ClientPtr client) +#else +SProcPanoramiXQueryVersion (client) + register ClientPtr client; +#endif +{ + register int n; + REQUEST(xPanoramiXQueryVersionReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + return ProcPanoramiXQueryVersion(client); +} + +static int +#if NeedFunctionPrototypes +SProcPanoramiXGetState(ClientPtr client) +#else +SProcPanoramiXGetState(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + +} + +static int +#if NeedFunctionPrototypes +SProcPanoramiXGetScreenCount(ClientPtr client) +#else +SProcPanoramixGetScreenCount(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return ProcPanoramiXGetScreenCount(client); +} + +static int +#if NeedFunctionPrototypes +SProcPanoramiXGetScreenSize(ClientPtr client) +#else +SProcPanoramiXGetScreenSize(client) + register ClientPtr client; +#endif +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return ProcPanoramiXGetScreenSize(client); +} + +int +#if NeedFunctionPrototypes +SProcPanoramiXDispatch (ClientPtr client) +#else +SProcPanoramiXDispatch (client) + ClientPtr client; +#endif +{ REQUEST(xReq); + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return SProcPanoramiXQueryVersion(client); + case X_PanoramiXGetState: + return SProcPanoramiXGetState(client); + case X_PanoramiXGetScreenCount: + return SProcPanoramiXGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return SProcPanoramiXGetScreenSize(client); + return BadRequest; + } +} diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c new file mode 100644 index 000000000..cd54bdcb3 --- /dev/null +++ b/Xext/panoramiXprocs.c @@ -0,0 +1,3034 @@ +/* $Xorg: panoramiXprocs.c,v 1.5 2000/08/17 19:47:57 cpqbld Exp $ */ +/***************************************************************** +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. +******************************************************************/ + +#include <stdio.h> +#include "X.h" +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xproto.h" +#include "windowstr.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "inputstr.h" +#include "migc.h" +#include "misc.h" +#include "dixstruct.h" +#include "panoramiX.h" + +extern Bool noPanoramiXExtension; +extern Bool PanoramiXVisibilityNotifySent; +extern Bool PanoramiXMapped; +extern int PanoramiXNumScreens; +extern int PanoramiXPixWidth; +extern int PanoramiXPixHeight; +extern PanoramiXWindow *PanoramiXWinRoot; +extern PanoramiXGC *PanoramiXGCRoot; +extern PanoramiXCmap *PanoramiXCmapRoot; +extern PanoramiXPmap *PanoramiXPmapRoot; +extern PanoramiXData *panoramiXdataPtr; +extern PanoramiXCDT PanoramiXColorDepthTable[MAXSCREENS]; +extern ScreenInfo *GlobalScrInfo; +extern int (* SavedProcVector[256])(); +extern void (* ReplySwapVector[256])(); +extern WindowPtr *WindowTable; +extern char *ConnectionInfo; +extern int connBlockScreenStart; + +extern XID clientErrorValue; + +extern void Swap32Write(); + +extern long defaultScreenSaverTime; +extern long defaultScreenSaverInterval; +extern int defaultScreenSaverBlanking; +extern int defaultScreenSaverAllowExposures; +static ClientPtr onlyClient; +static Bool grabbingClient = FALSE; +#ifdef __alpha /* THIS NEEDS TO BE LONG !!!! Change driver! */ +int *checkForInput[2]; +#else +long *checkForInput[2]; +#endif +extern int connBlockScreenStart; + +extern int (* InitialVector[3]) (); +extern int (* ProcVector[256]) (); +extern int (* SwappedProcVector[256]) (); +extern void (* EventSwapVector[128]) (); +extern void (* ReplySwapVector[256]) (); +extern void Swap32Write(), SLHostsExtend(), SQColorsExtend(), +WriteSConnectionInfo(); +extern void WriteSConnSetupPrefix(); +extern char *ClientAuthorized(); +extern Bool InsertFakeRequest(); +static void KillAllClients(); +static void DeleteClientFromAnySelections(); +extern void ProcessWorkQueue(); + + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number active clients */ + +char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + + + +extern int Ones(); + +int PanoramiXCreateWindow(register ClientPtr client) +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result, j = 0; + unsigned len; + Bool FoundIt = FALSE; + Window winID; + Window parID; + PanoramiXWindow *localWin; + PanoramiXWindow *parentWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXCmap *pPanoramiXCmap = NULL; + PanoramiXPmap *pBackgndPmap = NULL; + PanoramiXPmap *pBorderPmap = NULL; + VisualID orig_visual; + XID orig_wid; + int orig_x, orig_y; + register Mask orig_mask; + int cmap_offset = 0; + int pback_offset = 0; + int pbord_offset = 0; + int class_index, this_class_index; + int vid_index, this_vid_index; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + IF_RETURN((Ones((Mask)stuff->mask) != len), BadLength); + orig_mask = stuff->mask; + PANORAMIXFIND_ID(parentWin, stuff->parent); + if (parentWin) { + localWin = (PanoramiXWindow *)Xcalloc(sizeof(PanoramiXWindow)); + IF_RETURN(!localWin, BadAlloc); + } else { + return BadWindow; + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWBackPixmap)) { + XID pmapID; + + pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pback_offset); + if (pmapID) { + pBackgndPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBackgndPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWBorderPixmap)) { + XID pmapID; + + pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pbord_offset); + if (pmapID) { + pBorderPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBorderPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWColormap)) { + Colormap cmapID; + + cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); + cmapID = *((CARD32 *) &stuff[1] + cmap_offset); + if (cmapID) { + pPanoramiXCmap = PanoramiXCmapRoot; + PANORAMIXFIND_ID(pPanoramiXCmap, cmapID); + } + } + orig_x = stuff->x; + orig_y = stuff->y; + orig_wid = stuff->wid; + orig_visual = stuff->visual; + for (j = 0; j <= PanoramiXNumScreens - 1; j++) { + winID = j ? FakeClientID(client->index) : orig_wid; + localWin->info[j].id = winID; + } + localWin->FreeMe = FALSE; + localWin->visibility = VisibilityNotViewable; + localWin->VisibilitySent = FALSE; + PANORAMIXFIND_LAST(pPanoramiXWin, PanoramiXWinRoot); + pPanoramiXWin->next = localWin; + if ( (stuff->visual != CopyFromParent) && (stuff->depth != 0)) + { + /* Find the correct visual for this screen */ + for (class_index = 0; class_index < PanoramiXColorDepthTable[0].numVisuals; +class_index++) + { + for (vid_index = 0; vid_index < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[stuff->depth].numVids; vid_index++) + { + if ( stuff->visual == PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[stuff->depth].vid[vid_index] ) + { + this_class_index = class_index; + this_vid_index = vid_index; + FoundIt = TRUE; + break; + } + } + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (parentWin == PanoramiXWinRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + stuff->wid = localWin->info[j].id; + parID = (XID)(parentWin->info[j].id); + pParent = (WindowPtr)SecurityLookupWindow(parID, client,SecurityReadAccess); + IF_RETURN((!pParent),BadWindow); + stuff->parent = parID; + if ( (orig_visual != CopyFromParent) && (stuff->depth != 0) && FoundIt ) + { + stuff->visual = PanoramiXColorDepthTable[j].panoramiXScreenMap[this_class_index].vmap[stuff->depth].vid[this_vid_index]; + } + if (pBackgndPmap) + *((CARD32 *) &stuff[1] + pback_offset) = pBackgndPmap->info[j].id; + if (pBorderPmap) + *((CARD32 *) &stuff[1] + pbord_offset) = pBorderPmap->info[j].id; + if (pPanoramiXCmap) + *((CARD32 *) &stuff[1] + cmap_offset) = pPanoramiXCmap->info[j].id; + stuff->mask = orig_mask; + result = (*SavedProcVector[X_CreateWindow])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXWin->next = NULL; + if (localWin) + Xfree(localWin); + } + return (result); +} + + + +int PanoramiXChangeWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + int j; + Window winID; + Mask orig_valueMask; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWinback = NULL; + PanoramiXCmap *pPanoramiXCmap = NULL; + PanoramiXPmap *pBackgndPmap = NULL; + PanoramiXPmap *pBorderPmap = NULL; + int cmap_offset = 0; + int pback_offset = 0; + int pbord_offset = 0; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + IF_RETURN((len != Ones((Mask) stuff->valueMask)), BadLength); + orig_valueMask = stuff->valueMask; + winID = stuff->window; + for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->window); + pPanoramiXWin = pPanoramiXWin->next) + pPanoramiXWinback = pPanoramiXWin; + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, winID); + IF_RETURN(!pPanoramiXWin, BadWindow); + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWBackPixmap)) { + XID pmapID; + + pback_offset = Ones((Mask)stuff->valueMask & (CWBackPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pback_offset); + if (pmapID) { + pBackgndPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBackgndPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWBorderPixmap)) { + XID pmapID; + + pbord_offset = Ones((Mask)stuff->valueMask & (CWBorderPixmap - 1)); + pmapID = *((CARD32 *) &stuff[1] + pbord_offset); + if (pmapID) { + pBorderPmap = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pBorderPmap, pmapID); + } + } + if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWColormap )) { + Colormap cmapID; + + cmap_offset = Ones((Mask)stuff->valueMask & (CWColormap - 1)); + cmapID = *((CARD32 *) &stuff[1] + cmap_offset); + if (cmapID) { + pPanoramiXCmap = PanoramiXCmapRoot; + PANORAMIXFIND_ID(pPanoramiXCmap, cmapID); + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + stuff->valueMask = orig_valueMask; + if (pBackgndPmap) + *((CARD32 *) &stuff[1] + pback_offset) = pBackgndPmap->info[j].id; + if (pBorderPmap) + *((CARD32 *) &stuff[1] + pbord_offset) = pBorderPmap->info[j].id; + if (pPanoramiXCmap) + *((CARD32 *) &stuff[1] + cmap_offset) = pPanoramiXCmap->info[j].id; + result = (*SavedProcVector[X_ChangeWindowAttributes])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXWinback && + pPanoramiXWin && pPanoramiXWin->FreeMe) { + pPanoramiXWinback->next = pPanoramiXWin->next; + Xfree(pPanoramiXWin); + } + return (result); +} + + +int PanoramiXDestroyWindow(ClientPtr client) +{ + REQUEST(xResourceReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWinback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->id); + pPanoramiXWin = pPanoramiXWin->next) + pPanoramiXWinback = pPanoramiXWin; + IF_RETURN(!pPanoramiXWin,BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->id = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_DestroyWindow])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXWinback && + pPanoramiXWin && pPanoramiXWin->FreeMe) { + pPanoramiXWinback->next = pPanoramiXWin->next; + Xfree(pPanoramiXWin); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXDestroySubwindows(ClientPtr client) +{ + REQUEST(xResourceReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXWinback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->id); + pPanoramiXWin = pPanoramiXWin->next) + pPanoramiXWinback = pPanoramiXWin; + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->id = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_DestroySubwindows])(client); + } + if ((result == Success) && pPanoramiXWinback && + pPanoramiXWin && pPanoramiXWin->FreeMe) { + pPanoramiXWinback->next = pPanoramiXWin->next; + Xfree(pPanoramiXWin); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXChangeSaveSet(ClientPtr client) +{ + REQUEST(xChangeSaveSetReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + if (!stuff->window) + result = (* SavedProcVector[X_ChangeSaveSet])(client); + else { + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_ChangeSaveSet])(client); + } + } + return (result); +} + + +int PanoramiXReparentWindow(register ClientPtr client) +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXPar = PanoramiXWinRoot; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + PANORAMIXFIND_ID(pPanoramiXPar, stuff->parent); + IF_RETURN(!pPanoramiXPar, BadWindow); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXPar), j) { + stuff->window = pPanoramiXWin->info[j].id; + stuff->parent = pPanoramiXPar->info[j].id; + result = (*SavedProcVector[X_ReparentWindow])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXMapWindow(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + Window winID; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility */ + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, +SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + winID = pPanoramiXWin->info[j].id; + pWin = (WindowPtr) SecurityLookupWindow(winID, +client,SecurityReadAccess); + IF_RETURN((!pWin), BadWindow); + stuff->id = winID; + result = (*SavedProcVector[X_MapWindow])(client); + } + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + return (result); +} + + +int PanoramiXMapSubwindows(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility values */ + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + stuff->id = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_MapSubwindows])(client); + } + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXUnmapWindow(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility values */ + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + stuff->id = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_UnmapWindow])(client); + } + + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + PANORAMIX_FREE(client); + return (client->noClientException); +} + + +int PanoramiXUnmapSubwindows(register ClientPtr client) +{ + REQUEST(xResourceReq); + int j, result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + register WindowPtr pWin, pChild; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + /* initialize visibility values */ + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + IF_RETURN(!pWin, BadWindow); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + + PANORAMIXFIND_ID(pPanoramiXWin, stuff->id); + IF_RETURN(!pPanoramiXWin, BadWindow); + PanoramiXMapped = TRUE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) + { + stuff->id = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_UnmapSubwindows])(client); + } + + /* clean up */ + PanoramiXMapped = FALSE; + PanoramiXVisibilityNotifySent = FALSE; + pPanoramiXWin->VisibilitySent = FALSE; + pWin = (WindowPtr) SecurityLookupWindow(stuff->id, +client,SecurityReadAccess); + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){ + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id); + if (pPanoramiXWin) + pPanoramiXWin->VisibilitySent = FALSE; + } + PANORAMIX_FREE(client); + return (client->noClientException); +} + + +int PanoramiXConfigureWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + unsigned len, i, things; + XID changes[32]; + register Mask orig_mask; + int j, sib_position; + Window winID; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXWindow *pPanoramiXSib = NULL; + int x_off = 0, y_off = 0; + XID *pStuff; + XID *origStuff, *modStuff; + Mask local_mask; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + things = Ones((Mask)stuff->mask); + IF_RETURN((things != len), BadLength); + orig_mask = stuff->mask; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + if (!pPanoramiXWin) { + client->errorValue = stuff->window; + return (BadWindow); + } + if (things > 0) { + pStuff = (XID *) ALLOCATE_LOCAL(things * sizeof(XID)); + memcpy((char *) pStuff, (char *) &stuff[1], things * sizeof(XID)); + local_mask = (CWSibling | CWX | CWY) & ((Mask) stuff->mask); + if (local_mask & CWSibling) { + sib_position = Ones((Mask) stuff->mask & (CWSibling - 1)); + pPanoramiXSib = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXSib, *(pStuff + sib_position)); + } + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + winID = pPanoramiXWin->info[j].id; + pWin = (WindowPtr)SecurityLookupWindow(winID, client,SecurityReadAccess); + if (!pWin) { + client->errorValue = pPanoramiXWin->info[0].id; + return (BadWindow); + } + stuff->window = winID; + if (pWin->parent + && (pWin->parent->drawable.id == PanoramiXWinRoot->info[j].id)) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + modStuff = (XID *) &stuff[1]; + origStuff = pStuff; + i = things; + if (local_mask & CWX) { + *modStuff++ = *origStuff++ - x_off; + i--; + } + if (local_mask & CWY) { + *modStuff++ = *origStuff++ - y_off; + i--; + } + for ( ; i; i--) + *modStuff++ = *origStuff++; + if (pPanoramiXSib) + *((XID *) &stuff[1] + sib_position) = pPanoramiXSib->info[j].id; + stuff->mask = orig_mask; + result = (*SavedProcVector[X_ConfigureWindow])(client); + } + DEALLOCATE_LOCAL(pStuff); + PANORAMIX_FREE(client); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXCirculateWindow(register ClientPtr client) +{ + REQUEST(xCirculateWindowReq); + int j,result; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (*SavedProcVector[X_CirculateWindow])(client); + } + return (result); +} + + +int PanoramiXGetGeometry(register ClientPtr client) +{ + xGetGeometryReply rep; + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + VERIFY_GEOMETRABLE (pDraw, stuff->id, client); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep.depth = pDraw->depth; + + if (stuff->id == PanoramiXWinRoot->info[0].id) { + xConnSetup *setup = (xConnSetup *) ConnectionInfo; + xWindowRoot *root = (xWindowRoot *) + (ConnectionInfo + connBlockScreenStart); + + rep.width = root->pixWidth; + rep.height = root->pixHeight; + } else { + rep.width = pDraw->width; + rep.height = pDraw->height; + } + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) { + register WindowPtr pWin = (WindowPtr)pDraw; + rep.x = pWin->origin.x - wBorderWidth (pWin); + rep.y = pWin->origin.y - wBorderWidth (pWin); + rep.borderWidth = pWin->borderWidth; + } else { /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + rep.x = rep.y = rep.borderWidth = 0; + } + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return (client->noClientException); +} + + +int PanoramiXChangeProperty(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + REQUEST(xChangePropertyReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_ChangeProperty])(client); + if (result != Success) { + stuff->window = pPanoramiXWin->info[0].id; + break; + } + } + return (result); +} + + +int PanoramiXDeleteProperty(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + REQUEST(xDeletePropertyReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->window = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_DeleteProperty])(client); + BREAK_IF(result != Success); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXSendEvent(ClientPtr client) +{ + int result, j; + BYTE orig_type; + Mask orig_eventMask; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + REQUEST(xSendEventReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xSendEventReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->destination); + orig_type = stuff->event.u.u.type; + orig_eventMask = stuff->eventMask; + if (!pPanoramiXWin) { + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_SendEvent])(client); + noPanoramiXExtension = FALSE; + } + else { + noPanoramiXExtension = FALSE; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->destination = pPanoramiXWin->info[j].id; + stuff->eventMask = orig_eventMask; + stuff->event.u.u.type = orig_type; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_SendEvent])(client); + noPanoramiXExtension = FALSE; + } + } + return (result); +} + + +int PanoramiXCreatePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + int result, j; + Pixmap pmapID; + PanoramiXWindow *pPanoramiXWin; + PanoramiXPmap *pPanoramiXPmap; + PanoramiXPmap *localPmap; + XID orig_pid; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + + localPmap =(PanoramiXPmap *) Xcalloc(sizeof(PanoramiXPmap)); + IF_RETURN(!localPmap, BadAlloc); + + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!pDraw, BadDrawable); + + pPanoramiXWin = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadWindow); + + orig_pid = stuff->pid; + FOR_NSCREENS_OR_ONCE(pPanoramiXPmap, j) { + pmapID = j ? FakeClientID(client->index) : orig_pid; + localPmap->info[j].id = pmapID; + } + localPmap->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot); + pPanoramiXPmap->next = localPmap; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->pid = localPmap->info[j].id; + stuff->drawable = pPanoramiXWin->info[j].id; + result = (* SavedProcVector[X_CreatePixmap])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXPmap->next = NULL; + if (localPmap) + Xfree(localPmap); + } + return (result); +} + + +int PanoramiXFreePixmap(ClientPtr client) +{ + PixmapPtr pMap; + int result, j; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + PanoramiXPmap *pPanoramiXPmapback = NULL; + REQUEST(xResourceReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXPmap && (pPanoramiXPmap->info[0].id != stuff->id); + pPanoramiXPmap = pPanoramiXPmap->next) + pPanoramiXPmapback = pPanoramiXPmap; + if (!pPanoramiXPmap) + result = (* SavedProcVector[X_FreePixmap])(client); + else { + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->id = pPanoramiXPmap->info[j].id; + result = (* SavedProcVector[X_FreePixmap])(client); + } + if ((result == Success) && pPanoramiXPmapback && + pPanoramiXPmap && pPanoramiXPmap->FreeMe ) { + pPanoramiXPmapback->next = pPanoramiXPmap->next; + Xfree(pPanoramiXPmap); + } + } + return (result); +} + + +int PanoramiXCreateGC(register ClientPtr client) +{ + int result, j; + GC *pGC; + DrawablePtr pDraw; + unsigned len, i; + REQUEST(xCreateGCReq); + GContext GCID; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *localGC; + PanoramiXGC *pPanoramiXGC; + PanoramiXPmap *pPanoramiXTile = NULL, *pPanoramiXStip = NULL; + PanoramiXPmap *pPanoramiXClip = NULL; + int tile_offset, stip_offset, clip_offset; + XID orig_GC; + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!pDraw, BadDrawable); + pPanoramiXWin = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + IF_RETURN((len != Ones((Mask)stuff->mask)), BadLength); + localGC = (PanoramiXGC *) Xcalloc(sizeof(PanoramiXGC)); + IF_RETURN(!localGC, BadAlloc); + orig_GC = stuff->gc; + if ((Mask)stuff->mask & GCTile) { + XID tileID; + + tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); + tileID = *((CARD32 *) &stuff[1] + tile_offset); + if (tileID) { + pPanoramiXTile = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXTile, tileID); + } + } + if ((Mask)stuff->mask & GCStipple) { + XID stipID; + + stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); + stipID = *((CARD32 *) &stuff[1] + stip_offset); + if (stipID) { + pPanoramiXStip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXStip, stipID); + } + } + if ((Mask)stuff->mask & GCClipMask) { + XID clipID; + + clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); + clipID = *((CARD32 *) &stuff[1] + clip_offset); + if (clipID) { + pPanoramiXClip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXClip, clipID); + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + GCID = j ? FakeClientID(client->index) : orig_GC; + localGC->info[j].id = GCID; + } + localGC->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXGC, PanoramiXGCRoot); + pPanoramiXGC->next = localGC; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->gc = localGC->info[j].id; + stuff->drawable = pPanoramiXWin->info[j].id; + if (pPanoramiXTile) + *((CARD32 *) &stuff[1] + tile_offset) = pPanoramiXTile->info[j].id; + if (pPanoramiXStip) + *((CARD32 *) &stuff[1] + stip_offset) = pPanoramiXStip->info[j].id; + if (pPanoramiXClip) + *((CARD32 *) &stuff[1] + clip_offset) = pPanoramiXClip->info[j].id; + result = (* SavedProcVector[X_CreateGC])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXGC->next = NULL; + Xfree(localGC); + } + return (result); +} + + +int PanoramiXChangeGC(ClientPtr client) +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result, j; + unsigned len; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + PanoramiXPmap *pPanoramiXTile = NULL, *pPanoramiXStip = NULL; + PanoramiXPmap *pPanoramiXClip = NULL; + int tile_offset, stip_offset, clip_offset; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + VERIFY_GC(pGC, stuff->gc, client); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + IF_RETURN((len != Ones((Mask)stuff->mask)), BadLength); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + if ((Mask)stuff->mask & GCTile) { + XID tileID; + + tile_offset = Ones((Mask)stuff->mask & (GCTile -1) ); + tileID = *((CARD32 *) &stuff[1] + tile_offset); + if (tileID) { + pPanoramiXTile = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXTile, tileID); + } + } + if ((Mask)stuff->mask & GCStipple) { + XID stipID; + + stip_offset = Ones((Mask)stuff->mask & (GCStipple -1 )); + stipID = *((CARD32 *) &stuff[1] + stip_offset); + if (stipID) { + pPanoramiXStip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXStip, stipID); + } + } + if ((Mask)stuff->mask & GCClipMask) { + XID clipID; + + clip_offset = Ones((Mask)stuff->mask & (GCClipMask -1)); + clipID = *((CARD32 *) &stuff[1] + clip_offset); + if (clipID) { + pPanoramiXClip = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXClip, clipID); + } + } + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXTile) + *((CARD32 *) &stuff[1] + tile_offset) = pPanoramiXTile->info[j].id; + if (pPanoramiXStip) + *((CARD32 *) &stuff[1] + stip_offset) = pPanoramiXStip->info[j].id; + if (pPanoramiXClip) + *((CARD32 *) &stuff[1] + clip_offset) = pPanoramiXClip->info[j].id; + result = (* SavedProcVector[X_ChangeGC])(client); + BREAK_IF(result != Success); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXCopyGC(ClientPtr client) +{ + int j, result; + PanoramiXGC *pPanoramiXGCSrc = PanoramiXGCRoot; + PanoramiXGC *pPanoramiXGCDst = PanoramiXGCRoot; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + PANORAMIXFIND_ID(pPanoramiXGCSrc, stuff->srcGC); + IF_RETURN(!pPanoramiXGCSrc, BadGC); + PANORAMIXFIND_ID(pPanoramiXGCDst, stuff->dstGC); + IF_RETURN(!pPanoramiXGCDst, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGCDst, j) { + stuff->srcGC = pPanoramiXGCSrc->info[j].id; + stuff->dstGC = pPanoramiXGCDst->info[j].id; + result = (* SavedProcVector[X_CopyGC])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXSetDashes(ClientPtr client) +{ + GC *pGC; + REQUEST(xSetDashesReq); + int result, j; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + VERIFY_GC(pGC, stuff->gc, client); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_SetDashes])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXSetClipRectangles(register ClientPtr client) +{ + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + int j; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_SetClipRectangles])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXFreeGC(ClientPtr client) +{ + register GC *pGC; + REQUEST(xResourceReq); + int result, j; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + PanoramiXGC *pPanoramiXGCback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + for (; pPanoramiXGC && (pPanoramiXGC->info[0].id != stuff->id); + pPanoramiXGC = pPanoramiXGC->next) + pPanoramiXGCback = pPanoramiXGC; + IF_RETURN(!pPanoramiXGC, BadGC); + FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) { + stuff->id = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_FreeGC])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXGCback && + pPanoramiXGC && pPanoramiXGC->FreeMe) { + pPanoramiXGCback->next = pPanoramiXGC->next; + if (pPanoramiXGC) + Xfree(pPanoramiXGC); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXClearToBackground(register ClientPtr client) +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + int result, j; + Window winID; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + int orig_x, orig_y; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xClearAreaReq); + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + IF_RETURN(!pPanoramiXWin, BadWindow); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + winID = pPanoramiXWin->info[j].id; + pWin = (WindowPtr) SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!pWin) { + client->errorValue = pPanoramiXWin->info[0].id; + return (BadWindow); + } + stuff->window = winID; + if (pWin->drawable.id == PanoramiXWinRoot->info[j].id) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ClearArea])(client); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXCopyArea(ClientPtr client) +{ + int j, result; + Window srcID, dstID; + DrawablePtr pSrc, pDst; + GContext GCID; + GC *pGC; + PanoramiXWindow *pPanoramiXSrcRoot; + PanoramiXWindow *pPanoramiXDstRoot; + PanoramiXWindow *pPanoramiXSrc; + PanoramiXWindow *pPanoramiXDst; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + REQUEST(xCopyAreaReq); + int srcx = stuff->srcX, srcy = stuff->srcY; + int dstx = stuff->dstX, dsty = stuff->dstY; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) { + VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } else { + pSrc = pDst; + } + pPanoramiXSrcRoot = (pSrc->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXDstRoot = (pDst->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXSrc = pPanoramiXSrcRoot; + pPanoramiXDst = pPanoramiXDstRoot; + PANORAMIXFIND_ID(pPanoramiXSrc, stuff->srcDrawable); + IF_RETURN(!pPanoramiXSrc, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXDst, stuff->dstDrawable); + IF_RETURN(!pPanoramiXDst, BadDrawable); + GCID = stuff->gc; + PANORAMIXFIND_ID(pPanoramiXGC, GCID); + IF_RETURN(!pPanoramiXGC, BadGC); + + FOR_NSCREENS_OR_ONCE(pPanoramiXSrc, j) { + stuff->dstDrawable = pPanoramiXDst->info[j].id; + stuff->srcDrawable = pPanoramiXSrc->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXSrc == pPanoramiXSrcRoot) { + stuff->srcX = srcx - panoramiXdataPtr[j].x; + stuff->srcY = srcy - panoramiXdataPtr[j].y; + } + if (pPanoramiXDst == pPanoramiXDstRoot) { + stuff->dstX = dstx - panoramiXdataPtr[j].x; + stuff->dstY = dsty - panoramiXdataPtr[j].y; + } + result = (* SavedProcVector[X_CopyArea])(client); + BREAK_IF(result != Success); + } + return (result); +} + +int PanoramiXCopyPlane(ClientPtr client) +{ + int SrcScr = -1, DstScr = -1; + PixmapPtr pMap = NULL; + Pixmap pmapID; + PanoramiXRect SrcRect, DstRect; + int i, j, k; + Window srcID, dstID; + DrawablePtr pSrc, pDst; + GContext GCID; + GContext GCIDbase; + GC *pGC; + PanoramiXWindow *pPanoramiXSrc; + PanoramiXWindow *pPanoramiXDst; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + RegionPtr *PanoramiXRgnPtrs; + RegionPtr *FetchRgnPtrs = NULL; + RegionPtr pRgn; + REQUEST(xCopyPlaneReq); + int srcx = stuff->srcX, srcy = stuff->srcY; + int dstx = stuff->dstX, dsty = stuff->dstY; + int width = stuff->width, height = stuff->height; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) { + VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client); + if (pDst->pScreen != pSrc->pScreen) { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } else { + pSrc = pDst; + } + + /* + * Check to see if stuff->bitPlane has exactly ONE good bit set + */ + + + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (pSrc->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pPanoramiXSrc = (pSrc->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXDst = (pDst->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXSrc, stuff->srcDrawable); + IF_RETURN(!pPanoramiXSrc, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXDst, stuff->dstDrawable); + IF_RETURN(!pPanoramiXDst, BadDrawable); + GCIDbase = stuff->gc; + PANORAMIXFIND_ID(pPanoramiXGC, GCIDbase); + IF_RETURN(!pPanoramiXGC, BadGC); + + /* + * Unless both are pixmaps, need to do special things to accomodate + * being on multiple screens, different screens, etc. + */ + + if (pSrc->type != DRAWABLE_PIXMAP) { + SrcRect.x = pSrc->x + srcx; + SrcRect.y = pSrc->y + srcy; + SrcRect.width = width; + SrcRect.height = height; + for (SrcScr = PanoramiXNumScreens - 1; SrcScr>=0; SrcScr-- ) + if (RECTA_SUBSUMES_RECTB(panoramiXdataPtr[SrcScr], SrcRect)) + break; + } + if (pDst->type != DRAWABLE_PIXMAP) { + DstRect.x = pDst->x + dstx; + DstRect.y = pDst->y + dsty; + DstRect.width = width; + DstRect.height = height; + for (DstScr = PanoramiXNumScreens - 1; DstScr>=0; DstScr--) + if (RECTA_SUBSUMES_RECTB(panoramiXdataPtr[DstScr], DstRect)) + break; + } + + /* + * If source is on multiple screens, different screen from destination, + * destination is on multiple screens, or destination is a pixmap, + * need to get info into local pixmap for subsequent transfer. + */ + + + if ((pSrc->type != DRAWABLE_PIXMAP) && + (SrcScr < 0 || DstScr < 0 || SrcScr != DstScr + || pDst->type == DRAWABLE_PIXMAP)) { + unsigned char save_alu; + RegionRec tempReg; + RegionPtr pCompositeClip; + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + + pMap = (PixmapPtr) (*pSrc->pScreen->CreatePixmap)(pSrc->pScreen, + width, height, pGC->depth); + PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot); + pPanoramiXPmap->next = + (PanoramiXPmap *)Xcalloc(sizeof(PanoramiXPmap)); + pPanoramiXPmap = pPanoramiXPmap->next; + pmapID = FakeClientID(0); + AddResource(pmapID, RT_PIXMAP, (pointer)pMap); + for (j = PanoramiXNumScreens - 1; j>=0; j--) + pPanoramiXPmap->info[j].id = pmapID; + tempReg.extents.x1 = 0; + tempReg.extents.y1 = 0; + tempReg.extents.x2 = width; + tempReg.extents.y2 = height; + tempReg.data = NULL; + FetchRgnPtrs = + (RegionPtr *) ALLOCATE_LOCAL(PanoramiXNumScreens * sizeof(RegionPtr)); + i = 0; + FOR_NSCREENS_OR_ONCE(pPanoramiXSrc, j) { + if ((SrcScr >= 0) && pPanoramiXSrc) + j = SrcScr; + srcID = pPanoramiXSrc->info[j].id; + pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE, + SecurityReadAccess); + GCID = pPanoramiXGC->info[j].id; + pGC = (GC *) LookupIDByType(GCID, RT_GC); + pMap->drawable.pScreen = pSrc->pScreen; + pGC->pScreen = pSrc->pScreen; + save_alu = pGC->alu; + pGC->alu = GXcopy; + pCompositeClip = ((miPrivGC*) + (pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip; + ((miPrivGC*)(pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip = +&tempReg; + FetchRgnPtrs[i++] = (*pGC->ops->CopyPlane)(pSrc, (DrawablePtr) pMap, + pGC, srcx, srcy, width, height, 0, 0, stuff->bitPlane); + pGC->alu = save_alu; + ((miPrivGC*) (pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip = +pCompositeClip; + if (SrcScr >= 0) + j = 0; + } + } + + if (pMap) { + pSrc = (DrawablePtr) pMap; + srcx = 0; + srcy = 0; + } + PanoramiXRgnPtrs = + (RegionPtr *) ALLOCATE_LOCAL(PanoramiXNumScreens * sizeof(RegionPtr)); + k = 0; + /* if src and dst are entirely on one screen, + then we only need one simple transfer */ + if ((DstScr >= 0) && (pMap || (SrcScr >=0))) { + dstID = pPanoramiXDst->info[DstScr].id; + pDst = (DrawablePtr) SecurityLookupIDByClass(client, dstID, RC_DRAWABLE, + SecurityReadAccess); + GCID = pPanoramiXGC->info[DstScr].id; + pGC = (GC *) LookupIDByType(GCID, RT_GC); + ValidateGC(pDst, pGC); + if (pMap) { + pMap->drawable.pScreen = pDst->pScreen; + } else { + srcID = pPanoramiXSrc->info[SrcScr].id; + if (srcID != dstID) { + pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE, + SecurityReadAccess); + } else + pSrc = pDst; + } + if (pMap) + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + 1); + else + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + stuff->bitPlane); + }else { + FOR_NSCREENS_OR_ONCE(pPanoramiXDst, j) { + if (DstScr >= 0) { + dstID = pPanoramiXDst->info[DstScr].id; + GCID = pPanoramiXGC->info[DstScr].id; + } else { + dstID = pPanoramiXDst->info[j].id; + GCID = pPanoramiXGC->info[j].id; + } + pDst = (DrawablePtr) SecurityLookupIDByClass(client, dstID, RC_DRAWABLE, + SecurityReadAccess); + pGC = (GC *) LookupIDByType(GCID, RT_GC); + ValidateGC(pDst, pGC); + if (pMap) { + pMap->drawable.pScreen = pDst->pScreen; + } else { + srcID = pPanoramiXSrc->info[j].id; + if (srcID != dstID) { + pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE, + SecurityReadAccess); + } else { + pSrc = pDst; + } + } + if (pMap) + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + 1); + else + PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + stuff->bitPlane); + } + } + + if (pMap) { + for (j = PanoramiXNumScreens - 1; j>=0; j--) + if (PanoramiXRgnPtrs[j]) + (*pDst->pScreen->RegionDestroy) (PanoramiXRgnPtrs[j]); + DEALLOCATE_LOCAL(PanoramiXRgnPtrs); + PanoramiXRgnPtrs = FetchRgnPtrs; + k = i; + } + j = 1; + i = 0; + pRgn = PanoramiXRgnPtrs[i]; + while ((j < k) && pRgn && !REGION_NIL(pRgn)) { + if (PanoramiXRgnPtrs[j]) { + (*pGC->pScreen->Intersect)(pRgn, pRgn, PanoramiXRgnPtrs[j++]); + } else { + pRgn = PanoramiXRgnPtrs[i++]; + } + } + for (j = 0 ; j < k; j++) { + pRgn = PanoramiXRgnPtrs[j]; + GCID = pPanoramiXGC->info[j].id; + pGC = (GC *) LookupIDByType(GCID, RT_GC); + if (pGC && pGC->graphicsExposures) + (*pDst->pScreen->SendGraphicsExpose) (client, pRgn, + stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + (*pDst->pScreen->RegionDestroy) (pRgn); + } + DEALLOCATE_LOCAL(PanoramiXRgnPtrs); + if (pMap) { + PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot; + PanoramiXPmap *pback = PanoramiXPmapRoot; + + for (; pPanoramiXPmap && (pPanoramiXPmap->info[0].id != pmapID); + pPanoramiXPmap = pPanoramiXPmap->next) + pback = pPanoramiXPmap; + FreeResource(pPanoramiXPmap->info[0].id, RT_NONE); + if (pback) { + pback->next = pPanoramiXPmap->next; + Xfree(pPanoramiXPmap); + } + } + return (client->noClientException); +} + + +int PanoramiXPolyPoint(ClientPtr client) +{ + int result, npoint, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xPoint *origPts; + xPoint *origPtr, *modPtr; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, locDraw->id); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint > 0) { + origPts = (xPoint *) ALLOCATE_LOCAL(npoint * sizeof(xPoint)); + memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xPoint *) &stuff[1]; + origPtr = origPts; + for (i = npoint; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyPoint])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origPts); + return (result); + }else + return (client->noClientException); + +} + + +int PanoramiXPolyLine(ClientPtr client) +{ + int result, npoint, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xPoint *origPts; + xPoint *origPtr, *modPtr; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, locDraw->id); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != locDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 0){ + origPts = (xPoint *) ALLOCATE_LOCAL(npoint * sizeof(xPoint)); + memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xPoint *) &stuff[1]; + origPtr = origPts; + for (i = npoint; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyLine])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origPts); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolySegment(ClientPtr client) +{ + int result, nsegs, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xSegment *origSegs; + xSegment *origPtr, *modPtr; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != locDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + IF_RETURN((nsegs & 4), BadLength); + nsegs >>= 3; + if (nsegs > 0) { + origSegs = (xSegment *) ALLOCATE_LOCAL(nsegs * sizeof(xSegment)); + memcpy((char *) origSegs, (char *) &stuff[1], nsegs * +sizeof(xSegment)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xSegment *) &stuff[1]; + origPtr = origSegs; + for (i = nsegs; i; i--) { + modPtr->x1 = origPtr->x1 - x_off; + modPtr->y1 = origPtr->y1 - y_off; + modPtr->x2 = origPtr->x2 - x_off; + modPtr++->y2 = origPtr++->y2 - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolySegment])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origSegs); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyRectangle(ClientPtr client) +{ + int result, nrects, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + int x_off = 0, y_off = 0; + xRectangle *origRecs; + xRectangle *origPtr, *modPtr; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + IF_RETURN((nrects & 4), BadLength); + nrects >>= 3; + if (nrects > 0){ + origRecs = (xRectangle *) ALLOCATE_LOCAL(nrects * sizeof(xRectangle)); + memcpy((char *) origRecs, (char *) &stuff[1], nrects * +sizeof(xRectangle)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xRectangle *) &stuff[1]; + origPtr = origRecs; + for (i = nrects; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr->y = origPtr->y - y_off; + modPtr->width = origPtr->width - x_off; + modPtr++->height = origPtr++->height - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyRectangle])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origRecs); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyArc(ClientPtr client) +{ + int result, narcs, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + xArc *origArcs; + xArc *origPtr, *modPtr; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : +PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + IF_RETURN((narcs % sizeof(xArc)), BadLength); + narcs /= sizeof(xArc); + if (narcs > 0){ + origArcs = (xArc *) ALLOCATE_LOCAL(narcs * sizeof(xArc)); + memcpy((char *) origArcs, (char *) &stuff[1], narcs * sizeof(xArc)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xArc *) &stuff[1]; + origPtr = origArcs; + for (i = narcs; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyArc])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origArcs); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXFillPoly(ClientPtr client) +{ + int result, count, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + DDXPointPtr locPts; + DDXPointPtr origPts, modPts; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + count = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (count > 0){ + locPts = (DDXPointPtr) ALLOCATE_LOCAL(count * sizeof(DDXPointRec)); + memcpy((char *) locPts, (char *) &stuff[1], count * +sizeof(DDXPointRec)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPts = (DDXPointPtr) &stuff[1]; + origPts = locPts; + for (i = count; i; i--) { + modPts->x = origPts->x - x_off; + modPts++->y = origPts++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_FillPoly])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(locPts); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyFillRectangle(ClientPtr client) +{ + int result, things, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + xRectangle *origThings; + xRectangle *origPtr, *modPtr; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : +PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + IF_RETURN((things & 4), BadLength); + things >>= 3; + if (things > 0){ + origThings = (xRectangle *) ALLOCATE_LOCAL(things * sizeof(xRectangle)); + memcpy((char *) origThings, (char *)&stuff[1], things * +sizeof(xRectangle)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xRectangle *) &stuff[1]; + origPtr = origThings; + for (i = things; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyFillRectangle])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origThings); + return (result); + }else + return (client->noClientException); +} + + +int PanoramiXPolyFillArc(ClientPtr client) +{ + int result, arcs, i, j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr locDraw; + GCPtr locGC; + int x_off = 0, y_off = 0; + xArc *origArcs; + xArc *origPtr, *modPtr; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!locDraw, BadDrawable); + pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : +PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + arcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + IF_RETURN((arcs % sizeof(xArc)), BadLength); + arcs /= sizeof(xArc); + if (arcs > 0) { + origArcs = (xArc *) ALLOCATE_LOCAL(arcs * sizeof(xArc)); + memcpy((char *) origArcs, (char *)&stuff[1], arcs * sizeof(xArc)); + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + if (pPanoramiXWin == PanoramiXWinRoot) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + }else { + if ( (locDraw->type == DRAWABLE_PIXMAP) && + /* add special case check for root window */ + (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + x_off = panoramiXdataPtr[j].x; + y_off = panoramiXdataPtr[j].y; + } + } + modPtr = (xArc *) &stuff[1]; + origPtr = origArcs; + for (i = arcs; i; i--) { + modPtr->x = origPtr->x - x_off; + modPtr++->y = origPtr++->y - y_off; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PolyFillArc])(client); + BREAK_IF(result != Success); + } + DEALLOCATE_LOCAL(origArcs); + return (result); + }else + return (client->noClientException); +} + + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ + +int PanoramiXPutImage(register ClientPtr client) +{ + register GC *pGC; + register DrawablePtr pDraw; + long lengthProto, /* length of scanline protocl padded */ + length; /* length of scanline server padded */ + char *tmpImage; + int j; + PanoramiXWindow *pPanoramiXWin; + PanoramiXWindow *pPanoramiXRoot; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + int orig_x, orig_y; + int result; + + + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable, +RC_DRAWABLE, + SecurityReadAccess); + IF_RETURN(!pDraw, BadDrawable); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin,BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->dstX; + orig_y = stuff->dstY; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + if (pDraw->type == DRAWABLE_PIXMAP) { + if (stuff->width > panoramiXdataPtr[j].width) + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + if (stuff->height > panoramiXdataPtr[j].height) + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + result = (* SavedProcVector[X_PutImage])(client); + } + return(result); +} + + +typedef struct _SrcParts{ + int x1, y1, x2, y2, width, ByteWidth; + char *buf; +} SrcPartsRec; + + +int PanoramiXGetImage(register ClientPtr client) +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int height, linesDone; + long widthBytesLine, length; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + long widthBytesLineProto, lengthProto; + char *tmpImage; +#endif + Mask plane; + char *pBuf; + xGetImageReply xgi; + int j, k, ScrNum; + DrawablePtr locDraw; + SrcPartsRec srcParts; + BoxRec SrcBox; + char *BufPtr, *PartPtr; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST(xGetImageReq); + + height = stuff->height; + REQUEST_SIZE_MATCH(xGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + ScrNum = 0; + if (stuff->drawable == PanoramiXWinRoot->info[0].id) { + for (j = 0; j <= (PanoramiXNumScreens - 1); j++) { + ScrNum = j; + VERIFY_DRAWABLE(pDraw, pPanoramiXWin->info[ScrNum].id, client); + if (stuff->x < panoramiXdataPtr[ScrNum].x && + stuff->y < panoramiXdataPtr[ScrNum].y ) + break; + } + } + if (pDraw->type == DRAWABLE_WINDOW) { + if (!((WindowPtr) pDraw)->realized /* Check for viewable */ + || pDraw->x + stuff->x < 0 /* Check for on screen */ + || pDraw->x + stuff->x + (int)stuff->width > PanoramiXPixWidth + || pDraw->y + stuff->y < 0 + || pDraw->y + stuff->y + height > PanoramiXPixHeight + || stuff->x < - wBorderWidth((WindowPtr)pDraw) /* Inside border */ + || stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int) pDraw->width + + panoramiXdataPtr[ScrNum].x + || stuff->y < -wBorderWidth((WindowPtr)pDraw) + || stuff->y + height > + wBorderWidth ((WindowPtr)pDraw) + (int) pDraw->height + + panoramiXdataPtr[ScrNum].y) + return(BadMatch); + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + xgi.visual = wVisual (((WindowPtr) pDraw)); + pPanoramiXWin = PanoramiXWinRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadWindow); + } else { + if (stuff->x < 0 || stuff->x + (int)stuff->width > pDraw->width + || stuff->y < 0 || stuff->y + height > pDraw->height) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if (stuff->format == ZPixmap) { + widthBytesLine = PixmapBytePad(stuff->width, pDraw->depth); + length = widthBytesLine * height; + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLineProto = PixmapBytePadProto(stuff->width, pDraw->depth); + lengthProto = widthBytesLineProto * height; +#endif + } else { + widthBytesLine = BitmapBytePad(stuff->width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(stuff->planeMask & (plane | (plane - 1))); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLineProto = BitmapBytePadProto(stuff->width); + lengthProto = widthBytesLineProto * height * + Ones(stuff->planeMask & (plane | (plane - 1))); +#endif + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + xgi.length = (lengthProto + 3) >> 2; +#else + xgi.length = (length + 3) >> 2; +#endif + + if (widthBytesLine == 0 || height == 0) { + linesPerBuf = 0; + } else if (widthBytesLine >= IMAGE_BUFSIZE) { + linesPerBuf = 1; + } else { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) { + + /* + * Have to make sure intermediate buffers don't need padding + */ + + while ((linesPerBuf > 1) + && (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1))) { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1)) { + linesPerBuf++; + length += widthBytesLine; + } + } + IF_RETURN((!(pBuf = (char *) ALLOCATE_LOCAL(length))), BadAlloc); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* + * Check for protocol/server padding differences + */ + + if (widthBytesLine != widthBytesLineProto) + if (!(tmpImage = (char *) ALLOCATE_LOCAL(length))) { + DEALLOCATE_LOCAL(pBuf); + return (BadAlloc); + } +#endif + + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + + if (linesPerBuf == 0) { + + /* + * Nothing to do + */ + + } else if (stuff->format == ZPixmap) { + linesDone = 0; + while (height - linesDone > 0) { + nlines = min(linesPerBuf, height - linesDone); + if (pDraw->type == DRAWABLE_WINDOW) { + SrcBox.x1 = pDraw->x + stuff->x; + SrcBox.y1 = pDraw->y + stuff->y + linesDone; + SrcBox.x2 = SrcBox.x1 + stuff->width; + SrcBox.y2 = SrcBox.y1 + nlines; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + + /* + * If it isn't even on this screen, just continue. + */ + + if ((SrcBox.x1 >= panoramiXdataPtr[j].x + panoramiXdataPtr[j].width) + || (SrcBox.x2 <= panoramiXdataPtr[j].x) + || (SrcBox.y1 >= panoramiXdataPtr[j].y+panoramiXdataPtr[j].height) + || (SrcBox.y2 <= panoramiXdataPtr[j].y)) + continue; + + srcParts.x1 = max(SrcBox.x1 - panoramiXdataPtr[j].x, 0); + srcParts.x2 = min(SrcBox.x2 - panoramiXdataPtr[j].x, + panoramiXdataPtr[j].width); + srcParts.y1 = max(SrcBox.y1 - panoramiXdataPtr[j].y, 0); + srcParts.y2 = min(SrcBox.y2 - panoramiXdataPtr[j].y, + panoramiXdataPtr[j].height); + srcParts.width = srcParts.x2 - srcParts.x1; + srcParts.ByteWidth = PixmapBytePad(srcParts.width,pDraw->depth); + srcParts.buf = (char *) Xalloc(nlines * srcParts.ByteWidth); + locDraw = (DrawablePtr) SecurityLookupIDByClass(client, + pPanoramiXWin->info[j].id, + RC_DRAWABLE, + SecurityReadAccess); + (*pDraw->pScreen->GetImage)(locDraw, + srcParts.x1 - locDraw->x, + srcParts.y1 - locDraw->y, + srcParts.width, + srcParts.y2 - srcParts.y1, + stuff->format, + (unsigned long)stuff->planeMask, + srcParts.buf); + BufPtr = pBuf + + srcParts.x1 - stuff->x - (pDraw->x - panoramiXdataPtr[j].x) + + widthBytesLine * (srcParts.y1 - stuff->y + - (pDraw->y + linesDone - panoramiXdataPtr[j].y)); + PartPtr = srcParts.buf; + for (k = (srcParts.y2 - srcParts.y1); k; k--) { + bcopy(PartPtr, BufPtr, srcParts.width); + BufPtr += widthBytesLine; + PartPtr += srcParts.ByteWidth; + } + Xfree(srcParts.buf); + } + } else { + (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y + linesDone, + stuff->width, nlines, stuff->format, + (unsigned long)stuff->planeMask, pBuf); + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* + * For 64-bit server, convert image to pad to 32 bits + */ + + if ( widthBytesLine != widthBytesLineProto ) { + register char * bufPtr, * protoPtr; + register int i; + + bzero(tmpImage,length); + + for (i = 0, bufPtr = pBuf, protoPtr = tmpImage; i < nlines; + bufPtr += widthBytesLine, protoPtr += widthBytesLineProto, + i++) + memmove(protoPtr,bufPtr,widthBytesLineProto); + + /* + * Note this is NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLineProto), tmpImage); + } else +#endif + { + + /* + * Note this is NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), pBuf); + } + linesDone += nlines; + } + } else { /* XYPixmap */ + for (; plane; plane >>= 1) { + if (stuff->planeMask & plane) { + linesDone = 0; + while (height - linesDone > 0) { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + stuff->x, + stuff->y + linesDone, + stuff->width, + nlines, + stuff->format, + (unsigned long)plane, + pBuf); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* + * For 64-bit server, convert image to pad to 32 bits + */ + + if (widthBytesLine != widthBytesLineProto) { + register char * bufPtr, * protoPtr; + register int i; + + bzero(tmpImage, length); + + for (i = 0,bufPtr = pBuf,protoPtr =tmpImage; i < nlines; + bufPtr += widthBytesLine, + protoPtr += widthBytesLineProto, + i++) + bcopy(bufPtr, protoPtr, widthBytesLineProto); + + /* + * Note: NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLineProto), tmpImage); + } else +#endif + { + + /* + * Note: NOT a call to WriteSwappedDataToClient, + * as we do NOT byte swap + */ + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), pBuf); + } + linesDone += nlines; + } + } + } + } + DEALLOCATE_LOCAL(pBuf); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if (widthBytesLine != widthBytesLineProto) + DEALLOCATE_LOCAL(tmpImage); +#endif + return (client->noClientException); +} + + +int +PanoramiXPolyText8(register ClientPtr client) +{ + int result, j; + + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + PixmapPtr pPixmap; + GC *pGC; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != pDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + stuff->x = orig_x; + stuff->y = orig_y; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + if (!j) + noPanoramiXExtension = TRUE; + result = (*SavedProcVector[X_PolyText8])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + return (result); +} + +int +PanoramiXPolyText16(register ClientPtr client) +{ + int result, j; + + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + GC *pGC; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + /* In the case of Multibuffering, we need to make sure the drawable + isn't really a pixmap associated to a drawable */ + if (!pPanoramiXWin && (stuff->drawable != pDraw->id)) { + pPanoramiXWin = PanoramiXPmapRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + } + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + stuff->x = orig_x; + stuff->y = orig_y; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + if (!j) + noPanoramiXExtension = TRUE; + result = (*SavedProcVector[X_PolyText16])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + return (result); +} + + + +int PanoramiXImageText8(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + GCPtr pGC; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + }else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + result = (*SavedProcVector[X_ImageText8])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXImageText16(ClientPtr client) +{ + int result, j; + PanoramiXWindow *pPanoramiXRoot; + PanoramiXWindow *pPanoramiXWin; + PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot; + DrawablePtr pDraw; + GCPtr pGC; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP) + ? PanoramiXPmapRoot : PanoramiXWinRoot; + pPanoramiXWin = pPanoramiXRoot; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable); + IF_RETURN(!pPanoramiXWin, BadDrawable); + PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc); + IF_RETURN(!pPanoramiXGC, BadGC); + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) { + stuff->drawable = pPanoramiXWin->info[j].id; + stuff->gc = pPanoramiXGC->info[j].id; + if (pPanoramiXWin == pPanoramiXRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + }else { + if ( (pDraw->type == DRAWABLE_PIXMAP) && + /* special case root window bitmap */ + (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x + + panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + } + result = (*SavedProcVector[X_ImageText16])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXCreateColormap(register ClientPtr client) +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + DepthPtr pDepth; + + REQUEST(xCreateColormapReq); + + int i, result; + int vid_index, class_index; + int this_vid_index, this_class_index, this_depth; + int j = 0; + VisualID orig_visual; + Colormap cmapID; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXCmap *localCmap; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + short VisualClass; + Bool ClassKnown; + Bool FoundIt = FALSE; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + mid = stuff->mid; + orig_visual = stuff->visual; + j = 0; + PANORAMIXFIND_ID(pPanoramiXWin, stuff->window); + if (pPanoramiXWin) { + localCmap = (PanoramiXCmap *)Xcalloc(sizeof(PanoramiXCmap)); + IF_RETURN(!localCmap, BadAlloc); + } else { + return BadWindow; + } + for (j = 0; j <= PanoramiXNumScreens - 1; j++) { + cmapID = j ? FakeClientID(client->index) : mid; + localCmap->info[j].id = cmapID; + } + localCmap->FreeMe = FALSE; + PANORAMIXFIND_LAST(pPanoramiXCmap, PanoramiXCmapRoot); + pPanoramiXCmap->next = localCmap; + + /* Use Screen 0 to get the matching Visual ID */ + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if ( stuff->visual != CopyFromParent) + { + /* Find the correct visual for screen 0 */ + for (class_index = 0; class_index < PanoramiXColorDepthTable[0].numVisuals; +class_index++) + { + for (j = 0; j < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index +].numDepths; j++ ) + { + pDepth = (DepthPtr) &pWin->drawable.pScreen->allowedDepths[j]; + for (vid_index = 0; vid_index < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[pDepth->depth].numVids; vid_index++) + { + if ( stuff->visual == PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[pDepth->depth].vid[vid_index] ) + { + this_class_index = class_index; + this_vid_index = vid_index; + this_depth = pDepth->depth; + FoundIt = TRUE; + break; + } + } + } + } + } + if (!pWin) + return(BadWindow); + pScreen = pWin->drawable.pScreen; + FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) { + stuff->mid = localCmap->info[j].id; + stuff->window = pPanoramiXWin->info[j].id; + /* Look for the matching visual class, and use its + visual id for creating this colormap. */ + if ( orig_visual != CopyFromParent && FoundIt ) + { + stuff->visual = PanoramiXColorDepthTable[j].panoramiXScreenMap[this_class_index].vmap[this_depth].vid[this_vid_index]; + } + result = (* SavedProcVector[X_CreateColormap])(client); + BREAK_IF(result != Success); + } + if (result != Success) { + pPanoramiXCmap->next = NULL ; + if (localCmap) + Xfree(localCmap); + } + return (result); +} + + +int PanoramiXFreeColormap(ClientPtr client) +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + PanoramiXCmap *pPanoramiXCmapback = NULL; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + + for (; pPanoramiXCmap && (pPanoramiXCmap->info[0].id != stuff->id); + pPanoramiXCmap = pPanoramiXCmap->next) + pPanoramiXCmapback = pPanoramiXCmap; + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->id = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_FreeColormap])(client); + BREAK_IF(result != Success); + } + if ((result == Success) && pPanoramiXCmapback && + pPanoramiXCmap && pPanoramiXCmap->FreeMe) { + pPanoramiXCmapback->next = pPanoramiXCmap->next; + Xfree(pPanoramiXCmap); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXInstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + + REQUEST_SIZE_MATCH(xResourceReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->id); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->id = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_InstallColormap])(client); + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXUninstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_SIZE_MATCH(xResourceReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->id); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->id = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_UninstallColormap])(client); + BREAK_IF(result != Success); + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXAllocColor(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + if (!pPanoramiXCmap){ + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColor])(client); + noPanoramiXExtension = FALSE; + }else { + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColor])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + } + return (result); +} + + +int PanoramiXAllocNamedColor(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocNamedColor])(client); + noPanoramiXExtension = FALSE; + BREAK_IF(result != Success); + } + return (result); +} + + +int PanoramiXAllocColorCells(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + if (!pPanoramiXCmap) { + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColorCells])(client); + noPanoramiXExtension = FALSE; + }else { + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + if (!j) + noPanoramiXExtension = TRUE; + result = (* SavedProcVector[X_AllocColorCells])(client); + noPanoramiXExtension = FALSE; + /* Because id's are eventually searched for in + some client list, we don't check for success + on fake id's last id will be real, we really + only care about results related to real id's + BREAK_IF(result != Success); + */ + } + } + return (result); +} + + +int PanoramiXFreeColors(register ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xFreeColorsReq); + + PanoramiXGC *pPanoramiXFreeGC; + PanoramiXGC *pPanoramiXFreeGCback = NULL; + PanoramiXWindow *pPanoramiXFreeWin; + PanoramiXWindow *pPanoramiXFreeWinback = NULL; + PanoramiXCmap *pPanoramiXFreeCmap; + PanoramiXCmap *pPanoramiXFreeCmapback = NULL; + PanoramiXPmap *pPanoramiXFreePmap; + PanoramiXPmap *pPanoramiXFreePmapback = NULL; + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + IF_RETURN(!pPanoramiXCmap, BadColor); + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_FreeColors])(client); + /* Because id's are eventually searched for in + some client list, we don't check for success + on fake id's last id will be real, we really + only care about results related to real id's */ + } + PANORAMIX_FREE(client); + return (result); +} + + +int PanoramiXStoreColors(ClientPtr client) +{ + int result, j; + PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap); + if (!pPanoramiXCmap) + result = (* SavedProcVector[X_StoreColors])(client); + else { + FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) { + stuff->cmap = pPanoramiXCmap->info[j].id; + result = (* SavedProcVector[X_StoreColors])(client); + BREAK_IF(result != Success); + } + } + return (result); +} diff --git a/Xext/sampleEVI.c b/Xext/sampleEVI.c new file mode 100644 index 000000000..43265a73d --- /dev/null +++ b/Xext/sampleEVI.c @@ -0,0 +1,97 @@ +/* $Xorg: sampleEVI.c,v 1.3 2000/08/17 19:47:58 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc. +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. +********************************************************/ +#include "X.h" +#include "Xproto.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "dix.h" +#define _XEVI_SERVER_ +#include "XEVIstr.h" +#include "EVIstruct.h" +#include "scrnintstr.h" +static int sampleGetVisualInfo( + VisualID32 *visual, + int n_visual, + xExtendedVisualInfo **evi_rn, + int *n_info_rn, + VisualID32 **conflict_rn, + int *n_conflict_rn) +{ + int max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens; + VisualID32 *temp_conflict; + xExtendedVisualInfo *evi; + int max_visuals = 0, max_sz_conflict, sz_conflict = 0; + register int visualI, scrI, sz_evi = 0, conflictI, n_conflict; + *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi); + if (!*evi_rn) + return BadAlloc; + for (scrI = 0; scrI < screenInfo.numScreens; scrI++) { + if (screenInfo.screens[scrI]->numVisuals > max_visuals) + max_visuals = screenInfo.screens[scrI]->numVisuals; + } + max_sz_conflict = n_visual * sz_VisualID32 * screenInfo.numScreens * max_visuals; + temp_conflict = (VisualID32 *)xalloc(max_sz_conflict); + if (!temp_conflict) { + xfree(*evi_rn); + return BadAlloc; + } + for (scrI = 0; scrI < screenInfo.numScreens; scrI++) { + for (visualI = 0; visualI < n_visual; visualI++) { + evi[sz_evi].core_visual_id = visual[visualI]; + evi[sz_evi].screen = scrI; + evi[sz_evi].level = 0; + evi[sz_evi].transparency_type = XEVI_TRANSPARENCY_NONE; + evi[sz_evi].transparency_value = 0; + evi[sz_evi].min_hw_colormaps = 1; + evi[sz_evi].max_hw_colormaps = 1; + evi[sz_evi].num_colormap_conflicts = n_conflict = 0; + for (conflictI = 0; conflictI < n_conflict; conflictI++) + temp_conflict[sz_conflict++] = visual[visualI]; + sz_evi++; + } + } + *conflict_rn = temp_conflict; + *n_conflict_rn = sz_conflict; + *n_info_rn = sz_evi; + return Success; +} +static void sampleFreeVisualInfo( + xExtendedVisualInfo *evi, + VisualID32 *conflict) +{ + if (evi) + xfree(evi); + if (conflict) + xfree(conflict); +} +EviPrivPtr eviDDXInit() +{ + static EviPrivRec eviPriv; + eviPriv.getVisualInfo = sampleGetVisualInfo; + eviPriv.freeVisualInfo = sampleFreeVisualInfo; + return &eviPriv; +} +void eviDDXReset() +{ +} diff --git a/Xext/security.c b/Xext/security.c new file mode 100644 index 000000000..c2db8f4dd --- /dev/null +++ b/Xext/security.c @@ -0,0 +1,1995 @@ +/* $Xorg: security.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "propertyst.h" +#define _SECURITY_SERVER +#include "securstr.h" +#include <assert.h> +#include <stdarg.h> +#ifdef LBX +#define _XLBX_SERVER_ +#include "XLbx.h" +extern unsigned char LbxReqCode; +#endif +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#include <stdio.h> /* for file reading operations */ +#include "Xatom.h" /* for XA_STRING */ + +#ifndef DEFAULTPOLICYFILE +# define DEFAULTPOLICYFILE NULL +#endif +#ifdef WIN32 +#include <X11/Xos.h> +#undef index +#endif + +static int SecurityErrorBase; /* first Security error number */ +static int SecurityEventBase; /* first Security event number */ + +CallbackListPtr SecurityValidateGroupCallback = NULL; /* see security.h */ + +RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */ + +static RESTYPE RTEventClient; + +/* Proc vectors for untrusted clients, swapped and unswapped versions. + * These are the same as the normal proc vectors except that extensions + * that haven't declared themselves secure will have ProcBadRequest plugged + * in for their major opcode dispatcher. This prevents untrusted clients + * from guessing extension major opcodes and using the extension even though + * the extension can't be listed or queried. + */ +int (*UntrustedProcVector[256])( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); +int (*SwappedUntrustedProcVector[256])( +#if NeedNestedPrototypes + ClientPtr /*client*/ +#endif +); + +extern int ProcBadRequest(); + + +/* SecurityAudit + * + * Arguments: + * format is the formatting string to be used to interpret the + * remaining arguments. + * + * Returns: nothing. + * + * Side Effects: + * Writes the message to the log file if security logging is on. + */ + +void +SecurityAudit(char *format, ...) +{ + va_list args; + + if (auditTrailLevel < SECURITY_AUDIT_LEVEL) + return; + AuditPrefix(format); + va_start(args, format); + VErrorF(format, args); + va_end(args); +} /* SecurityAudit */ + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +/* SecurityDeleteAuthorization + * + * Arguments: + * value is the authorization to delete. + * id is its resource ID. + * + * Returns: Success. + * + * Side Effects: + * Frees everything associated with the authorization. + */ + +static int +SecurityDeleteAuthorization(value, id) + pointer value; + XID id; +{ + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; + unsigned short name_len, data_len; + char *name, *data; + int status; + int i; + OtherClientsPtr pEventClient; + + /* Remove the auth using the os layer auth manager */ + + status = AuthorizationFromID(pAuth->id, &name_len, &name, + &data_len, &data); + assert(status); + status = RemoveAuthorization(name_len, name, data_len, data); + assert(status); + + /* free the auth timer if there is one */ + + if (pAuth->timer) TimerFree(pAuth->timer); + + /* send revoke events */ + + while (pEventClient = pAuth->eventClients) + { + /* send revocation event event */ + ClientPtr client = rClient(pEventClient); + + if (!client->clientGone) + { + xSecurityAuthorizationRevokedEvent are; + are.type = SecurityEventBase + XSecurityAuthorizationRevoked; + are.sequenceNumber = client->sequence; + are.authId = pAuth->id; + WriteEventsToClient(client, 1, (xEvent *)&are); + } + FreeResource(pEventClient->resource, RT_NONE); + } + + /* kill all clients using this auth */ + + for (i = 1; i<currentMaxClients; i++) + { + if (clients[i] && (clients[i]->authId == pAuth->id)) + CloseDownClient(clients[i]); + } + + SecurityAudit("revoked authorization ID %d\n", pAuth->id); + xfree(pAuth); + return Success; + +} /* SecurityDeleteAuthorization */ + + +/* resource delete function for RTEventClient */ +static int +SecurityDeleteAuthorizationEventClient(value, id) + pointer value; + XID id; +{ + OtherClientsPtr pEventClient, prev = NULL; + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; + + for (pEventClient = pAuth->eventClients; + pEventClient; + pEventClient = pEventClient->next) + { + if (pEventClient->resource == id) + { + if (prev) + prev->next = pEventClient->next; + else + pAuth->eventClients = pEventClient->next; + xfree(pEventClient); + return(Success); + } + prev = pEventClient; + } + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} /* SecurityDeleteAuthorizationEventClient */ + + +/* SecurityComputeAuthorizationTimeout + * + * Arguments: + * pAuth is the authorization for which we are computing the timeout + * seconds is the number of seconds we want to wait + * + * Returns: + * the number of milliseconds that the auth timer should be set to + * + * Side Effects: + * Sets pAuth->secondsRemaining to any "overflow" amount of time + * that didn't fit in 32 bits worth of milliseconds + */ + +static CARD32 +SecurityComputeAuthorizationTimeout(pAuth, seconds) + SecurityAuthorizationPtr pAuth; + unsigned int seconds; +{ + /* maxSecs is the number of full seconds that can be expressed in + * 32 bits worth of milliseconds + */ + CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND; + + if (seconds > maxSecs) + { /* only come here if we want to wait more than 49 days */ + pAuth->secondsRemaining = seconds - maxSecs; + return maxSecs * MILLI_PER_SECOND; + } + else + { /* by far the common case */ + pAuth->secondsRemaining = 0; + return seconds * MILLI_PER_SECOND; + } +} /* SecurityStartAuthorizationTimer */ + +/* SecurityAuthorizationExpired + * + * This function is passed as an argument to TimerSet and gets called from + * the timer manager in the os layer when its time is up. + * + * Arguments: + * timer is the timer for this authorization. + * time is the current time. + * pval is the authorization whose time is up. + * + * Returns: + * A new time delay in milliseconds if the timer should wait some + * more, else zero. + * + * Side Effects: + * Frees the authorization resource if the timeout period is really + * over, otherwise recomputes pAuth->secondsRemaining. + */ + +static CARD32 +SecurityAuthorizationExpired(timer, time, pval) + OsTimerPtr timer; + CARD32 time; + pointer pval; +{ + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval; + + assert(pAuth->timer == timer); + + if (pAuth->secondsRemaining) + { + return SecurityComputeAuthorizationTimeout(pAuth, + pAuth->secondsRemaining); + } + else + { + FreeResource(pAuth->id, RT_NONE); + return 0; + } +} /* SecurityAuthorizationExpired */ + +/* SecurityStartAuthorizationTimer + * + * Arguments: + * pAuth is the authorization whose timer should be started. + * + * Returns: nothing. + * + * Side Effects: + * A timer is started, set to expire after the timeout period for + * this authorization. When it expires, the function + * SecurityAuthorizationExpired will be called. + */ + +static void +SecurityStartAuthorizationTimer(pAuth) + SecurityAuthorizationPtr pAuth; +{ + pAuth->timer = TimerSet(pAuth->timer, 0, + SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout), + SecurityAuthorizationExpired, pAuth); +} /* SecurityStartAuthorizationTimer */ + + +/* Proc functions all take a client argument, execute the request in + * client->requestBuffer, and return a protocol error status. + */ + +static int +ProcSecurityQueryVersion(client) + ClientPtr client; +{ + REQUEST(xSecurityQueryVersionReq); + xSecurityQueryVersionReply rep; + + /* paranoia: this "can't happen" because this extension is hidden + * from untrusted clients, but just in case... + */ + if (client->trustLevel != XSecurityClientTrusted) + return BadRequest; + + REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.majorVersion = SECURITY_MAJOR_VERSION; + rep.minorVersion = SECURITY_MINOR_VERSION; + if(client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), + (char *)&rep); + return (client->noClientException); +} /* ProcSecurityQueryVersion */ + + +static int +SecurityEventSelectForAuthorization(pAuth, client, mask) + SecurityAuthorizationPtr pAuth; + ClientPtr client; + Mask mask; +{ + OtherClients *pEventClient; + + for (pEventClient = pAuth->eventClients; + pEventClient; + pEventClient = pEventClient->next) + { + if (SameClient(pEventClient, client)) + { + if (mask == 0) + FreeResource(pEventClient->resource, RT_NONE); + else + pEventClient->mask = mask; + return Success; + } + } + + pEventClient = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!pEventClient) + return BadAlloc; + pEventClient->mask = mask; + pEventClient->resource = FakeClientID(client->index); + pEventClient->next = pAuth->eventClients; + if (!AddResource(pEventClient->resource, RTEventClient, + (pointer)pAuth)) + { + xfree(pEventClient); + return BadAlloc; + } + pAuth->eventClients = pEventClient; + + return Success; +} /* SecurityEventSelectForAuthorization */ + + +static int +ProcSecurityGenerateAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityGenerateAuthorizationReq); + int len; /* request length in CARD32s*/ + Bool removeAuth = FALSE; /* if bailout, call RemoveAuthorization? */ + SecurityAuthorizationPtr pAuth = NULL; /* auth we are creating */ + int err; /* error to return from this function */ + int status; /* return value from os functions */ + XID authId; /* authorization ID assigned by os layer */ + xSecurityGenerateAuthorizationReply rep; /* reply struct */ + unsigned int trustLevel; /* trust level of new auth */ + XID group; /* group of new auth */ + CARD32 timeout; /* timeout of new auth */ + CARD32 *values; /* list of supplied attributes */ + char *protoname; /* auth proto name sent in request */ + char *protodata; /* auth proto data sent in request */ + unsigned int authdata_len; /* # bytes of generated auth data */ + char *pAuthdata; /* generated auth data */ + Mask eventMask; /* what events on this auth does client want */ + + /* paranoia: this "can't happen" because this extension is hidden + * from untrusted clients, but just in case... + */ + if (client->trustLevel != XSecurityClientTrusted) + return BadRequest; + + /* check request length */ + + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + len = SIZEOF(xSecurityGenerateAuthorizationReq) >> 2; + len += (stuff->nbytesAuthProto + (unsigned)3) >> 2; + len += (stuff->nbytesAuthData + (unsigned)3) >> 2; + values = ((CARD32 *)stuff) + len; + len += Ones(stuff->valueMask); + if (client->req_len != len) + return BadLength; + + /* check valuemask */ + if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes) + { + client->errorValue = stuff->valueMask; + return BadValue; + } + + /* check timeout */ + timeout = 60; + if (stuff->valueMask & XSecurityTimeout) + { + timeout = *values++; + } + + /* check trustLevel */ + trustLevel = XSecurityClientUntrusted; + if (stuff->valueMask & XSecurityTrustLevel) + { + trustLevel = *values++; + if (trustLevel != XSecurityClientTrusted && + trustLevel != XSecurityClientUntrusted) + { + client->errorValue = trustLevel; + return BadValue; + } + } + + /* check group */ + group = None; + if (stuff->valueMask & XSecurityGroup) + { + group = *values++; + if (SecurityValidateGroupCallback) + { + SecurityValidateGroupInfoRec vgi; + vgi.group = group; + vgi.valid = FALSE; + CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi); + + /* if nobody said they recognized it, it's an error */ + + if (!vgi.valid) + { + client->errorValue = group; + return BadValue; + } + } + } + + /* check event mask */ + eventMask = 0; + if (stuff->valueMask & XSecurityEventMask) + { + eventMask = *values++; + if (eventMask & ~XSecurityAllEventMasks) + { + client->errorValue = eventMask; + return BadValue; + } + } + + protoname = (char *)&stuff[1]; + protodata = protoname + ((stuff->nbytesAuthProto + (unsigned)3) >> 2); + + /* call os layer to generate the authorization */ + + authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname, + stuff->nbytesAuthData, protodata, + &authdata_len, &pAuthdata); + if ((XID) ~0L == authId) + { + err = SecurityErrorBase + XSecurityBadAuthorizationProtocol; + goto bailout; + } + + /* now that we've added the auth, remember to remove it if we have to + * abort the request for some reason (like allocation failure) + */ + removeAuth = TRUE; + + /* associate additional information with this auth ID */ + + pAuth = (SecurityAuthorizationPtr)xalloc(sizeof(SecurityAuthorizationRec)); + if (!pAuth) + { + err = BadAlloc; + goto bailout; + } + + /* fill in the auth fields */ + + pAuth->id = authId; + pAuth->timeout = timeout; + pAuth->group = group; + pAuth->trustLevel = trustLevel; + pAuth->refcnt = 0; /* the auth was just created; nobody's using it yet */ + pAuth->secondsRemaining = 0; + pAuth->timer = NULL; + pAuth->eventClients = NULL; + + /* handle event selection */ + if (eventMask) + { + err = SecurityEventSelectForAuthorization(pAuth, client, eventMask); + if (err != Success) + goto bailout; + } + + if (!AddResource(authId, SecurityAuthorizationResType, pAuth)) + { + err = BadAlloc; + goto bailout; + } + + /* start the timer ticking */ + + if (pAuth->timeout != 0) + SecurityStartAuthorizationTimer(pAuth); + + /* tell client the auth id and data */ + + rep.type = X_Reply; + rep.length = (authdata_len + 3) >> 2; + rep.sequenceNumber = client->sequence; + rep.authId = authId; + rep.dataLength = authdata_len; + + if (client->swapped) + { + register char n; + swapl(&rep.length, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.authId, n); + swaps(&rep.dataLength, n); + } + + WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply), + (char *)&rep); + WriteToClient(client, authdata_len, pAuthdata); + + SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n", + client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout, + pAuth->group, eventMask); + + /* the request succeeded; don't call RemoveAuthorization or free pAuth */ + + removeAuth = FALSE; + pAuth = NULL; + err = client->noClientException; + +bailout: + if (removeAuth) + RemoveAuthorization(stuff->nbytesAuthProto, protoname, + authdata_len, pAuthdata); + if (pAuth) xfree(pAuth); + return err; + +} /* ProcSecurityGenerateAuthorization */ + +static int +ProcSecurityRevokeAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityRevokeAuthorizationReq); + SecurityAuthorizationPtr pAuth; + + /* paranoia: this "can't happen" because this extension is hidden + * from untrusted clients, but just in case... + */ + if (client->trustLevel != XSecurityClientTrusted) + return BadRequest; + + REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); + + pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client, + stuff->authId, SecurityAuthorizationResType, SecurityDestroyAccess); + if (!pAuth) + return SecurityErrorBase + XSecurityBadAuthorization; + + FreeResource(stuff->authId, RT_NONE); + return Success; +} /* ProcSecurityRevokeAuthorization */ + + +static int +ProcSecurityDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SecurityQueryVersion: + return ProcSecurityQueryVersion(client); + case X_SecurityGenerateAuthorization: + return ProcSecurityGenerateAuthorization(client); + case X_SecurityRevokeAuthorization: + return ProcSecurityRevokeAuthorization(client); + default: + return BadRequest; + } +} /* ProcSecurityDispatch */ + +static int +SProcSecurityQueryVersion(client) + ClientPtr client; +{ + REQUEST(xSecurityQueryVersionReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion,n); + return ProcSecurityQueryVersion(client); +} /* SProcSecurityQueryVersion */ + + +static int +SProcSecurityGenerateAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityGenerateAuthorizationReq); + register char n; + CARD32 *values; + unsigned long nvalues; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + swaps(&stuff->nbytesAuthProto, n); + swaps(&stuff->nbytesAuthData, n); + swapl(&stuff->valueMask, n); + values = (CARD32 *)(&stuff[1]) + + ((stuff->nbytesAuthProto + (unsigned)3) >> 2) + + ((stuff->nbytesAuthData + (unsigned)3) >> 2); + nvalues = (((CARD32 *)stuff) + stuff->length) - values; + SwapLongs(values, nvalues); + return ProcSecurityGenerateAuthorization(client); +} /* SProcSecurityGenerateAuthorization */ + + +static int +SProcSecurityRevokeAuthorization(client) + ClientPtr client; +{ + REQUEST(xSecurityRevokeAuthorizationReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); + swapl(&stuff->authId, n); + return ProcSecurityRevokeAuthorization(client); +} /* SProcSecurityRevokeAuthorization */ + + +static int +SProcSecurityDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SecurityQueryVersion: + return SProcSecurityQueryVersion(client); + case X_SecurityGenerateAuthorization: + return SProcSecurityGenerateAuthorization(client); + case X_SecurityRevokeAuthorization: + return SProcSecurityRevokeAuthorization(client); + default: + return BadRequest; + } +} /* SProcSecurityDispatch */ + +static void +SwapSecurityAuthorizationRevokedEvent(from, to) + xSecurityAuthorizationRevokedEvent *from, *to; +{ + to->type = from->type; + to->detail = from->detail; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->authId, to->authId); +} + +/* SecurityDetermineEventPropogationLimits + * + * This is a helper function for SecurityCheckDeviceAccess. + * + * Arguments: + * dev is the device for which the starting and stopping windows for + * event propogation should be determined. + * The values pointed to by ppWin and ppStopWin are not used. + * + * Returns: + * ppWin is filled in with a pointer to the window at which event + * propogation for the given device should start given the current + * state of the server (pointer position, window layout, etc.) + * ppStopWin is filled in with the window at which event propogation + * should stop; events should not go to ppStopWin. + * + * Side Effects: none. + */ + +static void +SecurityDetermineEventPropogationLimits(dev, ppWin, ppStopWin) + DeviceIntPtr dev; + WindowPtr *ppWin; + WindowPtr *ppStopWin; +{ + WindowPtr pFocusWin = dev->focus ? dev->focus->win : NoneWin; + + if (pFocusWin == NoneWin) + { /* no focus -- events don't go anywhere */ + *ppWin = *ppStopWin = NULL; + return; + } + + if (pFocusWin == PointerRootWin) + { /* focus follows the pointer */ + *ppWin = GetSpriteWindow(); + *ppStopWin = NULL; /* propogate all the way to the root */ + } + else + { /* a real window is set for the focus */ + WindowPtr pSpriteWin = GetSpriteWindow(); + *ppStopWin = pFocusWin->parent; /* don't go past the focus window */ + + /* if the pointer is in a subwindow of the focus window, start + * at that subwindow, else start at the focus window itself + */ + if (IsParent(pFocusWin, pSpriteWin)) + *ppWin = pSpriteWin; + else *ppWin = pFocusWin; + } +} /* SecurityDetermineEventPropogationLimits */ + + +/* SecurityCheckDeviceAccess + * + * Arguments: + * client is the client attempting to access a device. + * dev is the device being accessed. + * fromRequest is TRUE if the device access is a direct result of + * the client executing some request and FALSE if it is a + * result of the server trying to send an event (e.g. KeymapNotify) + * to the client. + * Returns: + * TRUE if the device access should be allowed, else FALSE. + * + * Side Effects: + * An audit message is generated if access is denied. + */ + +Bool +SecurityCheckDeviceAccess(client, dev, fromRequest) + ClientPtr client; + DeviceIntPtr dev; + Bool fromRequest; +{ + WindowPtr pWin, pStopWin; + Bool untrusted_got_event; + Bool found_event_window; + Mask eventmask; + int reqtype; + + /* trusted clients always allowed to do anything */ + if (client->trustLevel == XSecurityClientTrusted) + return TRUE; + + /* device security other than keyboard is not implemented yet */ + if (dev != inputInfo.keyboard) + return TRUE; + + /* some untrusted client wants access */ + + if (fromRequest) + { + reqtype = ((xReq *)client->requestBuffer)->reqType; + switch (reqtype) + { + /* never allow these */ + case X_ChangeKeyboardMapping: + case X_ChangeKeyboardControl: + case X_SetModifierMapping: + SecurityAudit("client %d attempted request %d\n", + client->index, reqtype); + return FALSE; + default: + break; + } + } + + untrusted_got_event = FALSE; + found_event_window = FALSE; + + if (dev->grab) + { + untrusted_got_event = + ((rClient(dev->grab))->trustLevel != XSecurityClientTrusted); + } + else + { + SecurityDetermineEventPropogationLimits(dev, &pWin, &pStopWin); + + eventmask = KeyPressMask | KeyReleaseMask; + while ( (pWin != pStopWin) && !found_event_window) + { + OtherClients *other; + + if (pWin->eventMask & eventmask) + { + found_event_window = TRUE; + client = wClient(pWin); + if (client->trustLevel != XSecurityClientTrusted) + { + untrusted_got_event = TRUE; + } + } + if (wOtherEventMasks(pWin) & eventmask) + { + found_event_window = TRUE; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & eventmask) + { + client = rClient(other); + if (client->trustLevel != XSecurityClientTrusted) + { + untrusted_got_event = TRUE; + break; + } + } + } + } + if (wDontPropagateMask(pWin) & eventmask) + break; + pWin = pWin->parent; + } /* while propogating the event */ + } + + /* allow access by untrusted clients only if an event would have gone + * to an untrusted client + */ + + if (!untrusted_got_event) + { + char *devname = dev->name; + if (!devname) devname = "unnamed"; + if (fromRequest) + SecurityAudit("client %d attempted request %d device %d (%s)\n", + client->index, reqtype, dev->id, devname); + else + SecurityAudit("client %d attempted to access device %d (%s)\n", + client->index, dev->id, devname); + } + return untrusted_got_event; +} /* SecurityCheckDeviceAccess */ + + + +/* SecurityAuditResourceIDAccess + * + * Arguments: + * client is the client doing the resource access. + * id is the resource id. + * + * Returns: NULL + * + * Side Effects: + * An audit message is generated with details of the denied + * resource access. + */ + +static pointer +SecurityAuditResourceIDAccess(client, id) + ClientPtr client; + XID id; +{ + int cid = CLIENT_ID(id); + int reqtype = ((xReq *)client->requestBuffer)->reqType; + switch (reqtype) + { + case X_ChangeProperty: + case X_DeleteProperty: + case X_GetProperty: + { + xChangePropertyReq *req = + (xChangePropertyReq *)client->requestBuffer; + int propertyatom = req->property; + char *propertyname = NameForAtom(propertyatom); + + SecurityAudit("client %d attempted request %d with window 0x%x property %s of client %d\n", + client->index, reqtype, id, propertyname, cid); + break; + } + default: + { + SecurityAudit("client %d attempted request %d with resource 0x%x of client %d\n", + client->index, reqtype, id, cid); + break; + } + } + return NULL; +} /* SecurityAuditResourceIDAccess */ + + +/* SecurityCheckResourceIDAccess + * + * This function gets plugged into client->CheckAccess and is called from + * SecurityLookupIDByType/Class to determine if the client can access the + * resource. + * + * Arguments: + * client is the client doing the resource access. + * id is the resource id. + * rtype is its type or class. + * access_mode represents the intended use of the resource; see + * resource.h. + * rval is a pointer to the resource structure for this resource. + * + * Returns: + * If access is granted, the value of rval that was passed in, else NULL. + * + * Side Effects: + * Disallowed resource accesses are audited. + */ + +static pointer +SecurityCheckResourceIDAccess(client, id, rtype, access_mode, rval) + ClientPtr client; + XID id; + RESTYPE rtype; + Mask access_mode; + pointer rval; +{ + int cid = CLIENT_ID(id); + int reqtype = ((xReq *)client->requestBuffer)->reqType; + + if (SecurityUnknownAccess == access_mode) + return rval; /* for compatibility, we have to allow access */ + + switch (reqtype) + { /* these are always allowed */ + case X_QueryTree: + case X_TranslateCoords: + case X_GetGeometry: + /* property access is controlled in SecurityCheckPropertyAccess */ + case X_GetProperty: + case X_ChangeProperty: + case X_DeleteProperty: + case X_RotateProperties: + case X_ListProperties: + return rval; + default: + break; + } + + if (cid != 0) + { /* not a server-owned resource */ + /* + * The following 'if' restricts clients to only access resources at + * the same trustLevel. Since there are currently only two trust levels, + * and trusted clients never call this function, this degenerates into + * saying that untrusted clients can only access resources of other + * untrusted clients. One way to add the notion of groups would be to + * allow values other than Trusted (0) and Untrusted (1) for this field. + * Clients at the same trust level would be able to use each other's + * resources, but not those of clients at other trust levels. I haven't + * tried it, but this probably mostly works already. The obvious + * competing alternative for grouping clients for security purposes is to + * use app groups. dpw + */ + if (client->trustLevel == clients[cid]->trustLevel +#ifdef XAPPGROUP + || (RT_COLORMAP == rtype && + XagDefaultColormap (client) == (Colormap) id) +#endif + ) + return rval; + else + return SecurityAuditResourceIDAccess(client, id); + } + else /* server-owned resource - probably a default colormap or root window */ + { + if (RT_WINDOW == rtype || RC_DRAWABLE == rtype) + { + switch (reqtype) + { /* the following operations are allowed on root windows */ + case X_CreatePixmap: + case X_CreateGC: + case X_CreateWindow: + case X_CreateColormap: + case X_ListProperties: + case X_GrabPointer: + case X_UngrabButton: + case X_QueryBestSize: + case X_GetWindowAttributes: + break; + case X_SendEvent: + { /* see if it is an event specified by the ICCCM */ + xSendEventReq *req = (xSendEventReq *) + (client->requestBuffer); + if (req->propagate == xTrue + || + (req->eventMask != ColormapChangeMask && + req->eventMask != StructureNotifyMask && + req->eventMask != + (SubstructureRedirectMask|SubstructureNotifyMask) + ) + || + (req->event.u.u.type != UnmapNotify && + req->event.u.u.type != ConfigureRequest && + req->event.u.u.type != ClientMessage + ) + ) + { /* not an ICCCM event */ + return SecurityAuditResourceIDAccess(client, id); + } + break; + } /* case X_SendEvent on root */ + + case X_ChangeWindowAttributes: + { /* Allow selection of PropertyNotify and StructureNotify + * events on the root. + */ + xChangeWindowAttributesReq *req = + (xChangeWindowAttributesReq *)(client->requestBuffer); + if (req->valueMask == CWEventMask) + { + CARD32 value = *((CARD32 *)(req + 1)); + if ( (value & + ~(PropertyChangeMask|StructureNotifyMask)) == 0) + break; + } + return SecurityAuditResourceIDAccess(client, id); + } /* case X_ChangeWindowAttributes on root */ + + default: + { +#ifdef LBX + /* XXX really need per extension dispatching */ + if (reqtype == LbxReqCode) { + switch (((xReq *)client->requestBuffer)->data) { + case X_LbxGetProperty: + case X_LbxChangeProperty: + return rval; + default: + break; + } + } +#endif + /* others not allowed */ + return SecurityAuditResourceIDAccess(client, id); + } + } + } /* end server-owned window or drawable */ + else if (SecurityAuthorizationResType == rtype) + { + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval; + if (pAuth->trustLevel != client->trustLevel) + return SecurityAuditResourceIDAccess(client, id); + } + else if (RT_COLORMAP != rtype) + { /* don't allow anything else besides colormaps */ + return SecurityAuditResourceIDAccess(client, id); + } + } + return rval; +} /* SecurityCheckResourceIDAccess */ + + +/* SecurityClientStateCallback + * + * Arguments: + * pcbl is &ClientStateCallback. + * nullata is NULL. + * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) + * which contains information about client state changes. + * + * Returns: nothing. + * + * Side Effects: + * + * If a new client is connecting, its authorization ID is copied to + * client->authID. If this is a generated authorization, its reference + * count is bumped, its timer is cancelled if it was running, and its + * trustlevel is copied to client->trustLevel. + * + * If a client is disconnecting and the client was using a generated + * authorization, the authorization's reference count is decremented, and + * if it is now zero, the timer for this authorization is started. + */ + +static void +SecurityClientStateCallback(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + NewClientInfoRec *pci = (NewClientInfoRec *)calldata; + ClientPtr client = pci->client; + + switch (client->clientState) + { + case ClientStateRunning: + { + XID authId = AuthorizationIDOfClient(client); + SecurityAuthorizationPtr pAuth; + + client->authId = authId; + pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, + SecurityAuthorizationResType); + if (pAuth) + { /* it is a generated authorization */ + pAuth->refcnt++; + if (pAuth->refcnt == 1) + { + if (pAuth->timer) TimerCancel(pAuth->timer); + } + client->trustLevel = pAuth->trustLevel; + if (client->trustLevel != XSecurityClientTrusted) + { + client->CheckAccess = SecurityCheckResourceIDAccess; + client->requestVector = client->swapped ? + SwappedUntrustedProcVector : UntrustedProcVector; + } + } + break; + } + case ClientStateGone: + case ClientStateRetained: /* client disconnected */ + { + XID authId = client->authId; + SecurityAuthorizationPtr pAuth; + + pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, + SecurityAuthorizationResType); + if (pAuth) + { /* it is a generated authorization */ + pAuth->refcnt--; + if (pAuth->refcnt == 0) + { + SecurityStartAuthorizationTimer(pAuth); + } + } + break; + } + default: break; + } +} /* SecurityClientStateCallback */ + +#ifdef LBX +Bool +SecuritySameLevel(client, authId) + ClientPtr client; + XID authId; +{ + SecurityAuthorizationPtr pAuth; + + pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, + SecurityAuthorizationResType); + if (pAuth) + return client->trustLevel == pAuth->trustLevel; + return client->trustLevel == XSecurityClientTrusted; +} +#endif + +/* SecurityCensorImage + * + * Called after pScreen->GetImage to prevent pieces or trusted windows from + * being returned in image data from an untrusted window. + * + * Arguments: + * client is the client doing the GetImage. + * pVisibleRegion is the visible region of the window. + * widthBytesLine is the width in bytes of one horizontal line in pBuf. + * pDraw is the source window. + * x, y, w, h is the rectangle of image data from pDraw in pBuf. + * format is the format of the image data in pBuf: ZPixmap or XYPixmap. + * pBuf is the image data. + * + * Returns: nothing. + * + * Side Effects: + * Any part of the rectangle (x, y, w, h) that is outside the visible + * region of the window will be destroyed (overwritten) in pBuf. + */ +void +SecurityCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h, + format, pBuf) + ClientPtr client; + RegionPtr pVisibleRegion; + long widthBytesLine; + DrawablePtr pDraw; + int x, y, w, h; + unsigned int format; + char * pBuf; +{ + RegionRec imageRegion; /* region representing x,y,w,h */ + RegionRec censorRegion; /* region to obliterate */ + BoxRec imageBox; + int nRects; + + imageBox.x1 = x; + imageBox.y1 = y; + imageBox.x2 = x + w; + imageBox.y2 = y + h; + REGION_INIT(pScreen, &imageRegion, &imageBox, 1); + REGION_INIT(pScreen, &censorRegion, NullBox, 0); + + /* censorRegion = imageRegion - visibleRegion */ + REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion); + nRects = REGION_NUM_RECTS(&censorRegion); + if (nRects > 0) + { /* we have something to censor */ + GCPtr pScratchGC = NULL; + PixmapPtr pPix = NULL; + xRectangle *pRects = NULL; + Bool failed = FALSE; + int depth = 1; + int bitsPerPixel = 1; + int i; + BoxPtr pBox; + + /* convert region to list-of-rectangles for PolyFillRect */ + + pRects = (xRectangle *)ALLOCATE_LOCAL(nRects * sizeof(xRectangle *)); + if (!pRects) + { + failed = TRUE; + goto failSafe; + } + for (pBox = REGION_RECTS(&censorRegion), i = 0; + i < nRects; + i++, pBox++) + { + pRects[i].x = pBox->x1; + pRects[i].y = pBox->y1 - imageBox.y1; + pRects[i].width = pBox->x2 - pBox->x1; + pRects[i].height = pBox->y2 - pBox->y1; + } + + /* use pBuf as a fake pixmap */ + + if (format == ZPixmap) + { + depth = pDraw->depth; + bitsPerPixel = pDraw->bitsPerPixel; + } + + pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, + depth, bitsPerPixel, + widthBytesLine, (pointer)pBuf); + if (!pPix) + { + failed = TRUE; + goto failSafe; + } + + pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); + if (!pScratchGC) + { + failed = TRUE; + goto failSafe; + } + + ValidateGC(&pPix->drawable, pScratchGC); + (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, + pScratchGC, nRects, pRects); + + failSafe: + if (failed) + { + /* Censoring was not completed above. To be safe, wipe out + * all the image data so that nothing trusted gets out. + */ + bzero(pBuf, (int)(widthBytesLine * h)); + } + if (pRects) DEALLOCATE_LOCAL(pRects); + if (pScratchGC) FreeScratchGC(pScratchGC); + if (pPix) FreeScratchPixmapHeader(pPix); + } + REGION_UNINIT(pScreen, &imageRegion); + REGION_UNINIT(pScreen, &censorRegion); +} /* SecurityCensorImage */ + +/**********************************************************************/ + +typedef struct _PropertyAccessRec { + ATOM name; + ATOM mustHaveProperty; + char *mustHaveValue; + char windowRestriction; +#define SecurityAnyWindow 0 +#define SecurityRootWindow 1 +#define SecurityWindowWithProperty 2 + char readAction; + char writeAction; + char destroyAction; + struct _PropertyAccessRec *next; +} PropertyAccessRec, *PropertyAccessPtr; + +static PropertyAccessPtr PropertyAccessList = NULL; +static char SecurityDefaultAction = SecurityErrorOperation; +static char *SecurityPolicyFile = DEFAULTPOLICYFILE; +static ATOM SecurityMaxPropertyName = 0; + +static char *SecurityKeywords[] = { +#define SecurityKeywordComment 0 + "#", +#define SecurityKeywordProperty 1 + "property", +#define SecurityKeywordSitePolicy 2 + "sitepolicy", +#define SecurityKeywordRoot 3 + "root", +#define SecurityKeywordAny 4 + "any" +}; + +#define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *)) + +#undef PROPDEBUG +/*#define PROPDEBUG 1*/ + +static void +SecurityFreePropertyAccessList() +{ + while (PropertyAccessList) + { + PropertyAccessPtr freeit = PropertyAccessList; + PropertyAccessList = PropertyAccessList->next; + xfree(freeit); + } +} /* SecurityFreePropertyAccessList */ + + +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') ) + +static char * +SecuritySkipWhitespace(p) + char *p; +{ + while (SecurityIsWhitespace(*p)) + p++; + return p; +} /* SecuritySkipWhitespace */ + + +static char * +SecurityParseString(rest) + char **rest; +{ + char *startOfString; + char *s = *rest; + char endChar = 0; + + s = SecuritySkipWhitespace(s); + + if (*s == '"' || *s == '\'') + { + endChar = *s++; + startOfString = s; + while (*s && (*s != endChar)) + s++; + } + else + { + startOfString = s; + while (*s && !SecurityIsWhitespace(*s)) + s++; + } + if (*s) + { + *s = '\0'; + *rest = s + 1; + return startOfString; + } + else + { + *rest = s; + return (endChar) ? NULL : startOfString; + } +} /* SecurityParseString */ + + +static int +SecurityParseKeyword(p) + char **p; +{ + int i; + char *s = *p; + s = SecuritySkipWhitespace(s); + for (i = 0; i < NUMKEYWORDS; i++) + { + int len = strlen(SecurityKeywords[i]); + if (strncmp(s, SecurityKeywords[i], len) == 0) + { + *p = s + len; + return (i); + } + } + *p = s; + return -1; +} /* SecurityParseKeyword */ + + +static Bool +SecurityParsePropertyAccessRule(p) + char *p; +{ + char *propname; + char c; + char action = SecurityDefaultAction; + char readAction, writeAction, destroyAction; + PropertyAccessPtr pacl, prev, cur; + ATOM atom; + char *mustHaveProperty = NULL; + char *mustHaveValue = NULL; + Bool invalid; + char windowRestriction; + int size; + int keyword; + + /* get property name */ + propname = SecurityParseString(&p); + if (!propname || (strlen(propname) == 0)) + return FALSE; + + /* get window on which property must reside for rule to apply */ + + keyword = SecurityParseKeyword(&p); + if (keyword == SecurityKeywordRoot) + windowRestriction = SecurityRootWindow; + else if (keyword == SecurityKeywordAny) + windowRestriction = SecurityAnyWindow; + else /* not root or any, must be a property name */ + { + mustHaveProperty = SecurityParseString(&p); + if (!mustHaveProperty || (strlen(mustHaveProperty) == 0)) + return FALSE; + windowRestriction = SecurityWindowWithProperty; + p = SecuritySkipWhitespace(p); + if (*p == '=') + { /* property value is specified too */ + p++; /* skip over '=' */ + mustHaveValue = SecurityParseString(&p); + if (!mustHaveValue) + return FALSE; + } + } + + /* get operations and actions */ + + invalid = FALSE; + readAction = writeAction = destroyAction = SecurityDefaultAction; + while ( (c = *p++) && !invalid) + { + switch (c) + { + case 'i': action = SecurityIgnoreOperation; break; + case 'a': action = SecurityAllowOperation; break; + case 'e': action = SecurityErrorOperation; break; + + case 'r': readAction = action; break; + case 'w': writeAction = action; break; + case 'd': destroyAction = action; break; + + default : + if (!SecurityIsWhitespace(c)) + invalid = TRUE; + break; + } + } + if (invalid) + return FALSE; + + /* We've successfully collected all the information needed for this + * property access rule. Now record it in a PropertyAccessRec. + */ + size = sizeof(PropertyAccessRec); + + /* If there is a property value string, allocate space for it + * right after the PropertyAccessRec. + */ + if (mustHaveValue) + size += strlen(mustHaveValue) + 1; + pacl = (PropertyAccessPtr)Xalloc(size); + if (!pacl) + return FALSE; + + pacl->name = MakeAtom(propname, strlen(propname), TRUE); + if (pacl->name == BAD_RESOURCE) + { + Xfree(pacl); + return FALSE; + } + if (mustHaveProperty) + { + pacl->mustHaveProperty = MakeAtom(mustHaveProperty, + strlen(mustHaveProperty), TRUE); + if (pacl->mustHaveProperty == BAD_RESOURCE) + { + Xfree(pacl); + return FALSE; + } + } + else + pacl->mustHaveProperty = 0; + + if (mustHaveValue) + { + pacl->mustHaveValue = (char *)(pacl + 1); + strcpy(pacl->mustHaveValue, mustHaveValue); + } + else + pacl->mustHaveValue = NULL; + + SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name); + + pacl->windowRestriction = windowRestriction; + pacl->readAction = readAction; + pacl->writeAction = writeAction; + pacl->destroyAction = destroyAction; + + /* link the new rule into the list of rules in order of increasing + * property name (atom) value to make searching easier + */ + + for (prev = NULL, cur = PropertyAccessList; + cur && cur->name <= pacl->name; + prev = cur, cur = cur->next) + ; + if (!prev) + { + pacl->next = cur; + PropertyAccessList = pacl; + } + else + { + prev->next = pacl; + pacl->next = cur; + } + return TRUE; +} /* SecurityParsePropertyAccessRule */ + +static char **SecurityPolicyStrings = NULL; +static int nSecurityPolicyStrings = 0; + +static Bool +SecurityParseSitePolicy(p) + char *p; +{ + char *policyStr = SecurityParseString(&p); + char *copyPolicyStr; + char **newStrings; + + if (!policyStr) + return FALSE; + + copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1); + if (!copyPolicyStr) + return TRUE; + strcpy(copyPolicyStr, policyStr); + newStrings = (char **)Xrealloc(SecurityPolicyStrings, + sizeof (char *) * (nSecurityPolicyStrings + 1)); + if (!newStrings) + { + Xfree(copyPolicyStr); + return TRUE; + } + + SecurityPolicyStrings = newStrings; + SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr; + + return TRUE; + +} /* SecurityParseSitePolicy */ + + +char ** +SecurityGetSitePolicyStrings(n) + int *n; +{ + *n = nSecurityPolicyStrings; + return SecurityPolicyStrings; +} /* SecurityGetSitePolicyStrings */ + +static void +SecurityFreeSitePolicyStrings() +{ + if (SecurityPolicyStrings) + { + assert(nSecurityPolicyStrings); + while (nSecurityPolicyStrings--) + { + Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]); + } + Xfree(SecurityPolicyStrings); + SecurityPolicyStrings = NULL; + nSecurityPolicyStrings = 0; + } +} /* SecurityFreeSitePolicyStrings */ + + +static void +SecurityLoadPropertyAccessList() +{ + FILE *f; + int lineNumber = 0; + + SecurityMaxPropertyName = 0; + + if (!SecurityPolicyFile) + return; + + f = fopen(SecurityPolicyFile, "r"); + if (!f) + { + ErrorF("error opening security policy file %s\n", + SecurityPolicyFile); + return; + } + + while (!feof(f)) + { + char buf[200]; + Bool validLine; + char *p; + + if (!(p = fgets(buf, sizeof(buf), f))) + break; + lineNumber++; + + /* if first line, check version number */ + if (lineNumber == 1) + { + char *v = SecurityParseString(&p); + if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0) + { + ErrorF("%s: invalid security policy file version, ignoring file\n", + SecurityPolicyFile); + break; + } + validLine = TRUE; + } + else + { + switch (SecurityParseKeyword(&p)) + { + case SecurityKeywordComment: + validLine = TRUE; + break; + + case SecurityKeywordProperty: + validLine = SecurityParsePropertyAccessRule(p); + break; + + case SecurityKeywordSitePolicy: + validLine = SecurityParseSitePolicy(p); + break; + + default: + validLine = (*p == '\0'); /* blank lines OK, others not */ + break; + } + } + + if (!validLine) + ErrorF("Line %d of %s invalid, ignoring\n", + lineNumber, SecurityPolicyFile); + } /* end while more input */ + +#ifdef PROPDEBUG + { + PropertyAccessPtr pacl; + char *op = "aie"; + for (pacl = PropertyAccessList; pacl; pacl = pacl->next) + { + ErrorF("property %s ", NameForAtom(pacl->name)); + switch (pacl->windowRestriction) + { + case SecurityAnyWindow: ErrorF("any "); break; + case SecurityRootWindow: ErrorF("root "); break; + case SecurityWindowWithProperty: + { + ErrorF("%s ", NameForAtom(pacl->mustHaveProperty)); + if (pacl->mustHaveValue) + ErrorF(" = \"%s\" ", pacl->mustHaveValue); + + } + break; + } + ErrorF("%cr %cw %cd\n", op[pacl->readAction], + op[pacl->writeAction], op[pacl->destroyAction]); + } + } +#endif /* PROPDEBUG */ + + fclose(f); +} /* SecurityLoadPropertyAccessList */ + + +static Bool +SecurityMatchString(ws, cs) + char *ws; + char *cs; +{ + while (*ws && *cs) + { + if (*ws == '*') + { + Bool match = FALSE; + ws++; + while (!(match = SecurityMatchString(ws, cs)) && *cs) + { + cs++; + } + return match; + } + else if (*ws == *cs) + { + ws++; + cs++; + } + else break; + } + return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') ) + && (*cs == '\0') ); +} /* SecurityMatchString */ + +#ifdef PROPDEBUG +#include <sys/types.h> +#include <sys/stat.h> +#endif + + +char +SecurityCheckPropertyAccess(client, pWin, propertyName, access_mode) + ClientPtr client; + WindowPtr pWin; + ATOM propertyName; + Mask access_mode; +{ + PropertyAccessPtr pacl; + char action = SecurityDefaultAction; + + /* if client trusted or window untrusted, allow operation */ + + if ( (client->trustLevel == XSecurityClientTrusted) || + (wClient(pWin)->trustLevel != XSecurityClientTrusted) ) + return SecurityAllowOperation; + +#ifdef PROPDEBUG + /* For testing, it's more convenient if the property rules file gets + * reloaded whenever it changes, so we can rapidly try things without + * having to reset the server. + */ + { + struct stat buf; + static time_t lastmod = 0; + int ret = stat(SecurityPolicyFile , &buf); + if ( (ret == 0) && (buf.st_mtime > lastmod) ) + { + ErrorF("reloading property rules\n"); + SecurityFreePropertyAccessList(); + SecurityLoadPropertyAccessList(); + lastmod = buf.st_mtime; + } + } +#endif + + /* If the property atom is bigger than any atoms on the list, + * we know we won't find it, so don't even bother looking. + */ + if (propertyName <= SecurityMaxPropertyName) + { + /* untrusted client operating on trusted window; see if it's allowed */ + + for (pacl = PropertyAccessList; pacl; pacl = pacl->next) + { + if (pacl->name < propertyName) + continue; + if (pacl->name > propertyName) + break; + + /* pacl->name == propertyName, so see if it applies to this window */ + + switch (pacl->windowRestriction) + { + case SecurityAnyWindow: /* always applies */ + break; + + case SecurityRootWindow: + { + /* if not a root window, this rule doesn't apply */ + if (pWin->parent) + continue; + } + break; + + case SecurityWindowWithProperty: + { + PropertyPtr pProp = wUserProps (pWin); + Bool match = FALSE; + char *p; + char *pEndData; + + while (pProp) + { + if (pProp->propertyName == pacl->mustHaveProperty) + break; + pProp = pProp->next; + } + if (!pProp) + continue; + if (!pacl->mustHaveValue) + break; + if (pProp->type != XA_STRING || pProp->format != 8) + continue; + + p = pProp->data; + pEndData = ((char *)pProp->data) + pProp->size; + while (!match && p < pEndData) + { + if (SecurityMatchString(pacl->mustHaveValue, p)) + match = TRUE; + else + { /* skip to the next string */ + while (*p++ && p < pEndData) + ; + } + } + if (!match) + continue; + } + break; /* end case SecurityWindowWithProperty */ + } /* end switch on windowRestriction */ + + /* If we get here, the property access rule pacl applies. + * If pacl doesn't apply, something above should have + * executed a continue, which will skip the follwing code. + */ + action = SecurityAllowOperation; + if (access_mode & SecurityReadAccess) + action = max(action, pacl->readAction); + if (access_mode & SecurityWriteAccess) + action = max(action, pacl->writeAction); + if (access_mode & SecurityDestroyAccess) + action = max(action, pacl->destroyAction); + break; + } /* end for each pacl */ + } /* end if propertyName <= SecurityMaxPropertyName */ + + if (SecurityAllowOperation != action) + { /* audit the access violation */ + int cid = CLIENT_ID(pWin->drawable.id); + int reqtype = ((xReq *)client->requestBuffer)->reqType; + char *actionstr = (SecurityIgnoreOperation == action) ? + "ignored" : "error"; + SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n", + client->index, reqtype, pWin->drawable.id, + NameForAtom(propertyName), propertyName, cid, actionstr); + } + return action; +} /* SecurityCheckPropertyAccess */ + + +/* SecurityResetProc + * + * Arguments: + * extEntry is the extension information for the security extension. + * + * Returns: nothing. + * + * Side Effects: + * Performs any cleanup needed by Security at server shutdown time. + */ + +static void +SecurityResetProc(extEntry) + ExtensionEntry *extEntry; +{ + SecurityFreePropertyAccessList(); + SecurityFreeSitePolicyStrings(); +} /* SecurityResetProc */ + + +int +XSecurityOptions(argc, argv, i) + int argc; + char **argv; + int i; +{ + if (strcmp(argv[i], "-sp") == 0) + { + if (i < argc) + SecurityPolicyFile = argv[++i]; + return (i + 1); + } + return (i); +} /* XSecurityOptions */ + + + +/* SecurityExtensionInit + * + * Arguments: none. + * + * Returns: nothing. + * + * Side Effects: + * Enables the Security extension if possible. + */ + +void +SecurityExtensionInit() +{ + ExtensionEntry *extEntry; + int i; + + SecurityAuthorizationResType = + CreateNewResourceType(SecurityDeleteAuthorization); + + RTEventClient = CreateNewResourceType( + SecurityDeleteAuthorizationEventClient); + + if (!SecurityAuthorizationResType || !RTEventClient) + return; + + RTEventClient |= RC_NEVERRETAIN; + + if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL)) + return; + + extEntry = AddExtension(SECURITY_EXTENSION_NAME, + XSecurityNumberEvents, XSecurityNumberErrors, + ProcSecurityDispatch, SProcSecurityDispatch, + SecurityResetProc, StandardMinorOpcode); + + SecurityErrorBase = extEntry->errorBase; + SecurityEventBase = extEntry->eventBase; + + EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = + SwapSecurityAuthorizationRevokedEvent; + + /* initialize untrusted proc vectors */ + + for (i = 0; i < 128; i++) + { + UntrustedProcVector[i] = ProcVector[i]; + SwappedUntrustedProcVector[i] = SwappedProcVector[i]; + } + + /* make sure insecure extensions are not allowed */ + + for (i = 128; i < 256; i++) + { + if (!UntrustedProcVector[i]) + { + UntrustedProcVector[i] = ProcBadRequest; + SwappedUntrustedProcVector[i] = ProcBadRequest; + } + } + + SecurityLoadPropertyAccessList(); + +} /* SecurityExtensionInit */ diff --git a/Xext/shape.c b/Xext/shape.c new file mode 100644 index 000000000..bff7d2502 --- /dev/null +++ b/Xext/shape.c @@ -0,0 +1,1217 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* $Xorg: shape.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ +#define NEED_REPLIES +#define NEED_EVENTS +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _SHAPE_SERVER_ /* don't want Xlib structures */ +#include "shapestr.h" +#include "regionstr.h" +#include "gcstruct.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#endif + +static int ShapeFreeClient(), ShapeFreeEvents(); +static void SendShapeNotify(); +static int ProcShapeDispatch(), SProcShapeDispatch(); +static void ShapeResetProc(), SShapeNotifyEvent(); + +static unsigned char ShapeReqCode = 0; +static int ShapeEventBase = 0; +static RESTYPE ClientType, EventType; /* resource types for event masks */ + +#ifdef PANORAMIX +extern int PanoramiXNumScreens; +extern Bool noPanoramiXExtension; +extern PanoramiXWindow *PanoramiXWinRoot; +extern PanoramiXPmap *PanoramiXPmapRoot; +#endif +/* + * each window has a list of clients requesting + * ShapeNotify events. Each client has a resource + * for each window it selects ShapeNotify input for, + * this resource is used to delete the ShapeNotifyRec + * entry from the per-window queue. + */ + +typedef struct _ShapeEvent *ShapeEventPtr; + +typedef struct _ShapeEvent { + ShapeEventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; +} ShapeEventRec; + +/**************** + * ShapeExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ + +void +ShapeExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + + ClientType = CreateNewResourceType(ShapeFreeClient); + EventType = CreateNewResourceType(ShapeFreeEvents); + if (ClientType && EventType && + (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, + ProcShapeDispatch, SProcShapeDispatch, + ShapeResetProc, StandardMinorOpcode))) + { + ShapeReqCode = (unsigned char)extEntry->base; + ShapeEventBase = extEntry->eventBase; + EventSwapVector[ShapeEventBase] = SShapeNotifyEvent; + } +} + +/*ARGSUSED*/ +static void +ShapeResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static +RegionOperate (client, pWin, kind, destRgnp, srcRgn, op, xoff, yoff, create) + ClientPtr client; + WindowPtr pWin; + int kind; + RegionPtr *destRgnp, srcRgn; + int op; + int xoff, yoff; + RegionPtr (*create)(); /* creates a reasonable *destRgnp */ +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (srcRgn && (xoff || yoff)) + REGION_TRANSLATE(pScreen, srcRgn, xoff, yoff); + if (!pWin->parent) + { + if (srcRgn) + REGION_DESTROY(pScreen, srcRgn); + return Success; + } + switch (op) { + case ShapeSet: + if (*destRgnp) + REGION_DESTROY(pScreen, *destRgnp); + *destRgnp = srcRgn; + srcRgn = 0; + break; + case ShapeUnion: + if (*destRgnp) + REGION_UNION(pScreen, *destRgnp, *destRgnp, srcRgn); + break; + case ShapeIntersect: + if (*destRgnp) + REGION_INTERSECT(pScreen, *destRgnp, *destRgnp, srcRgn); + else { + *destRgnp = srcRgn; + srcRgn = 0; + } + break; + case ShapeSubtract: + if (!*destRgnp) + *destRgnp = (*create)(pWin); + REGION_SUBTRACT(pScreen, *destRgnp, *destRgnp, srcRgn); + break; + case ShapeInvert: + if (!*destRgnp) + *destRgnp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); + else + REGION_SUBTRACT(pScreen, *destRgnp, srcRgn, *destRgnp); + break; + default: + client->errorValue = op; + return BadValue; + } + if (srcRgn) + REGION_DESTROY(pScreen, srcRgn); + (*pScreen->SetShape) (pWin); + SendShapeNotify (pWin, kind); + return Success; +} + +static RegionPtr +CreateBoundingShape (pWin) + WindowPtr pWin; +{ + BoxRec extents; + + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); +} + +static RegionPtr +CreateClipShape (pWin) + WindowPtr pWin; +{ + BoxRec extents; + + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); +} + +static int +ProcShapeQueryVersion (client) + register ClientPtr client; +{ + REQUEST(xShapeQueryVersionReq); + xShapeQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xShapeQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SHAPE_MAJOR_VERSION; + rep.minorVersion = SHAPE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xShapeQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/***************** + * ProcShapeRectangles + * + *****************/ +#ifdef PANORAMIX +static int +ProcPanoramiXShapeRectangles (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeRectanglesReq); + xRectangle *prects; + int nrects, ctype; + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + int destBounding; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + result = ProcShapeRectangles (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeRectangles (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeRectanglesReq); + xRectangle *prects; + int nrects, ctype; + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + int destBounding; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + UpdateCurrentTime(); + pWin = LookupWindow (stuff->dest, client); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + destBounding = 1; + createDefault = CreateBoundingShape; + break; + case ShapeClip: + destBounding = 0; + createDefault = CreateClipShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq)); + if (nrects & 4) + return BadLength; + nrects >>= 3; + prects = (xRectangle *) &stuff[1]; + ctype = VerifyRectOrder(nrects, prects, (int)stuff->ordering); + if (ctype < 0) + return BadMatch; + srcRgn = RECTS_TO_REGION(pScreen, nrects, prects, ctype); + + if (!pWin->optional) + MakeWindowOptional (pWin); + if (destBounding) + destRgn = &pWin->optional->boundingShape; + else + destRgn = &pWin->optional->clipShape; + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +/************** + * ProcShapeMask + **************/ + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeMask (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeMaskReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + PixmapPtr pPixmap; + RegionPtr (*createDefault)(); + int destBounding; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + PanoramiXPmap *pPmap = PanoramiXPmapRoot; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + PANORAMIXFIND_ID(pPmap, stuff->src); + IF_RETURN(!pPmap, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + stuff->src = pPmap->info[j].id; + result = ProcShapeMask (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeMask (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeMaskReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + PixmapPtr pPixmap; + RegionPtr (*createDefault)(); + int destBounding; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + UpdateCurrentTime(); + pWin = SecurityLookupWindow (stuff->dest, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + destBounding = 1; + createDefault = CreateBoundingShape; + break; + case ShapeClip: + destBounding = 0; + createDefault = CreateClipShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (stuff->src == None) + srcRgn = 0; + else { + pPixmap = (PixmapPtr) SecurityLookupIDByType(client, stuff->src, + RT_PIXMAP, SecurityReadAccess); + if (!pPixmap) + return BadPixmap; + if (pPixmap->drawable.pScreen != pScreen || + pPixmap->drawable.depth != 1) + return BadMatch; + srcRgn = BITMAP_TO_REGION(pScreen, pPixmap); + if (!srcRgn) + return BadAlloc; + } + + if (!pWin->optional) + MakeWindowOptional (pWin); + if (destBounding) + destRgn = &pWin->optional->boundingShape; + else + destRgn = &pWin->optional->clipShape; + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +/************ + * ProcShapeCombine + ************/ +#ifdef PANORAMIX +static int +ProcPanoramiXShapeCombine (client) + register ClientPtr client; +{ + WindowPtr pSrcWin, pDestWin; + ScreenPtr pScreen; + REQUEST(xShapeCombineReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + RegionPtr (*createSrc)(); + RegionPtr tmp; + int destBounding; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_AT_LEAST_SIZE (xShapeCombineReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + result = ProcShapeCombine (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeCombine (client) + register ClientPtr client; +{ + WindowPtr pSrcWin, pDestWin; + ScreenPtr pScreen; + REQUEST(xShapeCombineReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + RegionPtr (*createDefault)(); + RegionPtr (*createSrc)(); + RegionPtr tmp; + int destBounding; + + REQUEST_SIZE_MATCH (xShapeCombineReq); + UpdateCurrentTime(); + pDestWin = LookupWindow (stuff->dest, client); + if (!pDestWin) + return BadWindow; + if (!pDestWin->optional) + MakeWindowOptional (pDestWin); + switch (stuff->destKind) { + case ShapeBounding: + destBounding = 1; + createDefault = CreateBoundingShape; + break; + case ShapeClip: + destBounding = 0; + createDefault = CreateClipShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pDestWin->drawable.pScreen; + + pSrcWin = LookupWindow (stuff->src, client); + if (!pSrcWin) + return BadWindow; + switch (stuff->srcKind) { + case ShapeBounding: + srcRgn = wBoundingShape (pSrcWin); + createSrc = CreateBoundingShape; + break; + case ShapeClip: + srcRgn = wClipShape (pSrcWin); + createSrc = CreateClipShape; + break; + default: + client->errorValue = stuff->srcKind; + return BadValue; + } + if (pSrcWin->drawable.pScreen != pScreen) + { + return BadMatch; + } + + if (srcRgn) { + tmp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); + REGION_COPY(pScreen, tmp, srcRgn); + srcRgn = tmp; + } else + srcRgn = (*createSrc) (pSrcWin); + + if (!pDestWin->optional) + MakeWindowOptional (pDestWin); + if (destBounding) + destRgn = &pDestWin->optional->boundingShape; + else + destRgn = &pDestWin->optional->clipShape; + + return RegionOperate (client, pDestWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +/************* + * ProcShapeOffset + *************/ +#ifdef PANORAMIX +static int +ProcPanoramiXShapeOffset (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeOffsetReq); + RegionPtr srcRgn; + + register int result; + int j; + PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot; + + REQUEST_AT_LEAST_SIZE (xShapeOffsetReq); + PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest); + IF_RETURN(!pPanoramiXWin, BadRequest); + FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) { + stuff->dest = pPanoramiXWin->info[j].id; + result = ProcShapeOffset (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +#ifdef PANORAMIX +int +#else +static int +#endif +ProcShapeOffset (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeOffsetReq); + RegionPtr srcRgn; + + REQUEST_SIZE_MATCH (xShapeOffsetReq); + UpdateCurrentTime(); + pWin = LookupWindow (stuff->dest, client); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + srcRgn = wBoundingShape (pWin); + break; + case ShapeClip: + srcRgn = wClipShape(pWin); + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (srcRgn) + { + REGION_TRANSLATE(pScreen, srcRgn, stuff->xOff, stuff->yOff); + (*pScreen->SetShape) (pWin); + } + SendShapeNotify (pWin, (int)stuff->destKind); + return Success; +} + +static int +ProcShapeQueryExtents (client) + register ClientPtr client; +{ + REQUEST(xShapeQueryExtentsReq); + WindowPtr pWin; + xShapeQueryExtentsReply rep; + BoxRec extents, *pExtents; + register int n; + + REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.boundingShaped = (wBoundingShape(pWin) != 0); + rep.clipShaped = (wClipShape(pWin) != 0); + if (wBoundingShape(pWin)) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, wBoundingShape(pWin)); + extents = *pExtents; + } else { + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + } + rep.xBoundingShape = extents.x1; + rep.yBoundingShape = extents.y1; + rep.widthBoundingShape = extents.x2 - extents.x1; + rep.heightBoundingShape = extents.y2 - extents.y1; + if (wClipShape(pWin)) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, wClipShape(pWin)); + extents = *pExtents; + } else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + } + rep.xClipShape = extents.x1; + rep.yClipShape = extents.y1; + rep.widthClipShape = extents.x2 - extents.x1; + rep.heightClipShape = extents.y2 - extents.y1; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.xBoundingShape, n); + swaps(&rep.yBoundingShape, n); + swaps(&rep.widthBoundingShape, n); + swaps(&rep.heightBoundingShape, n); + swaps(&rep.xClipShape, n); + swaps(&rep.yClipShape, n); + swaps(&rep.widthClipShape, n); + swaps(&rep.heightClipShape, n); + } + WriteToClient(client, sizeof (xShapeQueryExtentsReply), (char *)&rep); + return (client->noClientException); +} + +/*ARGSUSED*/ +static int +ShapeFreeClient (data, id) + pointer data; + XID id; +{ + ShapeEventPtr pShapeEvent; + WindowPtr pWin; + ShapeEventPtr *pHead, pCur, pPrev; + + pShapeEvent = (ShapeEventPtr) data; + pWin = pShapeEvent->window; + pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + } + } + xfree ((pointer) pShapeEvent); + return 1; +} + +/*ARGSUSED*/ +static int +ShapeFreeEvents (data, id) + pointer data; + XID id; +{ + ShapeEventPtr *pHead, pCur, pNext; + + pHead = (ShapeEventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +static int +ProcShapeSelectInput (client) + register ClientPtr client; +{ + REQUEST(xShapeSelectInputReq); + WindowPtr pWin; + ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH (xShapeSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (ShapeEventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, SecurityWriteAccess); + switch (stuff->enable) { + case xTrue: + if (pHead) { + + /* check for existing entry. */ + for (pShapeEvent = *pHead; + pShapeEvent; + pShapeEvent = pShapeEvent->next) + { + if (pShapeEvent->client == client) + return Success; + } + } + + /* build the entry */ + pNewShapeEvent = (ShapeEventPtr) + xalloc (sizeof (ShapeEventRec)); + if (!pNewShapeEvent) + return BadAlloc; + pNewShapeEvent->next = 0; + pNewShapeEvent->client = client; + pNewShapeEvent->window = pWin; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewShapeEvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewShapeEvent)) + return BadAlloc; + /* + * create a resource to contain a pointer to the list + * of clients selecting input. This must be indirect as + * the list may be arbitrarily rearranged which cannot be + * done through the resource database. + */ + if (!pHead) + { + pHead = (ShapeEventPtr *) xalloc (sizeof (ShapeEventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewShapeEvent->next = *pHead; + *pHead = pNewShapeEvent; + break; + case xFalse: + /* delete the interest */ + if (pHead) { + pNewShapeEvent = 0; + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + if (pShapeEvent->client == client) + break; + pNewShapeEvent = pShapeEvent; + } + if (pShapeEvent) { + FreeResource (pShapeEvent->clientResource, ClientType); + if (pNewShapeEvent) + pNewShapeEvent->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + xfree (pShapeEvent); + } + } + break; + default: + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + +/* + * deliver the event + */ + +static void +SendShapeNotify (pWin, which) + WindowPtr pWin; + int which; +{ + ShapeEventPtr *pHead, pShapeEvent; + ClientPtr client; + xShapeNotifyEvent se; + BoxRec extents; + RegionPtr region; + BYTE shaped; + + pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (!pHead) + return; + if (which == ShapeBounding) { + region = wBoundingShape(pWin); + if (region) { + extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); + shaped = xTrue; + } else { + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + shaped = xFalse; + } + } else { + region = wClipShape(pWin); + if (region) { + extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); + shaped = xTrue; + } else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + shaped = xFalse; + } + } + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + client = pShapeEvent->client; + if (client == serverClient || client->clientGone) + continue; + se.type = ShapeNotify + ShapeEventBase; + se.kind = which; + se.window = pWin->drawable.id; + se.sequenceNumber = client->sequence; + se.x = extents.x1; + se.y = extents.y1; + se.width = extents.x2 - extents.x1; + se.height = extents.y2 - extents.y1; + se.time = currentTime.milliseconds; + se.shaped = shaped; + WriteEventsToClient (client, 1, (xEvent *) &se); + } +} + +static int +ProcShapeInputSelected (client) + register ClientPtr client; +{ + REQUEST(xShapeInputSelectedReq); + WindowPtr pWin; + ShapeEventPtr pShapeEvent, *pHead; + int enabled; + xShapeInputSelectedReply rep; + register int n; + + REQUEST_SIZE_MATCH (xShapeInputSelectedReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + pHead = (ShapeEventPtr *) SecurityLookupIDByType(client, + pWin->drawable.id, EventType, SecurityReadAccess); + enabled = xFalse; + if (pHead) { + for (pShapeEvent = *pHead; + pShapeEvent; + pShapeEvent = pShapeEvent->next) + { + if (pShapeEvent->client == client) { + enabled = xTrue; + break; + } + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.enabled = enabled; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + } + WriteToClient (client, sizeof (xShapeInputSelectedReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcShapeGetRectangles (client) + register ClientPtr client; +{ + REQUEST(xShapeGetRectanglesReq); + WindowPtr pWin; + xShapeGetRectanglesReply rep; + xRectangle *rects; + int nrects, i; + RegionPtr region; + register int n; + + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + pWin = LookupWindow (stuff->window, client); + if (!pWin) + return BadWindow; + switch (stuff->kind) { + case ShapeBounding: + region = wBoundingShape(pWin); + break; + case ShapeClip: + region = wClipShape(pWin); + break; + default: + client->errorValue = stuff->kind; + return BadValue; + } + if (!region) { + nrects = 1; + rects = (xRectangle *) ALLOCATE_LOCAL (sizeof (xRectangle)); + if (!rects) + return BadAlloc; + switch (stuff->kind) { + case ShapeBounding: + rects->x = - (int) wBorderWidth (pWin); + rects->y = - (int) wBorderWidth (pWin); + rects->width = pWin->drawable.width + wBorderWidth (pWin); + rects->height = pWin->drawable.height + wBorderWidth (pWin); + break; + case ShapeClip: + rects->x = 0; + rects->y = 0; + rects->width = pWin->drawable.width; + rects->height = pWin->drawable.height; + break; + } + } else { + BoxPtr box; + nrects = REGION_NUM_RECTS(region); + box = REGION_RECTS(region); + rects = (xRectangle *) ALLOCATE_LOCAL (nrects * sizeof (xRectangle)); + if (!rects && nrects) + return BadAlloc; + for (i = 0; i < nrects; i++, box++) { + rects[i].x = box->x1; + rects[i].y = box->y1; + rects[i].width = box->x2 - box->x1; + rects[i].height = box->y2 - box->y1; + } + } + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = (nrects * sizeof (xRectangle)) >> 2; + rep.ordering = YXBanded; + rep.nrects = nrects; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.nrects, n); + SwapShorts ((short *)rects, (unsigned long)nrects * 4); + } + WriteToClient (client, sizeof (rep), (char *) &rep); + WriteToClient (client, nrects * sizeof (xRectangle), (char *) rects); + DEALLOCATE_LOCAL (rects); + return client->noClientException; +} + +static int +ProcShapeDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return ProcShapeQueryVersion (client); + case X_ShapeRectangles: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeRectangles (client); + else + return ProcShapeRectangles (client); +#else + return ProcShapeRectangles (client); +#endif + case X_ShapeMask: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeMask (client); + else + return ProcShapeMask (client); +#else + return ProcShapeMask (client); +#endif + case X_ShapeCombine: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeCombine (client); + else + return ProcShapeCombine (client); +#else + return ProcShapeCombine (client); +#endif + case X_ShapeOffset: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeOffset (client); + else + return ProcShapeOffset (client); +#else + return ProcShapeOffset (client); +#endif + case X_ShapeQueryExtents: + return ProcShapeQueryExtents (client); + case X_ShapeSelectInput: + return ProcShapeSelectInput (client); + case X_ShapeInputSelected: + return ProcShapeInputSelected (client); + case X_ShapeGetRectangles: + return ProcShapeGetRectangles (client); + default: + return BadRequest; + } +} + +static void +SShapeNotifyEvent(from, to) + xShapeNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswapl (from->window, to->window); + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswaps (from->x, to->x); + cpswaps (from->y, to->y); + cpswaps (from->width, to->width); + cpswaps (from->height, to->height); + cpswapl (from->time, to->time); + to->shaped = from->shaped; +} + +static int +SProcShapeQueryVersion (client) + register ClientPtr client; +{ + register int n; + REQUEST (xShapeQueryVersionReq); + + swaps (&stuff->length, n); + return ProcShapeQueryVersion (client); +} + +static int +SProcShapeRectangles (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeRectanglesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + SwapRestS(stuff); + return ProcShapeRectangles (client); +} + +static int +SProcShapeMask (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeMaskReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeMaskReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + swapl (&stuff->src, n); + return ProcShapeMask (client); +} + +static int +SProcShapeCombine (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeCombineReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeCombineReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + swapl (&stuff->src, n); + return ProcShapeCombine (client); +} + +static int +SProcShapeOffset (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeOffsetReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeOffsetReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + return ProcShapeOffset (client); +} + +static int +SProcShapeQueryExtents (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeQueryExtentsReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); + swapl (&stuff->window, n); + return ProcShapeQueryExtents (client); +} + +static int +SProcShapeSelectInput (client) + register ClientPtr client; +{ + register char n; + REQUEST (xShapeSelectInputReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeSelectInputReq); + swapl (&stuff->window, n); + return ProcShapeSelectInput (client); +} + +static int +SProcShapeInputSelected (client) + register ClientPtr client; +{ + register int n; + REQUEST (xShapeInputSelectedReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeInputSelectedReq); + swapl (&stuff->window, n); + return ProcShapeInputSelected (client); +} + +static int +SProcShapeGetRectangles (client) + register ClientPtr client; +{ + REQUEST(xShapeGetRectanglesReq); + register char n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + swapl (&stuff->window, n); + return ProcShapeGetRectangles (client); +} + +static int +SProcShapeDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return SProcShapeQueryVersion (client); + case X_ShapeRectangles: + return SProcShapeRectangles (client); + case X_ShapeMask: + return SProcShapeMask (client); + case X_ShapeCombine: + return SProcShapeCombine (client); + case X_ShapeOffset: + return SProcShapeOffset (client); + case X_ShapeQueryExtents: + return SProcShapeQueryExtents (client); + case X_ShapeSelectInput: + return SProcShapeSelectInput (client); + case X_ShapeInputSelected: + return SProcShapeInputSelected (client); + case X_ShapeGetRectangles: + return SProcShapeGetRectangles (client); + default: + return BadRequest; + } +} diff --git a/Xext/shm.c b/Xext/shm.c new file mode 100644 index 000000000..0a9f3af59 --- /dev/null +++ b/Xext/shm.c @@ -0,0 +1,1010 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include "shmstr.h" +#include "Xfuncproto.h" + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(), fbShmPutImage(); +static PixmapPtr fbShmCreatePixmap(); +static int ProcShmDispatch(), SProcShmDispatch(); +static int ShmDetachSegment(); +static void ShmResetProc(), SShmCompletionEvent(); + +static unsigned char ShmReqCode; +static int ShmCompletionCode; +static int BadShmSegCode; +static RESTYPE ShmSegType, ShmPixType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + +void +ShmExtensionInit() +{ + ExtensionEntry *extEntry; + int i; + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + sharedPixmaps = xFalse; + pixmapFormat = 0; +#else + sharedPixmaps = xTrue; + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + shmFuncs[i] = &miFuncs; + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; +#endif + ShmSegType = CreateNewResourceType(ShmDetachSegment); + ShmPixType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && ShmPixType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs(pScreen, funcs) + ScreenPtr pScreen; + ShmFuncsPtr funcs; +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat(pScreen, format) + ScreenPtr pScreen; + int format; +{ + shmPixFormat[pScreen->myNum] = format; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + REQUEST(xShmQueryVersionReq); + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + return; + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + /*XXX*/depth, PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + FreeScratchPixmapHeader(pPixmap); + } + else + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); +} + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + long lengthProto; + char *tmpImage; + int tmpAlloced = 0; +#endif + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = PixmapBytePadProto(stuff->totalWidth, 1); +#endif + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = PixmapBytePadProto(stuff->totalWidth, 1); + lengthProto *= stuff->depth; +#endif + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); +#ifdef INTERNAL_VS_EXTERNAL_PADDING + lengthProto = PixmapBytePadProto(stuff->totalWidth, stuff->depth); +#endif + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + VERIFY_SHMSIZE(shmdesc, stuff->offset, lengthProto * stuff->totalHeight, + client); +#else + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); +#endif + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* handle 64 bit case where protocol may pad to 32 and we want 64 + * In this case, length is what the server wants and lengthProto is + * what the protocol thinks it is. If the the two are different, + * copy the protocol version (i.e. the memory shared between the + * server and the client) to a version with a scanline pad of 64. + */ + if (length != lengthProto) + { + register int i; + char * stuffptr, /* pointer into protocol data */ + * tmpptr; /* new location to copy to */ + + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->totalHeight))) + return (BadAlloc); + tmpAlloced = 1; + + bzero(tmpImage,length*stuff->totalHeight); + + if (stuff->format == XYPixmap) + { + int lineBytes = PixmapBytePad(stuff->totalWidth, 1); + int lineBytesProto = PixmapBytePadProto(stuff->totalWidth, 1); + int depth = stuff->depth; + + stuffptr = shmdesc->addr + stuff->offset ; + tmpptr = tmpImage; + for (i = 0; i < stuff->totalHeight*stuff->depth; + stuffptr += lineBytesProto,tmpptr += lineBytes, i++) + bcopy(stuffptr,tmpptr,lineBytesProto); + } + else + { + for (i = 0, + stuffptr = shmdesc->addr + stuff->offset, + tmpptr=tmpImage; + i < stuff->totalHeight; + stuffptr += lengthProto,tmpptr += length, i++) + bcopy(stuffptr,tmpptr,lengthProto); + } + } + /* handle 64-bit case where stuff is not 64-bit aligned + */ + else if ((unsigned long)(shmdesc->addr+stuff->offset) & + (sizeof(long)-1)) + { + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->totalHeight))) + return (BadAlloc); + tmpAlloced = 1; + bcopy((char *)(shmdesc->addr+stuff->offset), + tmpImage, + length*stuff->totalHeight); + } + else + tmpImage = (char *)(shmdesc->addr+stuff->offset); +#endif + + if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || + ((stuff->format != ZPixmap) && + (stuff->srcX < screenInfo.bitmapScanlinePad) && + ((stuff->format == XYBitmap) || + ((stuff->srcY == 0) && + (stuff->srcHeight == stuff->totalHeight))))) && + ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, + stuff->dstX, stuff->dstY, + stuff->totalWidth, stuff->srcHeight, + stuff->srcX, stuff->format, +#ifdef INTERNAL_VS_EXTERNAL_PADDING + tmpImage + +#else + shmdesc->addr + stuff->offset + +#endif + (stuff->srcY * length)); + else + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, +#ifdef INTERNAL_VS_EXTERNAL_PADDING + tmpImage); + +#else + shmdesc->addr + stuff->offset); +#endif + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if (tmpAlloced) + DEALLOCATE_LOCAL(tmpImage); +#endif + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer, length; + Mask plane; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; +#ifdef INTERNAL_VS_EXTERNAL_PADDING + long widthBytesLine,widthBytesLineProto; + long lenPerProto,lengthProto; + char *tmpImage; + int tmpAlloced = 0; +#endif + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLine = PixmapBytePad(stuff->width, pDraw->depth); + length = widthBytesLine * stuff->height; + widthBytesLineProto = PixmapBytePadProto(stuff->width, pDraw->depth); + lengthProto = widthBytesLineProto * stuff->height; +#else + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; +#endif + } + else + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + widthBytesLine = PixmapBytePad(stuff->width, 1); + lenPer = widthBytesLine * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + + widthBytesLineProto = PixmapBytePadProto(stuff->width, 1); + lenPerProto = widthBytesLineProto * stuff->height; + lengthProto = lenPerProto * Ones(stuff->planeMask & + (plane | (plane - 1))); +#else + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); +#endif + } + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + VERIFY_SHMSIZE(shmdesc, stuff->offset, lengthProto, client); + xgi.size = lengthProto; +#else + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; +#endif + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* check for protocol/server padding differences. + */ + if ((widthBytesLine != widthBytesLineProto) || + ((unsigned long)shmdesc->addr + stuff->offset & (sizeof(long)-1))) + { + /* temp stuff for 64 bit alignment stuff */ + register char * bufPtr, * protoPtr; + register int i; + + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + tmpAlloced = 1; + + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + tmpImage); + + /* for 64-bit server, convert image to pad to 32 bits + */ + bzero(shmdesc->addr + stuff->offset,lengthProto); + + for (i=0,bufPtr=tmpImage,protoPtr=shmdesc->addr + stuff->offset; + i < stuff->height; + bufPtr += widthBytesLine,protoPtr += widthBytesLineProto, + i++) + bcopy(bufPtr,protoPtr,widthBytesLineProto); + } + else + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } +#else + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); +#endif + } + else + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + /* check for protocol/server padding differences. + */ + if ((widthBytesLine != widthBytesLineProto) || + ((unsigned long)shmdesc->addr + stuff->offset & + (sizeof(long)-1))) + { + if(!(tmpImage = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + tmpAlloced = 1; + } +#endif + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if ((widthBytesLine != widthBytesLineProto) || + ((unsigned long)shmdesc->addr + stuff->offset & + (sizeof(long)-1))) + { + /* get image for each plane. + */ + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + tmpImage); + + /* for 64-bit server, convert image to pad to 32 bits */ + bzero(shmdesc->addr+length, widthBytesLine); + bcopy(tmpImage, shmdesc->addr+length, widthBytesLineProto); + /* increment length */ + length += lenPerProto; + } + else /* no diff between protocol and server */ + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } +#else + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; +#endif + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + +#ifdef INTERNAL_VS_EXTERNAL_PADDING + if (tmpAlloced) + DEALLOCATE_LOCAL(tmpImage); +#endif + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); + if (!pPixmap) + return NullPixmap; + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + /*XXX*/depth, PixmapBytePad(width, depth), (pointer)addr)) + return NullPixmap; + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + shmdesc->refcnt++; + if (AddResource(stuff->pid, ShmPixType, (pointer)shmdesc)) + return(client->noClientException); + FreeResource(stuff->pid, RT_NONE); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: + return ProcShmPutImage(client); + case X_ShmGetImage: + return ProcShmGetImage(client); + case X_ShmCreatePixmap: + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + return SProcShmPutImage(client); + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} diff --git a/Xext/sleepuntil.c b/Xext/sleepuntil.c new file mode 100644 index 000000000..292924ed6 --- /dev/null +++ b/Xext/sleepuntil.c @@ -0,0 +1,211 @@ +/* + * $Xorg: sleepuntil.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ + * +Copyright 1992, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* dixsleep.c - implement millisecond timeouts for X clients */ + +#include "X.h" +#include "Xmd.h" +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +typedef struct _Sertafied { + struct _Sertafied *next; + TimeStamp revive; + ClientPtr pClient; + XID id; + void (*notifyFunc)(); + pointer closure; +} SertafiedRec, *SertafiedPtr; + +static SertafiedPtr pPending; +static RESTYPE SertafiedResType; +static Bool BlockHandlerRegistered; +static int SertafiedGeneration; +static void ClientAwaken(); +static int SertafiedDelete(); +static void SertafiedBlockHandler(); +static void SertafiedWakeupHandler(); + +ClientSleepUntil (client, revive, notifyFunc, closure) + ClientPtr client; + TimeStamp *revive; + void (*notifyFunc)(); + pointer closure; +{ + SertafiedPtr pRequest, pReq, pPrev; + + if (SertafiedGeneration != serverGeneration) + { + SertafiedResType = CreateNewResourceType (SertafiedDelete); + if (!SertafiedResType) + return FALSE; + SertafiedGeneration = serverGeneration; + BlockHandlerRegistered = FALSE; + } + pRequest = (SertafiedPtr) xalloc (sizeof (SertafiedRec)); + if (!pRequest) + return FALSE; + pRequest->pClient = client; + pRequest->revive = *revive; + pRequest->id = FakeClientID (client->index); + pRequest->closure = closure; + if (!BlockHandlerRegistered) + { + if (!RegisterBlockAndWakeupHandlers (SertafiedBlockHandler, + SertafiedWakeupHandler, + (pointer) 0)) + { + xfree (pRequest); + return FALSE; + } + BlockHandlerRegistered = TRUE; + } + pRequest->notifyFunc = 0; + if (!AddResource (pRequest->id, SertafiedResType, (pointer) pRequest)) + return FALSE; + if (!notifyFunc) + notifyFunc = ClientAwaken; + pRequest->notifyFunc = notifyFunc; + /* Insert into time-ordered queue, with earliest activation time coming first. */ + pPrev = 0; + for (pReq = pPending; pReq; pReq = pReq->next) + { + if (CompareTimeStamps (pReq->revive, *revive) == LATER) + break; + pPrev = pReq; + } + if (pPrev) + pPrev->next = pRequest; + else + pPending = pRequest; + pRequest->next = pReq; + IgnoreClient (client); + return TRUE; +} + +static void +ClientAwaken (client, closure) + ClientPtr client; + pointer closure; +{ + if (!client->clientGone) + AttendClient (client); +} + + +static int +SertafiedDelete (value, id) + pointer value; + XID id; +{ + SertafiedPtr pRequest = (SertafiedPtr)value; + SertafiedPtr pReq, pPrev; + + pPrev = 0; + for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) + if (pReq == pRequest) + { + if (pPrev) + pPrev->next = pReq->next; + else + pPending = pReq->next; + break; + } + if (pRequest->notifyFunc) + (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); + xfree (pRequest); + return TRUE; +} + +static void +SertafiedBlockHandler (data, wt, LastSelectMask) + pointer data; /* unused */ + OSTimePtr wt; /* wait time */ + pointer LastSelectMask; +{ + SertafiedPtr pReq, pNext; + unsigned long newdelay, olddelay; + TimeStamp now; + + if (!pPending) + return; + now.milliseconds = GetTimeInMillis (); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) + { + pNext = pReq->next; + if (CompareTimeStamps (pReq->revive, now) == LATER) + break; + FreeResource (pReq->id, RT_NONE); + + /* AttendClient() may have been called via the resource delete + * function so a client may have input to be processed and so + * set delay to 0 to prevent blocking in WaitForSomething(). + */ + AdjustWaitForDelay (wt, 0); + } + pReq = pPending; + if (!pReq) + return; + newdelay = pReq->revive.milliseconds - now.milliseconds; + AdjustWaitForDelay (wt, newdelay); +} + +static void +SertafiedWakeupHandler (data, i, LastSelectMask) + pointer data; + int i; + pointer LastSelectMask; +{ + SertafiedPtr pReq, pNext; + TimeStamp now; + + now.milliseconds = GetTimeInMillis (); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) + { + pNext = pReq->next; + if (CompareTimeStamps (pReq->revive, now) == LATER) + break; + FreeResource (pReq->id, RT_NONE); + } + if (!pPending) + { + RemoveBlockAndWakeupHandlers (SertafiedBlockHandler, + SertafiedWakeupHandler, + (pointer) 0); + BlockHandlerRegistered = FALSE; + } +} diff --git a/Xext/sync.c b/Xext/sync.c new file mode 100644 index 000000000..8274d2522 --- /dev/null +++ b/Xext/sync.c @@ -0,0 +1,2322 @@ +/* $Xorg: sync.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + +Copyright 1991, 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, 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 The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, +and Olivetti Research Limited, Cambridge, England. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or Olivetti +not be used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. Digital and Olivetti +make no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +*/ + +#define NEED_REPLIES +#define NEED_EVENTS +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "Xmd.h" +#include "misc.h" +#include "os.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _SYNC_SERVER +#include "sync.h" +#include "syncstr.h" + +/* + * Local Global Variables + */ +static int SyncReqCode; +static int SyncEventBase; +static int SyncErrorBase; +static RESTYPE RTCounter = 0; +static RESTYPE RTAwait; +static RESTYPE RTAlarm; +static RESTYPE RTAlarmClient; +static int SyncNumSystemCounters = 0; +static SyncCounter **SysCounterList = NULL; + +#define IsSystemCounter(pCounter) \ + (pCounter && (pCounter->client == NULL)) + +/* these are all the alarm attributes that pertain to the alarm's trigger */ +#define XSyncCAAllTrigger \ + (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) + +static void SyncComputeBracketValues( +#if NeedFunctionPrototypes + SyncCounter * /* pCounter */, + Bool /* startOver */ +#endif +); + +/* Each counter maintains a simple linked list of triggers that are + * interested in the counter. The two functions below are used to + * delete and add triggers on this list. + */ +static void +SyncDeleteTriggerFromCounter(pTrigger) + SyncTrigger *pTrigger; +{ + SyncTriggerList *pCur, *pPrev = NULL; + + /* pCounter needs to be stored in pTrigger before calling here. */ + + if (!pTrigger->pCounter) + return; + + for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) + { + if (pCur->pTrigger == pTrigger) + { + if (pPrev) + pPrev->next = pCur->next; + else + pTrigger->pCounter->pTriglist = pCur->next; + xfree(pCur); + break; + } + } + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE); +} + + +static int +SyncAddTriggerToCounter(pTrigger) + SyncTrigger *pTrigger; +{ + SyncTriggerList *pCur; + + if (!pTrigger->pCounter) + return Success; + + /* don't do anything if it's already there */ + for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) + { + if (pCur->pTrigger == pTrigger) + return Success; + } + + if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList)))) + return BadAlloc; + + pCur->pTrigger = pTrigger; + pCur->next = pTrigger->pCounter->pTriglist; + pTrigger->pCounter->pTriglist = pCur; + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE); + + return Success; +} + + +/* Below are four possible functions that can be plugged into + * pTrigger->CheckTrigger, corresponding to the four possible + * test-types. These functions are called after the counter's + * value changes but are also passed the old counter value + * so they can inspect both the old and new values. + * (PositiveTransition and NegativeTransition need to see both + * pieces of information.) These functions return the truth value + * of the trigger. + * + * All of them include the condition pTrigger->pCounter == NULL. + * This is because the spec says that a trigger with a counter value + * of None is always TRUE. + */ + +static Bool +SyncCheckTriggerPositiveComparison(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerNegativeComparison(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerPositiveTransition(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + (XSyncValueLessThan(oldval, pTrigger->test_value) && + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static Bool +SyncCheckTriggerNegativeTransition(pTrigger, oldval) + SyncTrigger *pTrigger; + CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + (XSyncValueGreaterThan(oldval, pTrigger->test_value) && + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + + + +static int +SyncInitTrigger(client, pTrigger, counter, changes) + ClientPtr client; /* so we can set errorValue */ + SyncTrigger *pTrigger; + XSyncCounter counter; + Mask changes; +{ + SyncCounter *pCounter = pTrigger->pCounter; + int status; + Bool newcounter = FALSE; + + if (changes & XSyncCACounter) + { + if (counter == None) + pCounter = NULL; + else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType( + client, counter, RTCounter, SecurityReadAccess))) + { + client->errorValue = counter; + return SyncErrorBase + XSyncBadCounter; + } + if (pCounter != pTrigger->pCounter) + { /* new counter for trigger */ + SyncDeleteTriggerFromCounter(pTrigger); + pTrigger->pCounter = pCounter; + newcounter = TRUE; + } + } + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + if (changes & XSyncCAValueType) + { + if (pTrigger->value_type != XSyncRelative && + pTrigger->value_type != XSyncAbsolute) + { + client->errorValue = pTrigger->value_type; + return BadValue; + } + } + + if (changes & XSyncCATestType) + { + if (pTrigger->test_type != XSyncPositiveTransition && + pTrigger->test_type != XSyncNegativeTransition && + pTrigger->test_type != XSyncPositiveComparison && + pTrigger->test_type != XSyncNegativeComparison) + { + client->errorValue = pTrigger->test_type; + return BadValue; + } + /* select appropriate Ch |