diff options
Diffstat (limited to 'nx-X11/programs/Xserver/Xext')
64 files changed, 43414 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/Xext/EVI.c b/nx-X11/programs/Xserver/Xext/EVI.c new file mode 100644 index 000000000..93ed19fa6 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/EVI.c @@ -0,0 +1,215 @@ +/* $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. +********************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/EVI.c,v 3.10tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "dixstruct.h" +#include "extnsionst.h" +#include "dix.h" +#define _XEVI_SERVER_ +#include <X11/extensions/XEVIstr.h> +#include "EVIstruct.h" +#include "modinit.h" +#include "scrnintstr.h" + +#if 0 +static unsigned char XEVIReqCode = 0; +#endif +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 i, n, n_conflict, n_info, sz_info, sz_conflict; + VisualID32 *conflict; + unsigned int total_visuals = 0; + xExtendedVisualInfo *eviInfo; + int status; + + /* + * do this first, otherwise REQUEST_FIXED_SIZE can overflow. we assume + * here that you don't have more than 2^32 visuals over all your screens; + * this seems like a safe assumption. + */ + for (i = 0; i < screenInfo.numScreens; i++) + total_visuals += screenInfo.screens[i]->numVisuals; + if (stuff->n_visual > total_visuals) + return BadValue; + + 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(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(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(EVINAME, 0, 0, + ProcEVIDispatch, + SProcEVIDispatch, + EVIResetProc, StandardMinorOpcode))) { + XEVIReqCode = (unsigned char)extEntry->base; +#else + if (AddExtension(EVINAME, 0, 0, + ProcEVIDispatch, SProcEVIDispatch, + EVIResetProc, StandardMinorOpcode)) { +#endif + eviPriv = eviDDXInit(); + } +} diff --git a/nx-X11/programs/Xserver/Xext/EVIstruct.h b/nx-X11/programs/Xserver/Xext/EVIstruct.h new file mode 100644 index 000000000..857e7565a --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/EVIstruct.h @@ -0,0 +1,60 @@ +/* $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. +********************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/EVIstruct.h,v 3.5 2003/07/16 01:38:28 dawes Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef EVI_STRUCT_H +#define EVI_STRUCT_H + +/* + ****************************************************************************** + ** Per-ddx data + ****************************************************************************** + */ + +typedef int (*GetVisualInfoProc)( + VisualID32*, + int, + xExtendedVisualInfo**, + int*, + VisualID32**, + int* +); + +typedef void (*FreeVisualInfoProc)( + xExtendedVisualInfo*, + VisualID32* +); +typedef struct _EviPrivRec { + GetVisualInfoProc getVisualInfo; + FreeVisualInfoProc freeVisualInfo; +} EviPrivRec, *EviPrivPtr; + +extern EviPrivPtr eviDDXInit(void); +extern void eviDDXReset(void); + +#endif /* EVI_STRUCT_H */ diff --git a/nx-X11/programs/Xserver/Xext/Imakefile b/nx-X11/programs/Xserver/Xext/Imakefile new file mode 100644 index 000000000..b75f8913b --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/Imakefile @@ -0,0 +1,226 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/Imakefile,v 1.9 2005/04/24 01:10:12 gisburn Exp $ */ +XCOMM $Xorg: Imakefile,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ + + + + +XCOMM $XFree86: xc/programs/Xserver/Xext/Imakefile,v 3.43 2003/04/21 18:56:48 sven Exp $ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NX-X11, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include <Server.tmpl> + +#if DoLoadableServer +#define IHaveSubdirs +SUBDIRS = extmod +#endif + +#if BuildEVI +#ifdef SGIArchitectureNotTog + EVISRCS = EVI.c sgiEVI.c + EVIOBJS = EVI.o sgiEVI.o +#else + EVISRCS = EVI.c sampleEVI.c + EVIOBJS = EVI.o sampleEVI.o +#endif +#endif +#if HasShm + SHMSRCS = shm.c + SHMOBJS = shm.o +#endif + +#if BuildMultibuffer + MULTIBUFSRC = mbuf.c + MULTIBUFOBJ = mbuf.o +#endif + +#if BuildScreenSaverExt + SCRNSAVSRC = saver.c + SCRNSAVOBJ = saver.o +#endif + +#if BuildXF86VidModeExt && \ + ((defined(XF86Server) && XF86Server) || \ + (defined(XorgServer) && XorgServer)) + VIDMODESRCS = xf86vmode.c + VIDMODEOBJS = xf86vmode.o +#endif + +#if BuildXF86MiscExt && \ + ((defined(XF86Server) && XF86Server) || \ + (defined(XorgServer) && XorgServer)) +XF86MISCSRCS = xf86misc.c +XF86MISCOBJS = xf86misc.o +#endif + +#if BuildXF86BigfontExt +XF86BIGFSRCS = xf86bigfont.c +XF86BIGFOBJS = xf86bigfont.o +#if HasShm + SHM_DEFINES = -DHAS_SHM +#endif +#endif + +#if BuildXF86DGA + XF86DGASRCS = xf86dga.c xf86dga2.c + XF86DGAOBJS = xf86dga.o xf86dga2.o +#if HasShm + XVMCSHM_DEFINES = -DHAS_XVMCSHM +#endif +#endif + +#if BuildXvExt + XVSRCS = xvmain.c xvdisp.c xvmc.c + XVOBJS = xvmain.o xvdisp.o xvmc.o +#endif + +#if BuildXResExt + XRESSRCS = xres.c + XRESOBJS = xres.o +#endif + +#if BuildAppgroup + APPGROUPSRCS = appgroup.c + APPGROUPOBJS = appgroup.o +#endif +#if BuildXCSecurity + SECURITYSRCS = security.c + SECURITYOBJS = security.o + SERVERCONFIGDIR = ServerConfigDir + POLICYFILEDEF = -DDEFAULTPOLICYFILE=\"$(SERVERCONFIGDIR)/SecurityPolicy\" +#endif +#if BuildCup + CUPSRCS = cup.c + CUPOBJS = cup.o +#endif +#if BuildXinerama + PNRXSRCS = panoramiX.c panoramiXSwap.c panoramiXprocs.c + PNRXOBJS = panoramiX.o panoramiXSwap.o panoramiXprocs.o + PNRXINCLUDES = -I$(FONTINCSRC) -I../mi -I../render +#endif +#if XdmxServer + DMXSRCS = dmx.c + DMXOBJS = dmx.o + DMXINCLUDES = -I../hw/dmx +#endif +#if BuildDPMS + DPMSSRCS = dpms.c + DPMSOBJS = dpms.o +#endif + +#if BuildFontCache + FONTCACHESRCS = fontcache.c + FONTCACHEOBJS = fontcache.o +#if 0 + FONTCACHEINCLUDES = -I$(XF86SRC)/os-support +#endif +#endif + +#if BuildXevie + XEVIESRCS = xevie.c + XEVIEOBJS = xevie.o +#endif + +#if BuildXprint + XPRINTSRCS = xprint.c + XPRINTOBJS = xprint.o +#endif + + SRCS = shape.c $(SHMSRCS) $(MULTIBUFSRC) \ + mitmisc.c xtest.c xtest1di.c xtest1dd.c sleepuntil.c \ + bigreq.c sync.c $(SCRNSAVSRC) xcmisc.c $(VIDMODESRCS) \ + $(XF86MISCSRCS) $(XF86BIGFSRCS) $(XF86DGASRCS) $(SECURITYSRCS) \ + $(APPGROUPSRCS) $(XPRINTSRCS) $(CUPSRCS) $(PNRXSRCS) $(DPMSSRCS) \ + $(XEVIESRCS) \ + $(EVISRCS) $(XVSRCS) $(FONTCACHESRCS) $(XRESSRCS) $(DMXSRCS) + + OBJS = shape.o $(SHMOBJS) $(MULTIBUFOBJ) \ + mitmisc.o xtest.o xtest1di.o xtest1dd.o sleepuntil.o \ + bigreq.o sync.o $(SCRNSAVOBJ) xcmisc.o $(VIDMODEOBJS) \ + $(XF86MISCOBJS) $(XF86BIGFOBJS) $(XF86DGAOBJS) $(SECURITYOBJS) \ + $(APPGROUPOBJS) $(XPRINTOBJS) $(CUPOBJS) $(PNRXOBJS) $(DPMSOBJS) \ + $(XEVIEOBJS) \ + $(EVIOBJS) $(XVOBJS) $(FONTCACHEOBJS) $(XRESOBJS) $(DMXOBJS) + + SOBJS = $(SHMOBJS) $(APPGROUPOBJS) $(SECURITYOBJS) $(XPRINTOBJS) \ + shape.o xtest.o xtest1di.o xtest1dd.o sleepuntil.o $(PNRXOBJS) \ + $(XEVIEOBJS) \ + $(XF86BIGFOBJS) + +#if defined(NXAgentServer) && NXAgentServer +NX_DEFINES = -DNXAGENT_SERVER +#endif + + +#if (defined(XFree86Version) || defined(XorgVersion)) +/* XXX Check if this can be eliminated */ +XF86INCLUDES = -I$(XF86COMSRC) +#endif + INCLUDES = -I. -I../include -I$(XINCLUDESRC) -I$(EXTINCSRC) \ + $(PNRXINCLUDES) $(XF86INCLUDES) -I$(FONTINCSRC) \ + $(FONTCACHEINCLUDES) $(DMXINCLUDES) + LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln + +#if defined(NXAgentServer) && NXAgentServer + DEFINES = $(EXT_DEFINES) $(XVMCSHM_DEFINES) $(NX_DEFINES) +#else + DEFINES = $(EXT_DEFINES) $(XVMCSHM_DEFINES) +#endif + +NormalLibraryObjectRule() + +/* + * A hack to work around an optimization problem with gcc 2.95.2 + */ +#if BuildXF86VidModeExt && defined(GccOptBug295) +SpecialCObjectRule(xf86vmode,NullParameter,-O0) +#endif + +NormalLibraryTarget(ext,$(OBJS)) +LintLibraryTarget(ext,$(SRCS)) +NormalLintTarget($(SRCS)) + +#if DoLoadableServer +NormalLibraryTarget(exts,$(SOBJS)) +#endif + +#if BuildXF86BigfontExt +SpecialCObjectRule(xf86bigfont,$(ICONFIGFILES),$(SHM_DEFINES)) +#endif +#if BuildXCSecurity +SpecialCObjectRule(security,$(ICONFIGFILES),$(POLICYFILEDEF)) +#endif + +LinkConfDirectory(xserver,.,xserver,.) + +LinkSourceFile(modinit.h,extmod) + +#if BuildXCSecurity && InstallSecurityConfig +InstallNonExecFile(SecurityPolicy,$(SERVERCONFIGDIR)) +#endif + +DependTarget() + +#if DoLoadableServer +MakeSubdirs($(SUBDIRS)) +DependSubdirs($(SUBDIRS)) +#endif + +InstallDriverSDKNonExecFile(dgaproc.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xvdix.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xvmcext.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/nx-X11/programs/Xserver/Xext/Imakefile.NX.original b/nx-X11/programs/Xserver/Xext/Imakefile.NX.original new file mode 100644 index 000000000..b75f8913b --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/Imakefile.NX.original @@ -0,0 +1,226 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/Imakefile,v 1.9 2005/04/24 01:10:12 gisburn Exp $ */ +XCOMM $Xorg: Imakefile,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ + + + + +XCOMM $XFree86: xc/programs/Xserver/Xext/Imakefile,v 3.43 2003/04/21 18:56:48 sven Exp $ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NX-X11, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include <Server.tmpl> + +#if DoLoadableServer +#define IHaveSubdirs +SUBDIRS = extmod +#endif + +#if BuildEVI +#ifdef SGIArchitectureNotTog + EVISRCS = EVI.c sgiEVI.c + EVIOBJS = EVI.o sgiEVI.o +#else + EVISRCS = EVI.c sampleEVI.c + EVIOBJS = EVI.o sampleEVI.o +#endif +#endif +#if HasShm + SHMSRCS = shm.c + SHMOBJS = shm.o +#endif + +#if BuildMultibuffer + MULTIBUFSRC = mbuf.c + MULTIBUFOBJ = mbuf.o +#endif + +#if BuildScreenSaverExt + SCRNSAVSRC = saver.c + SCRNSAVOBJ = saver.o +#endif + +#if BuildXF86VidModeExt && \ + ((defined(XF86Server) && XF86Server) || \ + (defined(XorgServer) && XorgServer)) + VIDMODESRCS = xf86vmode.c + VIDMODEOBJS = xf86vmode.o +#endif + +#if BuildXF86MiscExt && \ + ((defined(XF86Server) && XF86Server) || \ + (defined(XorgServer) && XorgServer)) +XF86MISCSRCS = xf86misc.c +XF86MISCOBJS = xf86misc.o +#endif + +#if BuildXF86BigfontExt +XF86BIGFSRCS = xf86bigfont.c +XF86BIGFOBJS = xf86bigfont.o +#if HasShm + SHM_DEFINES = -DHAS_SHM +#endif +#endif + +#if BuildXF86DGA + XF86DGASRCS = xf86dga.c xf86dga2.c + XF86DGAOBJS = xf86dga.o xf86dga2.o +#if HasShm + XVMCSHM_DEFINES = -DHAS_XVMCSHM +#endif +#endif + +#if BuildXvExt + XVSRCS = xvmain.c xvdisp.c xvmc.c + XVOBJS = xvmain.o xvdisp.o xvmc.o +#endif + +#if BuildXResExt + XRESSRCS = xres.c + XRESOBJS = xres.o +#endif + +#if BuildAppgroup + APPGROUPSRCS = appgroup.c + APPGROUPOBJS = appgroup.o +#endif +#if BuildXCSecurity + SECURITYSRCS = security.c + SECURITYOBJS = security.o + SERVERCONFIGDIR = ServerConfigDir + POLICYFILEDEF = -DDEFAULTPOLICYFILE=\"$(SERVERCONFIGDIR)/SecurityPolicy\" +#endif +#if BuildCup + CUPSRCS = cup.c + CUPOBJS = cup.o +#endif +#if BuildXinerama + PNRXSRCS = panoramiX.c panoramiXSwap.c panoramiXprocs.c + PNRXOBJS = panoramiX.o panoramiXSwap.o panoramiXprocs.o + PNRXINCLUDES = -I$(FONTINCSRC) -I../mi -I../render +#endif +#if XdmxServer + DMXSRCS = dmx.c + DMXOBJS = dmx.o + DMXINCLUDES = -I../hw/dmx +#endif +#if BuildDPMS + DPMSSRCS = dpms.c + DPMSOBJS = dpms.o +#endif + +#if BuildFontCache + FONTCACHESRCS = fontcache.c + FONTCACHEOBJS = fontcache.o +#if 0 + FONTCACHEINCLUDES = -I$(XF86SRC)/os-support +#endif +#endif + +#if BuildXevie + XEVIESRCS = xevie.c + XEVIEOBJS = xevie.o +#endif + +#if BuildXprint + XPRINTSRCS = xprint.c + XPRINTOBJS = xprint.o +#endif + + SRCS = shape.c $(SHMSRCS) $(MULTIBUFSRC) \ + mitmisc.c xtest.c xtest1di.c xtest1dd.c sleepuntil.c \ + bigreq.c sync.c $(SCRNSAVSRC) xcmisc.c $(VIDMODESRCS) \ + $(XF86MISCSRCS) $(XF86BIGFSRCS) $(XF86DGASRCS) $(SECURITYSRCS) \ + $(APPGROUPSRCS) $(XPRINTSRCS) $(CUPSRCS) $(PNRXSRCS) $(DPMSSRCS) \ + $(XEVIESRCS) \ + $(EVISRCS) $(XVSRCS) $(FONTCACHESRCS) $(XRESSRCS) $(DMXSRCS) + + OBJS = shape.o $(SHMOBJS) $(MULTIBUFOBJ) \ + mitmisc.o xtest.o xtest1di.o xtest1dd.o sleepuntil.o \ + bigreq.o sync.o $(SCRNSAVOBJ) xcmisc.o $(VIDMODEOBJS) \ + $(XF86MISCOBJS) $(XF86BIGFOBJS) $(XF86DGAOBJS) $(SECURITYOBJS) \ + $(APPGROUPOBJS) $(XPRINTOBJS) $(CUPOBJS) $(PNRXOBJS) $(DPMSOBJS) \ + $(XEVIEOBJS) \ + $(EVIOBJS) $(XVOBJS) $(FONTCACHEOBJS) $(XRESOBJS) $(DMXOBJS) + + SOBJS = $(SHMOBJS) $(APPGROUPOBJS) $(SECURITYOBJS) $(XPRINTOBJS) \ + shape.o xtest.o xtest1di.o xtest1dd.o sleepuntil.o $(PNRXOBJS) \ + $(XEVIEOBJS) \ + $(XF86BIGFOBJS) + +#if defined(NXAgentServer) && NXAgentServer +NX_DEFINES = -DNXAGENT_SERVER +#endif + + +#if (defined(XFree86Version) || defined(XorgVersion)) +/* XXX Check if this can be eliminated */ +XF86INCLUDES = -I$(XF86COMSRC) +#endif + INCLUDES = -I. -I../include -I$(XINCLUDESRC) -I$(EXTINCSRC) \ + $(PNRXINCLUDES) $(XF86INCLUDES) -I$(FONTINCSRC) \ + $(FONTCACHEINCLUDES) $(DMXINCLUDES) + LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln + +#if defined(NXAgentServer) && NXAgentServer + DEFINES = $(EXT_DEFINES) $(XVMCSHM_DEFINES) $(NX_DEFINES) +#else + DEFINES = $(EXT_DEFINES) $(XVMCSHM_DEFINES) +#endif + +NormalLibraryObjectRule() + +/* + * A hack to work around an optimization problem with gcc 2.95.2 + */ +#if BuildXF86VidModeExt && defined(GccOptBug295) +SpecialCObjectRule(xf86vmode,NullParameter,-O0) +#endif + +NormalLibraryTarget(ext,$(OBJS)) +LintLibraryTarget(ext,$(SRCS)) +NormalLintTarget($(SRCS)) + +#if DoLoadableServer +NormalLibraryTarget(exts,$(SOBJS)) +#endif + +#if BuildXF86BigfontExt +SpecialCObjectRule(xf86bigfont,$(ICONFIGFILES),$(SHM_DEFINES)) +#endif +#if BuildXCSecurity +SpecialCObjectRule(security,$(ICONFIGFILES),$(POLICYFILEDEF)) +#endif + +LinkConfDirectory(xserver,.,xserver,.) + +LinkSourceFile(modinit.h,extmod) + +#if BuildXCSecurity && InstallSecurityConfig +InstallNonExecFile(SecurityPolicy,$(SERVERCONFIGDIR)) +#endif + +DependTarget() + +#if DoLoadableServer +MakeSubdirs($(SUBDIRS)) +DependSubdirs($(SUBDIRS)) +#endif + +InstallDriverSDKNonExecFile(dgaproc.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xvdix.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xvmcext.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/nx-X11/programs/Xserver/Xext/Imakefile.X.original b/nx-X11/programs/Xserver/Xext/Imakefile.X.original new file mode 100644 index 000000000..f2753b3f4 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/Imakefile.X.original @@ -0,0 +1,200 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/Imakefile,v 1.9 2005/04/24 01:10:12 gisburn Exp $ */ +XCOMM $Xorg: Imakefile,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ + + + + +XCOMM $XFree86: xc/programs/Xserver/Xext/Imakefile,v 3.43 2003/04/21 18:56:48 sven Exp $ + +#include <Server.tmpl> + +#if DoLoadableServer +#define IHaveSubdirs +SUBDIRS = extmod +#endif + +#if BuildEVI +#ifdef SGIArchitectureNotTog + EVISRCS = EVI.c sgiEVI.c + EVIOBJS = EVI.o sgiEVI.o +#else + EVISRCS = EVI.c sampleEVI.c + EVIOBJS = EVI.o sampleEVI.o +#endif +#endif +#if HasShm + SHMSRCS = shm.c + SHMOBJS = shm.o +#endif + +#if BuildMultibuffer + MULTIBUFSRC = mbuf.c + MULTIBUFOBJ = mbuf.o +#endif + +#if BuildScreenSaverExt + SCRNSAVSRC = saver.c + SCRNSAVOBJ = saver.o +#endif + +#if BuildXF86VidModeExt && \ + ((defined(XF86Server) && XF86Server) || \ + (defined(XorgServer) && XorgServer)) + VIDMODESRCS = xf86vmode.c + VIDMODEOBJS = xf86vmode.o +#endif + +#if BuildXF86MiscExt && \ + ((defined(XF86Server) && XF86Server) || \ + (defined(XorgServer) && XorgServer)) +XF86MISCSRCS = xf86misc.c +XF86MISCOBJS = xf86misc.o +#endif + +#if BuildXF86BigfontExt +XF86BIGFSRCS = xf86bigfont.c +XF86BIGFOBJS = xf86bigfont.o +#if HasShm + SHM_DEFINES = -DHAS_SHM +#endif +#endif + +#if BuildXF86DGA + XF86DGASRCS = xf86dga.c xf86dga2.c + XF86DGAOBJS = xf86dga.o xf86dga2.o +#if HasShm + XVMCSHM_DEFINES = -DHAS_XVMCSHM +#endif +#endif + +#if BuildXvExt + XVSRCS = xvmain.c xvdisp.c xvmc.c + XVOBJS = xvmain.o xvdisp.o xvmc.o +#endif + +#if BuildXResExt + XRESSRCS = xres.c + XRESOBJS = xres.o +#endif + +#if BuildAppgroup + APPGROUPSRCS = appgroup.c + APPGROUPOBJS = appgroup.o +#endif +#if BuildXCSecurity + SECURITYSRCS = security.c + SECURITYOBJS = security.o + SERVERCONFIGDIR = ServerConfigDir + POLICYFILEDEF = -DDEFAULTPOLICYFILE=\"$(SERVERCONFIGDIR)/SecurityPolicy\" +#endif +#if BuildCup + CUPSRCS = cup.c + CUPOBJS = cup.o +#endif +#if BuildXinerama + PNRXSRCS = panoramiX.c panoramiXSwap.c panoramiXprocs.c + PNRXOBJS = panoramiX.o panoramiXSwap.o panoramiXprocs.o + PNRXINCLUDES = -I$(FONTINCSRC) -I../mi -I../render +#endif +#if XdmxServer + DMXSRCS = dmx.c + DMXOBJS = dmx.o + DMXINCLUDES = -I../hw/dmx +#endif +#if BuildDPMS + DPMSSRCS = dpms.c + DPMSOBJS = dpms.o +#endif + +#if BuildFontCache + FONTCACHESRCS = fontcache.c + FONTCACHEOBJS = fontcache.o +#if 0 + FONTCACHEINCLUDES = -I$(XF86SRC)/os-support +#endif +#endif + +#if BuildXevie + XEVIESRCS = xevie.c + XEVIEOBJS = xevie.o +#endif + +#if BuildXprint + XPRINTSRCS = xprint.c + XPRINTOBJS = xprint.o +#endif + + SRCS = shape.c $(SHMSRCS) $(MULTIBUFSRC) \ + mitmisc.c xtest.c xtest1di.c xtest1dd.c sleepuntil.c \ + bigreq.c sync.c $(SCRNSAVSRC) xcmisc.c $(VIDMODESRCS) \ + $(XF86MISCSRCS) $(XF86BIGFSRCS) $(XF86DGASRCS) $(SECURITYSRCS) \ + $(APPGROUPSRCS) $(XPRINTSRCS) $(CUPSRCS) $(PNRXSRCS) $(DPMSSRCS) \ + $(XEVIESRCS) \ + $(EVISRCS) $(XVSRCS) $(FONTCACHESRCS) $(XRESSRCS) $(DMXSRCS) + + OBJS = shape.o $(SHMOBJS) $(MULTIBUFOBJ) \ + mitmisc.o xtest.o xtest1di.o xtest1dd.o sleepuntil.o \ + bigreq.o sync.o $(SCRNSAVOBJ) xcmisc.o $(VIDMODEOBJS) \ + $(XF86MISCOBJS) $(XF86BIGFOBJS) $(XF86DGAOBJS) $(SECURITYOBJS) \ + $(APPGROUPOBJS) $(XPRINTOBJS) $(CUPOBJS) $(PNRXOBJS) $(DPMSOBJS) \ + $(XEVIEOBJS) \ + $(EVIOBJS) $(XVOBJS) $(FONTCACHEOBJS) $(XRESOBJS) $(DMXOBJS) + + SOBJS = $(SHMOBJS) $(APPGROUPOBJS) $(SECURITYOBJS) $(XPRINTOBJS) \ + shape.o xtest.o xtest1di.o xtest1dd.o sleepuntil.o $(PNRXOBJS) \ + $(XEVIEOBJS) \ + $(XF86BIGFOBJS) + +#if (defined(XFree86Version) || defined(XorgVersion)) +/* XXX Check if this can be eliminated */ +XF86INCLUDES = -I$(XF86COMSRC) +#endif + INCLUDES = -I. -I../include -I$(XINCLUDESRC) -I$(EXTINCSRC) \ + $(PNRXINCLUDES) $(XF86INCLUDES) -I$(FONTINCSRC) \ + $(FONTCACHEINCLUDES) $(DMXINCLUDES) + LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln + + DEFINES = $(EXT_DEFINES) $(XVMCSHM_DEFINES) + +NormalLibraryObjectRule() + +/* + * A hack to work around an optimization problem with gcc 2.95.2 + */ +#if BuildXF86VidModeExt && defined(GccOptBug295) +SpecialCObjectRule(xf86vmode,NullParameter,-O0) +#endif + +NormalLibraryTarget(ext,$(OBJS)) +LintLibraryTarget(ext,$(SRCS)) +NormalLintTarget($(SRCS)) + +#if DoLoadableServer +NormalLibraryTarget(exts,$(SOBJS)) +#endif + +#if BuildXF86BigfontExt +SpecialCObjectRule(xf86bigfont,$(ICONFIGFILES),$(SHM_DEFINES)) +#endif +#if BuildXCSecurity +SpecialCObjectRule(security,$(ICONFIGFILES),$(POLICYFILEDEF)) +#endif + +LinkConfDirectory(xserver,.,xserver,.) + +LinkSourceFile(modinit.h,extmod) + +#if BuildXCSecurity && InstallSecurityConfig +InstallNonExecFile(SecurityPolicy,$(SERVERCONFIGDIR)) +#endif + +DependTarget() + +#if DoLoadableServer +MakeSubdirs($(SUBDIRS)) +DependSubdirs($(SUBDIRS)) +#endif + +InstallDriverSDKNonExecFile(dgaproc.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xvdix.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xvmcext.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/nx-X11/programs/Xserver/Xext/SecurityPolicy b/nx-X11/programs/Xserver/Xext/SecurityPolicy new file mode 100644 index 000000000..cc521c263 --- /dev/null +++ b/nx-X11/programs/Xserver/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/nx-X11/programs/Xserver/Xext/appgroup.c b/nx-X11/programs/Xserver/Xext/appgroup.c new file mode 100644 index 000000000..ad4afa9e4 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/appgroup.c @@ -0,0 +1,829 @@ +/* $XFree86: xc/programs/Xserver/Xext/appgroup.c,v 1.10tsi Exp $ */ +/* +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 +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/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 <X11/extensions/Xagstr.h> +#include <X11/extensions/Xagsrv.h> +#define _SECURITY_SERVER +#include <X11/extensions/security.h> +#include <X11/Xfuncproto.h> + +#define XSERV_t +#include <X11/Xtrans/Xtrans.h> +#include "../os/osdep.h" + +#include <stdio.h> + +#include "modinit.h" +#include "appgroup.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(ClientPtr client); +static int SProcXagDispatch(ClientPtr client); +static void XagResetProc(ExtensionEntry* extEntry); + +#if 0 +static unsigned char XagReqCode = 0; +static int XagErrorBase; +#endif +static int XagCallbackRefCount = 0; + +static RESTYPE RT_APPGROUP; +static AppGroupPtr appGrpList = NULL; + +extern xConnSetupPrefix connSetupPrefix; +extern char* ConnectionInfo; +extern int connBlockScreenStart; + +static +int XagAppGroupFree( + 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( + CallbackListPtr* pcbl, + pointer nulldata, + pointer calldata) +{ + SecurityAuthorizationPtr pAuth; + NewClientInfoRec* pci = (NewClientInfoRec*) calldata; + ClientPtr pClient = pci->client; + AppGroupPtr pAppGrp; + XID authId = 0; + + 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(INITARGS) +{ +#if 0 + ExtensionEntry* extEntry; + + if ((extEntry = AddExtension (XAGNAME, + 0, + XagNumberErrors, + ProcXagDispatch, + SProcXagDispatch, + XagResetProc, + StandardMinorOpcode))) { + XagReqCode = (unsigned char)extEntry->base; + XagErrorBase = extEntry->errorBase; +#else + if (AddExtension (XAGNAME, + 0, + XagNumberErrors, + ProcXagDispatch, + SProcXagDispatch, + XagResetProc, + StandardMinorOpcode)) { +#endif + RT_APPGROUP = CreateNewResourceType (XagAppGroupFree); + } +} + +/*ARGSUSED*/ +static +void XagResetProc( + ExtensionEntry* extEntry) +{ + DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL); + XagCallbackRefCount = 0; + while (appGrpList) XagAppGroupFree ((pointer) appGrpList, 0); +} + +static +int ProcXagQueryVersion( + 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( + 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( + AppGroupPtr pAppGrp) +{ + 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( + ClientPtr client, + XID appgroupId, + unsigned int attrib_mask, + CARD32* attribs) +{ + AppGroupPtr pAppGrp; + + 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( + 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 ( + 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( + 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( + 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( + 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( + 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; +#if defined(WIN32) || defined(__CYGWIN__) /* 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( + 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 ( + 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( + register ClientPtr client) +{ + register int n; + REQUEST(xXagQueryVersionReq); + swaps(&stuff->length, n); + return ProcXagQueryVersion(client); +} + +static +int SProcXagCreate( + 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( + 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( + 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( + 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( + 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( + 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( + 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( + ClientPtr client) +{ + return (client->appgroup ? client->appgroup->default_colormap : None); +} + +VisualID XagRootVisual( + ClientPtr client) +{ + return (client->appgroup ? client->appgroup->root_visual : 0); +} + +ClientPtr XagLeader( + 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( + 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( + 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( + ClientPtr client) +{ + return (client->appgroup ? client->appgroup->appgroupId : 0); +} + +void XagGetDeltaInfo( + 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( + ClientPtr client) +{ + if (appGrpList) { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + XagClientStateChange (NULL, NULL, (pointer)&clientinfo); + } +} diff --git a/nx-X11/programs/Xserver/Xext/appgroup.h b/nx-X11/programs/Xserver/Xext/appgroup.h new file mode 100644 index 000000000..05c9ef124 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/appgroup.h @@ -0,0 +1,10 @@ +/* $XFree86$ */ + +void XagClientStateChange( + CallbackListPtr* pcbl, + pointer nulldata, + pointer calldata); +int ProcXagCreate ( + register ClientPtr client); +int ProcXagDestroy( + register ClientPtr client); diff --git a/nx-X11/programs/Xserver/Xext/bigreq.c b/nx-X11/programs/Xserver/Xext/bigreq.c new file mode 100644 index 000000000..1af8a930b --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/bigreq.c @@ -0,0 +1,107 @@ +/* $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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/bigreq.c,v 3.8 2003/10/28 23:08:43 tsi Exp $ */ + +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include <X11/extensions/bigreqstr.h> +#include "opaque.h" +#include "modinit.h" + +#if 0 +static unsigned char XBigReqCode; +#endif + +static void BigReqResetProc( + ExtensionEntry * /* extEntry */ +); + +static DISPATCH_PROC(ProcBigReqDispatch); + +void +BigReqExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XBigReqExtensionName, 0, 0, + ProcBigReqDispatch, ProcBigReqDispatch, + BigReqResetProc, StandardMinorOpcode)) != 0) + XBigReqCode = (unsigned char)extEntry->base; +#else + (void) AddExtension(XBigReqExtensionName, 0, 0, + ProcBigReqDispatch, ProcBigReqDispatch, + BigReqResetProc, StandardMinorOpcode); +#endif + + 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 = maxBigRequestSize; + 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/nx-X11/programs/Xserver/Xext/cup.c b/nx-X11/programs/Xserver/Xext/cup.c new file mode 100644 index 000000000..198aa801f --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/cup.c @@ -0,0 +1,367 @@ +/* $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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/cup.c,v 1.11tsi Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "swapreq.h" +#define _XCUP_SERVER_ +#include <X11/extensions/Xcupstr.h> +#include <X11/Xfuncproto.h> + +#ifndef EXTMODULE +#include "../os/osdep.h" +#else +#include "xf86_ansic.h" +#endif + +#include "modinit.h" + +static int ProcDispatch(ClientPtr client); +static int SProcDispatch(ClientPtr client); +static void ResetProc(ExtensionEntry* extEntry); + +#if 0 +static unsigned char ReqCode = 0; +static int ErrorBase; +#endif + +#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 (INITARGS) +{ +#if 0 + ExtensionEntry* extEntry; + + if ((extEntry = AddExtension (XCUPNAME, + 0, + XcupNumberErrors, + ProcDispatch, + SProcDispatch, + ResetProc, + StandardMinorOpcode))) { + ReqCode = (unsigned char)extEntry->base; + ErrorBase = extEntry->errorBase; + } +#else + (void) AddExtension (XCUPNAME, + 0, + XcupNumberErrors, + ProcDispatch, + SProcDispatch, + ResetProc, + StandardMinorOpcode); +#endif + + /* PC servers initialize the desktop colors (citems) here! */ +} + +/*ARGSUSED*/ +static +void ResetProc( + ExtensionEntry* extEntry) +{ +} + +static +int ProcQueryVersion( + 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( + register ClientPtr client) +{ + REQUEST (xXcupGetReservedColormapEntriesReq); + xXcupGetReservedColormapEntriesReply rep; + xColorItem* cptr; + register int n; + + REQUEST_SIZE_MATCH (xXcupGetReservedColormapEntriesReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + +#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( + 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; + + 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( + 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( + register ClientPtr client) +{ + register int n; + + REQUEST(xXcupQueryVersionReq); + swaps(&stuff->length, n); + return ProcQueryVersion(client); +} + +static +int SProcGetReservedColormapEntries( + 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 SProcXcupStoreColors( + 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( + register ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XcupQueryVersion: + return SProcQueryVersion (client); + case X_XcupGetReservedColormapEntries: + return SProcGetReservedColormapEntries (client); + case X_XcupStoreColors: + return SProcXcupStoreColors (client); + default: + return BadRequest; + } +} + + diff --git a/nx-X11/programs/Xserver/Xext/dgaproc.h b/nx-X11/programs/Xserver/Xext/dgaproc.h new file mode 100644 index 000000000..eb9791098 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/dgaproc.h @@ -0,0 +1,144 @@ +/* $XFree86: xc/programs/Xserver/Xext/dgaproc.h,v 1.21 2000/06/30 19:06:54 keithp Exp $ */ + +#ifndef __DGAPROC_H +#define __DGAPROC_H + +#include <X11/Xproto.h> +#include "pixmap.h" + +#define DGA_CONCURRENT_ACCESS 0x00000001 +#define DGA_FILL_RECT 0x00000002 +#define DGA_BLIT_RECT 0x00000004 +#define DGA_BLIT_RECT_TRANS 0x00000008 +#define DGA_PIXMAP_AVAILABLE 0x00000010 + +#define DGA_INTERLACED 0x00010000 +#define DGA_DOUBLESCAN 0x00020000 + +#define DGA_FLIP_IMMEDIATE 0x00000001 +#define DGA_FLIP_RETRACE 0x00000002 + +#define DGA_COMPLETED 0x00000000 +#define DGA_PENDING 0x00000001 + +#define DGA_NEED_ROOT 0x00000001 + +typedef struct { + int num; /* A unique identifier for the mode (num > 0) */ + char *name; /* name of mode given in the XF86Config */ + int VSync_num; + int VSync_den; + int flags; /* DGA_CONCURRENT_ACCESS, etc... */ + int imageWidth; /* linear accessible portion (pixels) */ + int imageHeight; + int pixmapWidth; /* Xlib accessible portion (pixels) */ + int pixmapHeight; /* both fields ignored if no concurrent access */ + int bytesPerScanline; + int byteOrder; /* MSBFirst, LSBFirst */ + int depth; + int bitsPerPixel; + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + short visualClass; + int viewportWidth; + int viewportHeight; + int xViewportStep; /* viewport position granularity */ + int yViewportStep; + int maxViewportX; /* max viewport origin */ + int maxViewportY; + int viewportFlags; /* types of page flipping possible */ + int offset; + int reserved1; + int reserved2; +} XDGAModeRec, *XDGAModePtr; + +/* DDX interface */ + +int +DGASetMode( + int Index, + int num, + XDGAModePtr mode, + PixmapPtr *pPix +); + +void +DGASetInputMode( + int Index, + Bool keyboard, + Bool mouse +); + +void +DGASelectInput( + int Index, + ClientPtr client, + long mask +); + +Bool DGAAvailable(int Index); +Bool DGAActive(int Index); +void DGAShutdown(void); +void DGAInstallCmap(ColormapPtr cmap); +int DGAGetViewportStatus(int Index); +int DGASync(int Index); + +int +DGAFillRect( + int Index, + int x, int y, int w, int h, + unsigned long color +); + +int +DGABlitRect( + int Index, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +); + +int +DGABlitTransRect( + int Index, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +); + +int +DGASetViewport( + int Index, + int x, int y, + int mode +); + +int DGAGetModes(int Index); +int DGAGetOldDGAMode(int Index); + +int DGAGetModeInfo(int Index, XDGAModePtr mode, int num); + +Bool DGAVTSwitch(void); +Bool DGAStealMouseEvent(int Index, xEvent *e, int dx, int dy); +Bool DGAStealKeyEvent(int Index, xEvent *e); +Bool DGAIsDgaEvent (xEvent *e); + +Bool DGADeliverEvent (ScreenPtr pScreen, xEvent *e); + +Bool DGAOpenFramebuffer(int Index, char **name, unsigned char **mem, + int *size, int *offset, int *flags); +void DGACloseFramebuffer(int Index); +Bool DGAChangePixmapMode(int Index, int *x, int *y, int mode); +int DGACreateColormap(int Index, ClientPtr client, int id, int mode, + int alloc); + +extern unsigned char DGAReqCode; +extern int DGAErrorBase; +extern int DGAEventBase; +extern int *XDGAEventBase; + + + +#endif /* __DGAPROC_H */ diff --git a/nx-X11/programs/Xserver/Xext/dmx.c b/nx-X11/programs/Xserver/Xext/dmx.c new file mode 100644 index 000000000..75623e696 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/dmx.c @@ -0,0 +1,1133 @@ +/* $XFree86$ */ +/* + * Copyright 2002-2004 Red Hat Inc., Durham, North Carolina. + * + * All Rights Reserved. + * + * 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 on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS + * 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. + */ + +/* + * Authors: + * Rickard E. (Rik) Faith <faith@redhat.com> + * + */ + +/** \file + * This file implements the server-side part of the DMX protocol. A + * vector of fucntions is provided at extension initialization time, so + * most all of the useful functions in this file are declared static and + * do not appear in the doxygen documentation. + * + * Much of the low-level work is done by functions in #dmxextension.c + * + * Please see the Client-to-Server DMX Extension to the X Protocol + * document for details about the protocol. */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#define EXTENSION_PROC_ARGS void * +#include "extnsionst.h" +#include "opaque.h" + +#include "dmxextension.h" +#include <X11/extensions/dmxproto.h> + +#define _DMX_SERVER_ +#include <X11/extensions/dmxext.h> + +#ifdef PANORAMIX +#include "panoramiX.h" +extern unsigned long XRT_WINDOW; +extern int PanoramiXNumScreens; +#endif + +extern void DMXExtensionInit(void); + +static unsigned char DMXCode; + +static DISPATCH_PROC(ProcDMXDispatch); +static DISPATCH_PROC(ProcDMXQueryVersion); +static DISPATCH_PROC(ProcDMXSync); +static DISPATCH_PROC(ProcDMXForceWindowCreation); +static DISPATCH_PROC(ProcDMXGetScreenCount); +static DISPATCH_PROC(ProcDMXGetScreenAttributes); +static DISPATCH_PROC(ProcDMXChangeScreensAttributes); +static DISPATCH_PROC(ProcDMXAddScreen); +static DISPATCH_PROC(ProcDMXRemoveScreen); +static DISPATCH_PROC(ProcDMXGetWindowAttributes); +static DISPATCH_PROC(ProcDMXGetDesktopAttributes); +static DISPATCH_PROC(ProcDMXChangeDesktopAttributes); +static DISPATCH_PROC(ProcDMXGetInputCount); +static DISPATCH_PROC(ProcDMXGetInputAttributes); +static DISPATCH_PROC(ProcDMXAddInput); +static DISPATCH_PROC(ProcDMXRemoveInput); + +static DISPATCH_PROC(SProcDMXDispatch); +static DISPATCH_PROC(SProcDMXQueryVersion); +static DISPATCH_PROC(SProcDMXSync); +static DISPATCH_PROC(SProcDMXForceWindowCreation); +static DISPATCH_PROC(SProcDMXGetScreenCount); +static DISPATCH_PROC(SProcDMXGetScreenAttributes); +static DISPATCH_PROC(SProcDMXChangeScreensAttributes); +static DISPATCH_PROC(SProcDMXAddScreen); +static DISPATCH_PROC(SProcDMXRemoveScreen); +static DISPATCH_PROC(SProcDMXGetWindowAttributes); +static DISPATCH_PROC(SProcDMXGetDesktopAttributes); +static DISPATCH_PROC(SProcDMXChangeDesktopAttributes); +static DISPATCH_PROC(SProcDMXGetInputCount); +static DISPATCH_PROC(SProcDMXGetInputAttributes); +static DISPATCH_PROC(SProcDMXAddInput); +static DISPATCH_PROC(SProcDMXRemoveInput); + +static int _DMXXineramaActive(void) +{ +#ifdef PANORAMIX + return !noPanoramiXExtension; +#endif + return 0; +} + +static void DMXResetProc(ExtensionEntry *extEntry) +{ +} + +/** Initialize the extension. */ +void DMXExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0, + ProcDMXDispatch, SProcDMXDispatch, + DMXResetProc, StandardMinorOpcode))) + DMXCode = extEntry->base; +} + +static void dmxSetScreenAttribute(int bit, DMXScreenAttributesPtr attr, + CARD32 value) +{ + switch (1 << bit) { + case DMXScreenWindowWidth: attr->screenWindowWidth = value; break; + case DMXScreenWindowHeight: attr->screenWindowHeight = value; break; + case DMXScreenWindowXoffset: attr->screenWindowXoffset = value; break; + case DMXScreenWindowYoffset: attr->screenWindowYoffset = value; break; + case DMXRootWindowWidth: attr->rootWindowWidth = value; break; + case DMXRootWindowHeight: attr->rootWindowHeight = value; break; + case DMXRootWindowXoffset: attr->rootWindowXoffset = value; break; + case DMXRootWindowYoffset: attr->rootWindowYoffset = value; break; + case DMXRootWindowXorigin: attr->rootWindowXorigin = value; break; + case DMXRootWindowYorigin: attr->rootWindowYorigin = value; break; + } +} + +static int dmxFetchScreenAttributes(unsigned int mask, + DMXScreenAttributesPtr attr, + CARD32 *value_list) +{ + int i; + CARD32 *value = value_list; + int count = 0; + + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { + dmxSetScreenAttribute(i, attr, *value); + ++value; + ++count; + } + } + return count; +} + +static void dmxSetDesktopAttribute(int bit, DMXDesktopAttributesPtr attr, + CARD32 value) +{ + switch (1 << bit) { + case DMXDesktopWidth: attr->width = value; break; + case DMXDesktopHeight: attr->height = value; break; + case DMXDesktopShiftX: attr->shiftX = value; break; + case DMXDesktopShiftY: attr->shiftY = value; break; + } +} + +static int dmxFetchDesktopAttributes(unsigned int mask, + DMXDesktopAttributesPtr attr, + CARD32 *value_list) +{ + int i; + CARD32 *value = value_list; + int count = 0; + + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { + dmxSetDesktopAttribute(i, attr, *value); + ++value; + ++count; + } + } + return count; +} + +static void dmxSetInputAttribute(int bit, DMXInputAttributesPtr attr, + CARD32 value) +{ + switch (1 << bit) { + case DMXInputType: attr->inputType = value; break; + case DMXInputPhysicalScreen: attr->physicalScreen = value; break; + case DMXInputSendsCore: attr->sendsCore = !!value; break; + } +} + +static int dmxFetchInputAttributes(unsigned int mask, + DMXInputAttributesPtr attr, + CARD32 *value_list) +{ + int i; + CARD32 *value = value_list; + int count = 0; + + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { + dmxSetInputAttribute(i, attr, *value); + ++value; + ++count; + } + } + return count; +} + +static int ProcDMXQueryVersion(ClientPtr client) +{ + xDMXQueryVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXQueryVersionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.majorVersion = DMX_EXTENSION_MAJOR; + rep.minorVersion = DMX_EXTENSION_MINOR; + rep.patchVersion = DMX_EXTENSION_PATCH; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + swapl(&rep.patchVersion, n); + } + WriteToClient(client, sizeof(xDMXQueryVersionReply), (char *)&rep); + return client->noClientException; +} + +static int ProcDMXSync(ClientPtr client) +{ + xDMXSyncReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXSyncReq); + + dmxFlushPendingSyncs(); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xDMXSyncReply), (char *)&rep); + return client->noClientException; +} + +static int ProcDMXForceWindowCreation(ClientPtr client) +{ + xDMXForceWindowCreationReply rep; + REQUEST(xDMXForceWindowCreationReq); + WindowPtr pWin; + int n; + + REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq); + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + PanoramiXRes *win; + int i; + + if (!(win = SecurityLookupIDByType(client, stuff->window, XRT_WINDOW, + SecurityReadAccess))) + return -1; /* BadWindow */ + + FOR_NSCREENS(i) { + if (!(pWin = SecurityLookupWindow(win->info[i].id, client, + SecurityReadAccess))) + return -1; /* BadWindow */ + + dmxForceWindowCreation(pWin); + } + goto doreply; + } +#endif + + if (!(pWin = SecurityLookupWindow(stuff->window, client, + SecurityReadAccess))) + return -1; /* BadWindow */ + + dmxForceWindowCreation(pWin); + doreply: + dmxFlushPendingSyncs(); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xDMXForceWindowCreationReply), (char *)&rep); + return Success; +} + +static int ProcDMXGetScreenCount(ClientPtr client) +{ + xDMXGetScreenCountReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXGetScreenCountReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.screenCount = dmxGetNumScreens(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.screenCount, n); + } + WriteToClient(client, sizeof(xDMXGetScreenCountReply), (char *)&rep); + return client->noClientException; +} + +static int ProcDMXGetScreenAttributes(ClientPtr client) +{ + REQUEST(xDMXGetScreenAttributesReq); + xDMXGetScreenAttributesReply rep; + int n; + int length; + int paddedLength; + DMXScreenAttributesRec attr; + + REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq); + + if (stuff->physicalScreen < 0 + || stuff->physicalScreen >= dmxGetNumScreens()) return BadValue; + + if (!dmxGetScreenAttributes(stuff->physicalScreen, &attr)) + return BadValue; + + rep.logicalScreen = attr.logicalScreen; + rep.screenWindowWidth = attr.screenWindowWidth; + rep.screenWindowHeight = attr.screenWindowHeight; + rep.screenWindowXoffset = attr.screenWindowXoffset; + rep.screenWindowYoffset = attr.screenWindowYoffset; + rep.rootWindowWidth = attr.rootWindowWidth; + rep.rootWindowHeight = attr.rootWindowHeight; + rep.rootWindowXoffset = attr.rootWindowXoffset; + rep.rootWindowYoffset = attr.rootWindowYoffset; + rep.rootWindowXorigin = attr.rootWindowXorigin; + rep.rootWindowYorigin = attr.rootWindowYorigin; + + length = attr.displayName ? strlen(attr.displayName) : 0; + paddedLength = (length + 3) & ~3; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = paddedLength >> 2; + rep.displayNameLength = length; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.displayNameLength, n); + swapl(&rep.logicalScreen, n); + swaps(&rep.screenWindowWidth, n); + swaps(&rep.screenWindowHeight, n); + swaps(&rep.screenWindowXoffset, n); + swaps(&rep.screenWindowYoffset, n); + swaps(&rep.rootWindowWidth, n); + swaps(&rep.rootWindowHeight, n); + swaps(&rep.rootWindowXoffset, n); + swaps(&rep.rootWindowYoffset, n); + swaps(&rep.rootWindowXorigin, n); + swaps(&rep.rootWindowYorigin, n); + } + WriteToClient(client, sizeof(xDMXGetScreenAttributesReply), (char *)&rep); + if (length) WriteToClient(client, length, (char *)attr.displayName); + return client->noClientException; +} + +static int ProcDMXChangeScreensAttributes(ClientPtr client) +{ + REQUEST(xDMXChangeScreensAttributesReq); + xDMXChangeScreensAttributesReply rep; + int n; + int status = DMX_BAD_XINERAMA; + unsigned int mask = 0; + unsigned int i; + CARD32 *screen_list; + CARD32 *mask_list; + CARD32 *value_list; + DMXScreenAttributesPtr attribs; + int errorScreen = 0; + unsigned int len; + int ones = 0; + + + REQUEST_AT_LEAST_SIZE(xDMXChangeScreensAttributesReq); + len = client->req_len - (sizeof(xDMXChangeScreensAttributesReq) >> 2); + if (len < stuff->screenCount + stuff->maskCount) + return BadLength; + + screen_list = (CARD32 *)(stuff + 1); + mask_list = &screen_list[stuff->screenCount]; + value_list = &mask_list[stuff->maskCount]; + + for (i = 0; i < stuff->maskCount; i++) ones += Ones(mask_list[i]); + if (len != stuff->screenCount + stuff->maskCount + ones) + return BadLength; + + if (!_DMXXineramaActive()) goto noxinerama; + + if (!(attribs = ALLOCATE_LOCAL(stuff->screenCount * sizeof(*attribs)))) + return BadAlloc; + + for (i = 0; i < stuff->screenCount; i++) { + int count; + + if (i < stuff->maskCount) mask = mask_list[i]; + dmxGetScreenAttributes(screen_list[i], &attribs[i]); + count = dmxFetchScreenAttributes(mask, &attribs[i], value_list); + value_list += count; + } + +#if PANORAMIX + status = dmxConfigureScreenWindows(stuff->screenCount, + screen_list, + attribs, + &errorScreen); +#endif + + DEALLOCATE_LOCAL(attribs); + + if (status == BadValue) return status; + + noxinerama: + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + rep.errorScreen = errorScreen; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + swapl(&rep.errorScreen, n); + } + WriteToClient(client, + sizeof(xDMXChangeScreensAttributesReply), + (char *)&rep); + return client->noClientException; +} + +static int ProcDMXAddScreen(ClientPtr client) +{ + REQUEST(xDMXAddScreenReq); + xDMXAddScreenReply rep; + int n; + int status = 0; + CARD32 *value_list; + DMXScreenAttributesRec attr; + int count; + char *name; + int len; + int paddedLength; + + REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq); + paddedLength = (stuff->displayNameLength + 3) & ~3; + len = client->req_len - (sizeof(xDMXAddScreenReq) >> 2); + if (len != Ones(stuff->valueMask) + paddedLength/4) + return BadLength; + + memset(&attr, 0, sizeof(attr)); + dmxGetScreenAttributes(stuff->physicalScreen, &attr); + value_list = (CARD32 *)(stuff + 1); + count = dmxFetchScreenAttributes(stuff->valueMask, &attr, value_list); + + if (!(name = ALLOCATE_LOCAL(stuff->displayNameLength + 1 + 4))) + return BadAlloc; + memcpy(name, &value_list[count], stuff->displayNameLength); + name[stuff->displayNameLength] = '\0'; + attr.displayName = name; + + status = dmxAttachScreen(stuff->physicalScreen, &attr); + + DEALLOCATE_LOCAL(name); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + rep.physicalScreen = stuff->physicalScreen; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + swapl(&rep.physicalScreen, n); + } + WriteToClient(client, + sizeof(xDMXAddScreenReply), + (char *)&rep); + return client->noClientException; +} + +static int ProcDMXRemoveScreen(ClientPtr client) +{ + REQUEST(xDMXRemoveScreenReq); + xDMXRemoveScreenReply rep; + int n; + int status = 0; + + REQUEST_SIZE_MATCH(xDMXRemoveScreenReq); + + status = dmxDetachScreen(stuff->physicalScreen); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, + sizeof(xDMXRemoveScreenReply), + (char *)&rep); + return client->noClientException; +} + + +#ifdef PANORAMIX +static int dmxPopulatePanoramiX(ClientPtr client, Window window, + CARD32 *screens, CARD32 *windows, + xRectangle *pos, xRectangle *vis) +{ + WindowPtr pWin; + PanoramiXRes *win; + int i; + int count = 0; + DMXWindowAttributesRec attr; + + if (!(win = SecurityLookupIDByType(client, window, XRT_WINDOW, + SecurityReadAccess))) + return -1; /* BadWindow */ + + FOR_NSCREENS(i) { + if (!(pWin = SecurityLookupWindow(win->info[i].id, client, + SecurityReadAccess))) + return -1; /* BadWindow */ + if (dmxGetWindowAttributes(pWin, &attr)) { + screens[count] = attr.screen; + windows[count] = attr.window; + pos[count] = attr.pos; + vis[count] = attr.vis; + ++count; /* Only count existing windows */ + } + } + return count; +} +#endif + +static int dmxPopulate(ClientPtr client, Window window, CARD32 *screens, + CARD32 *windows, xRectangle *pos, xRectangle *vis) +{ + WindowPtr pWin; + DMXWindowAttributesRec attr; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + return dmxPopulatePanoramiX(client, window, screens, windows, + pos, vis); +#endif + + if (!(pWin = SecurityLookupWindow(window, client, SecurityReadAccess))) + return -1; /* BadWindow */ + + dmxGetWindowAttributes(pWin, &attr); + *screens = attr.screen; + *windows = attr.window; + *pos = attr.pos; + *vis = attr.vis; + return 1; +} + +static int dmxMaxNumScreens(void) +{ +#ifdef PANORAMIX + if (!noPanoramiXExtension) return PanoramiXNumScreens; +#endif + return 1; +} + +static int ProcDMXGetWindowAttributes(ClientPtr client) +{ + REQUEST(xDMXGetWindowAttributesReq); + xDMXGetWindowAttributesReply rep; + int i, n; + CARD32 *screens; + CARD32 *windows; + xRectangle *pos, *vis; + int count = dmxMaxNumScreens(); + + REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq); + + if (!(screens = ALLOCATE_LOCAL(count * sizeof(*screens)))) + return BadAlloc; + if (!(windows = ALLOCATE_LOCAL(count * sizeof(*windows)))) { + DEALLOCATE_LOCAL(screens); + return BadAlloc; + } + if (!(pos = ALLOCATE_LOCAL(count * sizeof(*pos)))) { + DEALLOCATE_LOCAL(windows); + DEALLOCATE_LOCAL(screens); + return BadAlloc; + } + if (!(vis = ALLOCATE_LOCAL(count * sizeof(*vis)))) { + DEALLOCATE_LOCAL(pos); + DEALLOCATE_LOCAL(windows); + DEALLOCATE_LOCAL(screens); + return BadAlloc; + } + + if ((count = dmxPopulate(client, stuff->window, screens, windows, + pos, vis)) < 0) { + DEALLOCATE_LOCAL(vis); + DEALLOCATE_LOCAL(pos); + DEALLOCATE_LOCAL(windows); + DEALLOCATE_LOCAL(screens); + return BadWindow; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = count * 6; + rep.screenCount = count; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.screenCount, n); + for (i = 0; i < count; i++) { + swapl(&screens[i], n); + swapl(&windows[i], n); + + swaps(&pos[i].x, n); + swaps(&pos[i].y, n); + swaps(&pos[i].width, n); + swaps(&pos[i].height, n); + + swaps(&vis[i].x, n); + swaps(&vis[i].y, n); + swaps(&vis[i].width, n); + swaps(&vis[i].height, n); + } + } + + dmxFlushPendingSyncs(); + + WriteToClient(client, sizeof(xDMXGetWindowAttributesReply), (char *)&rep); + if (count) { + WriteToClient(client, count * sizeof(*screens), (char *)screens); + WriteToClient(client, count * sizeof(*windows), (char *)windows); + WriteToClient(client, count * sizeof(*pos), (char *)pos); + WriteToClient(client, count * sizeof(*vis), (char *)vis); + } + + DEALLOCATE_LOCAL(vis); + DEALLOCATE_LOCAL(pos); + DEALLOCATE_LOCAL(windows); + DEALLOCATE_LOCAL(screens); + + return client->noClientException; +} + +static int ProcDMXGetDesktopAttributes(ClientPtr client) +{ + xDMXGetDesktopAttributesReply rep; + int n; + DMXDesktopAttributesRec attr; + + REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq); + + dmxGetDesktopAttributes(&attr); + + rep.width = attr.width; + rep.height = attr.height; + rep.shiftX = attr.shiftX; + rep.shiftY = attr.shiftY; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.width, n); + swapl(&rep.height, n); + swapl(&rep.shiftX, n); + swapl(&rep.shiftY, n); + } + WriteToClient(client, sizeof(xDMXGetDesktopAttributesReply), (char *)&rep); + return client->noClientException; +} + +static int ProcDMXChangeDesktopAttributes(ClientPtr client) +{ + REQUEST(xDMXChangeDesktopAttributesReq); + xDMXChangeDesktopAttributesReply rep; + int n; + int status = DMX_BAD_XINERAMA; + CARD32 *value_list; + DMXDesktopAttributesRec attr; + int len; + + REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq); + len = client->req_len - (sizeof(xDMXChangeDesktopAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + + if (!_DMXXineramaActive()) goto noxinerama; + + value_list = (CARD32 *)(stuff + 1); + + dmxGetDesktopAttributes(&attr); + dmxFetchDesktopAttributes(stuff->valueMask, &attr, value_list); + +#if PANORAMIX + status = dmxConfigureDesktop(&attr); +#endif + if (status == BadValue) return status; + + noxinerama: + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, + sizeof(xDMXChangeDesktopAttributesReply), + (char *)&rep); + return client->noClientException; +} + +static int ProcDMXGetInputCount(ClientPtr client) +{ + xDMXGetInputCountReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXGetInputCountReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.inputCount = dmxGetInputCount(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.inputCount, n); + } + WriteToClient(client, sizeof(xDMXGetInputCountReply), (char *)&rep); + return client->noClientException; +} + +static int ProcDMXGetInputAttributes(ClientPtr client) +{ + REQUEST(xDMXGetInputAttributesReq); + xDMXGetInputAttributesReply rep; + int n; + int length; + int paddedLength; + DMXInputAttributesRec attr; + + REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq); + + if (dmxGetInputAttributes(stuff->deviceId, &attr)) return BadValue; + rep.inputType = attr.inputType; + rep.physicalScreen = attr.physicalScreen; + rep.physicalId = attr.physicalId; + rep.isCore = attr.isCore; + rep.sendsCore = attr.sendsCore; + rep.detached = attr.detached; + + length = attr.name ? strlen(attr.name) : 0; + paddedLength = (length + 3) & ~3; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = paddedLength >> 2; + rep.nameLength = length; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.inputType, n); + swapl(&rep.physicalScreen, n); + swapl(&rep.physicalId, n); + swapl(&rep.nameLength, n); + } + WriteToClient(client, sizeof(xDMXGetInputAttributesReply), (char *)&rep); + if (length) WriteToClient(client, length, (char *)attr.name); + return client->noClientException; +} + +static int ProcDMXAddInput(ClientPtr client) +{ + REQUEST(xDMXAddInputReq); + xDMXAddInputReply rep; + int n; + int status = 0; + CARD32 *value_list; + DMXInputAttributesRec attr; + int count; + char *name; + int len; + int paddedLength; + int id = -1; + + REQUEST_AT_LEAST_SIZE(xDMXAddInputReq); + paddedLength = (stuff->displayNameLength + 3) & ~3; + len = client->req_len - (sizeof(xDMXAddInputReq) >> 2); + if (len != Ones(stuff->valueMask) + paddedLength/4) + return BadLength; + + memset(&attr, 0, sizeof(attr)); + value_list = (CARD32 *)(stuff + 1); + count = dmxFetchInputAttributes(stuff->valueMask, &attr, value_list); + + if (!(name = ALLOCATE_LOCAL(stuff->displayNameLength + 1 + 4))) + return BadAlloc; + memcpy(name, &value_list[count], stuff->displayNameLength); + name[stuff->displayNameLength] = '\0'; + attr.name = name; + + status = dmxAddInput(&attr, &id); + + DEALLOCATE_LOCAL(name); + + if (status) return status; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + rep.physicalId = id; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + swapl(&rep.physicalId, n); + } + WriteToClient(client, sizeof(xDMXAddInputReply), (char *)&rep); + return client->noClientException; +} + +static int ProcDMXRemoveInput(ClientPtr client) +{ + REQUEST(xDMXRemoveInputReq); + xDMXRemoveInputReply rep; + int n; + int status = 0; + + REQUEST_SIZE_MATCH(xDMXRemoveInputReq); + + status = dmxRemoveInput(stuff->physicalId); + + if (status) return status; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xDMXRemoveInputReply), (char *)&rep); + return client->noClientException; +} + +static int ProcDMXDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_DMXQueryVersion: return ProcDMXQueryVersion(client); + case X_DMXSync: return ProcDMXSync(client); + case X_DMXForceWindowCreation: return ProcDMXForceWindowCreation(client); + case X_DMXGetScreenCount: return ProcDMXGetScreenCount(client); + case X_DMXGetScreenAttributes: return ProcDMXGetScreenAttributes(client); + case X_DMXChangeScreensAttributes: + return ProcDMXChangeScreensAttributes(client); + case X_DMXAddScreen: return ProcDMXAddScreen(client); + case X_DMXRemoveScreen: return ProcDMXRemoveScreen(client); + case X_DMXGetWindowAttributes: return ProcDMXGetWindowAttributes(client); + case X_DMXGetDesktopAttributes: return ProcDMXGetDesktopAttributes(client); + case X_DMXChangeDesktopAttributes: + return ProcDMXChangeDesktopAttributes(client); + case X_DMXGetInputCount: return ProcDMXGetInputCount(client); + case X_DMXGetInputAttributes: return ProcDMXGetInputAttributes(client); + case X_DMXAddInput: return ProcDMXAddInput(client); + case X_DMXRemoveInput: return ProcDMXRemoveInput(client); + + case X_DMXGetScreenInformationDEPRECATED: + case X_DMXForceWindowCreationDEPRECATED: + case X_DMXReconfigureScreenDEPRECATED: + return BadImplementation; + + default: return BadRequest; + } +} + +static int SProcDMXQueryVersion(ClientPtr client) +{ + int n; + REQUEST(xDMXQueryVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXQueryVersionReq); + return ProcDMXQueryVersion(client); +} + +static int SProcDMXSync(ClientPtr client) +{ + int n; + REQUEST(xDMXSyncReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXSyncReq); + return ProcDMXSync(client); +} + +static int SProcDMXForceWindowCreation(ClientPtr client) +{ + int n; + REQUEST(xDMXForceWindowCreationReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq); + swaps(&stuff->window, n); + return ProcDMXForceWindowCreation(client); +} + +static int SProcDMXGetScreenCount(ClientPtr client) +{ + int n; + REQUEST(xDMXGetScreenCountReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetScreenCountReq); + return ProcDMXGetScreenCount(client); +} + +static int SProcDMXGetScreenAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetScreenAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq); + swapl(&stuff->physicalScreen, n); + return ProcDMXGetScreenAttributes(client); +} + +static int SProcDMXChangeScreensAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXChangeScreensAttributesReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXGetScreenAttributesReq); + swapl(&stuff->screenCount, n); + swapl(&stuff->maskCount, n); + SwapRestL(stuff); + return ProcDMXGetScreenAttributes(client); +} + +static int SProcDMXAddScreen(ClientPtr client) +{ + int n; + int paddedLength; + REQUEST(xDMXAddScreenReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq); + swapl(&stuff->displayNameLength, n); + swapl(&stuff->valueMask, n); + paddedLength = (stuff->displayNameLength + 3) & ~3; + SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4); + return ProcDMXAddScreen(client); +} + +static int SProcDMXRemoveScreen(ClientPtr client) +{ + int n; + REQUEST(xDMXRemoveScreenReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXRemoveScreenReq); + swapl(&stuff->physicalScreen, n); + return ProcDMXRemoveScreen(client); +} + +static int SProcDMXGetWindowAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetWindowAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq); + swapl(&stuff->window, n); + return ProcDMXGetWindowAttributes(client); +} + +static int SProcDMXGetDesktopAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetDesktopAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq); + return ProcDMXGetDesktopAttributes(client); +} + +static int SProcDMXChangeDesktopAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXChangeDesktopAttributesReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return ProcDMXChangeDesktopAttributes(client); +} + +static int SProcDMXGetInputCount(ClientPtr client) +{ + int n; + REQUEST(xDMXGetInputCountReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetInputCountReq); + return ProcDMXGetInputCount(client); +} + +static int SProcDMXGetInputAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetInputAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq); + swapl(&stuff->deviceId, n); + return ProcDMXGetInputAttributes(client); +} + +static int SProcDMXAddInput(ClientPtr client) +{ + int n; + int paddedLength; + REQUEST(xDMXAddInputReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXAddInputReq); + swapl(&stuff->displayNameLength, n); + swapl(&stuff->valueMask, n); + paddedLength = (stuff->displayNameLength + 3) & ~3; + SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4); + return ProcDMXAddInput(client); +} + +static int SProcDMXRemoveInput(ClientPtr client) +{ + int n; + REQUEST(xDMXRemoveInputReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXRemoveInputReq); + swapl(&stuff->physicalId, n); + return ProcDMXRemoveInput(client); +} + +static int SProcDMXDispatch (ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_DMXQueryVersion: return SProcDMXQueryVersion(client); + case X_DMXSync: return SProcDMXSync(client); + case X_DMXForceWindowCreation: return SProcDMXForceWindowCreation(client); + case X_DMXGetScreenCount: return SProcDMXGetScreenCount(client); + case X_DMXGetScreenAttributes: return SProcDMXGetScreenAttributes(client); + case X_DMXChangeScreensAttributes: + return SProcDMXChangeScreensAttributes(client); + case X_DMXAddScreen: return SProcDMXAddScreen(client); + case X_DMXRemoveScreen: return SProcDMXRemoveScreen(client); + case X_DMXGetWindowAttributes: return SProcDMXGetWindowAttributes(client); + case X_DMXGetDesktopAttributes: + return SProcDMXGetDesktopAttributes(client); + case X_DMXChangeDesktopAttributes: + return SProcDMXChangeDesktopAttributes(client); + case X_DMXGetInputCount: return SProcDMXGetInputCount(client); + case X_DMXGetInputAttributes: return SProcDMXGetInputAttributes(client); + case X_DMXAddInput: return SProcDMXAddInput(client); + case X_DMXRemoveInput: return SProcDMXRemoveInput(client); + + case X_DMXGetScreenInformationDEPRECATED: + case X_DMXForceWindowCreationDEPRECATED: + case X_DMXReconfigureScreenDEPRECATED: + return BadImplementation; + + default: return BadRequest; + } +} diff --git a/nx-X11/programs/Xserver/Xext/dpms.c b/nx-X11/programs/Xserver/Xext/dpms.c new file mode 100644 index 000000000..3e79602d1 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/dpms.c @@ -0,0 +1,450 @@ +/* $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. + +******************************************************************/ + +/* + * HISTORY + * + * @(#)RCSfile: dpms.c,v Revision: 1.1.4.5 (DEC) Date: 1996/03/04 15:27:00 + */ + +/* $XFree86: xc/programs/Xserver/Xext/dpms.c,v 3.10tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "opaque.h" +#define DPMS_SERVER +#include <X11/extensions/dpms.h> +#include <X11/extensions/dpmsstr.h> +#include "dpmsproc.h" +#include "modinit.h" + +#if 0 +static unsigned char DPMSCode; +#endif +static DISPATCH_PROC(ProcDPMSDispatch); +static DISPATCH_PROC(SProcDPMSDispatch); +static DISPATCH_PROC(ProcDPMSGetVersion); +static DISPATCH_PROC(SProcDPMSGetVersion); +static DISPATCH_PROC(ProcDPMSGetTimeouts); +static DISPATCH_PROC(SProcDPMSGetTimeouts); +static DISPATCH_PROC(ProcDPMSSetTimeouts); +static DISPATCH_PROC(SProcDPMSSetTimeouts); +static DISPATCH_PROC(ProcDPMSEnable); +static DISPATCH_PROC(SProcDPMSEnable); +static DISPATCH_PROC(ProcDPMSDisable); +static DISPATCH_PROC(SProcDPMSDisable); +static DISPATCH_PROC(ProcDPMSForceLevel); +static DISPATCH_PROC(SProcDPMSForceLevel); +static DISPATCH_PROC(ProcDPMSInfo); +static DISPATCH_PROC(SProcDPMSInfo); +static DISPATCH_PROC(ProcDPMSCapable); +static DISPATCH_PROC(SProcDPMSCapable); +static void DPMSResetProc(ExtensionEntry* extEntry); + +void +DPMSExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(DPMSExtensionName, 0, 0, + ProcDPMSDispatch, SProcDPMSDispatch, + DPMSResetProc, StandardMinorOpcode))) + DPMSCode = (unsigned char)extEntry->base; +#else + (void) AddExtension(DPMSExtensionName, 0, 0, + ProcDPMSDispatch, SProcDPMSDispatch, + DPMSResetProc, StandardMinorOpcode); +#endif +} + +/*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(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; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + 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); + + 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; + SetDPMSTimers(); + + 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); + + DPMSSet(DPMSModeOn); + + 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(); + } 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; + } + + DPMSSet(stuff->level); + + return(client->noClientException); +} + +static int +ProcDPMSInfo(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(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/nx-X11/programs/Xserver/Xext/dpmsproc.h b/nx-X11/programs/Xserver/Xext/dpmsproc.h new file mode 100644 index 000000000..ae1e6e25a --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/dpmsproc.h @@ -0,0 +1,16 @@ +/* $XFree86: xc/programs/Xserver/Xext/dpmsproc.h,v 1.3 2001/10/28 03:32:50 tsi Exp $ */ + +/* Prototypes for functions that the DDX must provide */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _DPMSPROC_H_ +#define _DPMSPROC_H_ + +void DPMSSet(int level); +int DPMSGet(int *plevel); +Bool DPMSSupported(void); + +#endif diff --git a/nx-X11/programs/Xserver/Xext/dpmsstubs.c b/nx-X11/programs/Xserver/Xext/dpmsstubs.c new file mode 100644 index 000000000..128c57bb0 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/dpmsstubs.c @@ -0,0 +1,54 @@ +/* $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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/dpmsstubs.c,v 3.4 2001/01/17 22:13:15 dawes Exp $ */ + +typedef int Bool; + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "dpmsproc.h" + +#define FALSE 0 + +Bool DPMSSupported(void) +{ + return FALSE; +} + +int DPMSGet(int *plevel) +{ + return -1; +} + +void DPMSSet(int level) +{ + +} diff --git a/nx-X11/programs/Xserver/Xext/extmod/Imakefile b/nx-X11/programs/Xserver/Xext/extmod/Imakefile new file mode 100644 index 000000000..450a318b4 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/extmod/Imakefile @@ -0,0 +1,127 @@ +XCOMM $XFree86: xc/programs/Xserver/Xext/extmod/Imakefile,v 1.21 2001/03/05 04:51:56 mvojkovi Exp $ +XCOMM This directory is only entered if DoLoadableServer is set + +#define IHaveModules +#include <Server.tmpl> + +#if BuildMultibuffer + MULTIBUFSRC = mbuf.c + MULTIBUFOBJ = mbuf.o +LinkSourceFile(mbuf.c,..) +#endif + +#if BuildScreenSaverExt + SCRNSAVSRC = saver.c + SCRNSAVOBJ = saver.o +LinkSourceFile(saver.c,..) +#endif + +#if BuildXF86VidModeExt + VIDMODESRCS = xf86vmode.c + VIDMODEOBJS = xf86vmode.o +LinkSourceFile(xf86vmode.c,..) +#endif + +#if BuildXF86MiscExt + XF86MISCSRCS = xf86misc.c + XF86MISCOBJS = xf86misc.o +LinkSourceFile(xf86misc.c,..) +#endif + +#if BuildXF86DGA + XF86DGASRCS = xf86dga.c xf86dga2.c + XF86DGAOBJS = xf86dga.o xf86dga2.o +LinkSourceFile(xf86dga.c,..) +LinkSourceFile(xf86dga2.c,..) +#endif + +#if BuildDPMS + DPMSSRCS = dpms.c + DPMSOBJS = dpms.o +LinkSourceFile(dpms.c,..) +#endif + +#if BuildFontCache + FONTCACHESRCS = fontcache.c + FONTCACHEOBJS = fontcache.o +#if 0 + FONTCACHEINCLUDES = -I$(XF86SRC)/os-support +#endif +LinkSourceFile(fontcache.c,..) +#endif + +#if BuildXvExt + XVSRCS = xvmain.c xvdisp.c xvmod.c xvmc.c + XVOBJS = xvmain.o xvdisp.o xvmod.o xvmc.o +LinkSourceFile(xvmain.c,..) +LinkSourceFile(xvdisp.c,..) +LinkSourceFile(xvmod.c,..) +LinkSourceFile(xvmc.c,..) +#endif + +#if BuildXResExt + XRESSRCS = xres.c + XRESOBJS = xres.o +LinkSourceFile(xres.c,..) +#endif + +#if BuildEVI + EVISRCS = EVI.c sampleEVI.c + EVIOBJS = EVI.o sampleEVI.o +LinkSourceFile(EVI.c,..) +LinkSourceFile(sampleEVI.c,..) +#endif + +#if BuildCup + CUPSRCS = cup.c + CUPOBJS = cup.o +LinkSourceFile(cup.c,..) +#endif + + MODINITSRCS = modinit.c + MODINITOBJS = modinit.o + + SRCS = shape.c $(MULTIBUFSRC) \ + mitmisc.c \ + bigreq.c sync.c $(SCRNSAVSRC) xcmisc.c $(VIDMODESRCS) \ + $(XF86MISCSRCS) $(XF86DGASRCS) \ + $(CUPSRCS) $(DPMSSRCS) $(FONTCACHESRCS) \ + $(EVISRCS) $(XVSRCS) $(MODINITSRCS) $(XRESSRCS) + + MOBJS = $(MODINITOBJS) shape.o $(MULTIBUFOBJ) mitmisc.o \ + bigreq.o sync.o $(SCRNSAVOBJ) xcmisc.o \ + $(VIDMODEOBJS) $(XF86MISCOBJS) $(XF86DGAOBJS) \ + $(CUPOBJS) $(DPMSOBJS) $(FONTCACHEOBJS) \ + $(EVIOBJS) $(XVOBJS) $(XRESOBJS) + + DEFINES = -DEXTMODULE $(EXT_DEFINES) + +XF86INCLUDES = -I$(XF86COMSRC) + INCLUDES = -I.. -I../../include -I$(XINCLUDESRC) -I$(EXTINCSRC) \ + $(XF86INCLUDES) $(FONTCACHEINCLUDES) -I$(FONTINCSRC) + LINTLIBS = ../../dix/llib-ldix.ln ../../os/llib-los.ln + +LinkSourceFile(shape.c,..) +LinkSourceFile(mitmisc.c,..) +LinkSourceFile(bigreq.c,..) +LinkSourceFile(sync.c,..) +LinkSourceFile(xcmisc.c,..) + +ModuleObjectRule() + +/* + * A hack to work around an optimization problem with gcc 2.95.2 + */ +#if BuildXF86VidModeExt && defined(GccOptBug295) +SpecialCObjectRule(xf86vmode,NullParameter,-O0) +#endif + +SpecialCObjectRule(modinit,$(ICONFIGFILES),$(EXT_DEFINES)) +LibraryModuleTarget(extmod,$(MOBJS)) +NormalLintTarget($(SRCS)) + +InstallLibraryModule(extmod,$(MODULEDIR),extensions) + +DependTarget() + +InstallDriverSDKLibraryModule(extmod,$(DRIVERSDKMODULEDIR),extensions) diff --git a/nx-X11/programs/Xserver/Xext/extmod/modinit.c b/nx-X11/programs/Xserver/Xext/extmod/modinit.c new file mode 100644 index 000000000..3c2044f78 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/extmod/modinit.c @@ -0,0 +1,264 @@ +/* $XFree86: xc/programs/Xserver/Xext/extmod/modinit.c,v 1.16 2002/03/06 21:12:33 mvojkovi Exp $ */ + +/* + * + * Copyright (c) 1997 Matthieu Herrb + * + * 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, and that the name of Matthieu Herrb not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Matthieu Herrb makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * MATTHIEU HERRB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL MATTHIEU HERRB 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifdef XFree86LOADER +#include "xf86_ansic.h" + +#include "xf86Module.h" +#include "xf86Opt.h" + +#include <X11/Xproto.h> + +#include "modinit.h" +#include "globals.h" + +static MODULESETUPPROTO(extmodSetup); + +/* + * Array describing extensions to be initialized + */ +ExtensionModule extensionModules[] = { +#ifdef SHAPE + { + ShapeExtensionInit, + SHAPENAME, + &noShapeExtension, + NULL, + NULL + }, +#endif +#ifdef MULTIBUFFER + { + MultibufferExtensionInit, + MULTIBUFFER_PROTOCOL_NAME, + &noMultibufferExtension, + NULL, + NULL + }, +#endif +#ifdef MITMISC + { + MITMiscExtensionInit, + MITMISCNAME, + &noMITMiscExtension, + NULL, + NULL + }, +#endif +#ifdef notyet + { + XTestExtensionInit, + XTestExtensionName, + &noTestExtensions, + NULL, + NULL + }, +#endif +#ifdef BIGREQS + { + BigReqExtensionInit, + XBigReqExtensionName, + &noBigReqExtension, + NULL, + NULL + }, +#endif +#ifdef XSYNC + { + SyncExtensionInit, + SYNC_NAME, + &noSyncExtension, + NULL, + NULL + }, +#endif +#ifdef SCREENSAVER + { + ScreenSaverExtensionInit, + ScreenSaverName, + &noScreenSaverExtension, + NULL, + NULL + }, +#endif +#ifdef XCMISC + { + XCMiscExtensionInit, + XCMiscExtensionName, + &noXCMiscExtension, + NULL, + NULL + }, +#endif +#ifdef XF86VIDMODE + { + XFree86VidModeExtensionInit, + XF86VIDMODENAME, + &noXFree86VidModeExtension, + NULL, + NULL + }, +#endif +#ifdef XF86MISC + { + XFree86MiscExtensionInit, + XF86MISCNAME, + &noXFree86MiscExtension, + NULL, + NULL + }, +#endif +#ifdef XFreeXDGA + { + XFree86DGAExtensionInit, + XF86DGANAME, + &noXFree86DGAExtension, + XFree86DGARegister, + NULL + }, +#endif +#ifdef DPMSExtension + { + DPMSExtensionInit, + DPMSExtensionName, + &noDPMSExtension, + NULL, + NULL + }, +#endif +#ifdef FONTCACHE + { + FontCacheExtensionInit, + FONTCACHENAME, + &noFontCacheExtension, + NULL, + NULL + }, +#endif +#ifdef TOGCUP + { + XcupExtensionInit, + XCUPNAME, + &noXcupExtension, + NULL, + NULL + }, +#endif +#ifdef EVI + { + EVIExtensionInit, + EVINAME, + &noEVIExtension, + NULL, + NULL + }, +#endif +#ifdef XV + { + XvExtensionInit, + XvName, + &noXvExtension, + XvRegister, + NULL + }, + { + XvMCExtensionInit, + XvMCName, + &noXvExtension, + NULL, + NULL + }, +#endif +#ifdef RES + { + ResExtensionInit, + XRES_NAME, + &noResExtension, + NULL, + NULL + }, +#endif + { /* DON'T delete this entry ! */ + NULL, + NULL, + NULL, + NULL, + NULL + } +}; + +static XF86ModuleVersionInfo VersRec = +{ + "extmod", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_EXTENSION, + ABI_EXTENSION_VERSION, + MOD_CLASS_EXTENSION, + {0,0,0,0} +}; + +/* + * Data for the loader + */ +XF86ModuleData extmodModuleData = { &VersRec, extmodSetup, NULL }; + +static pointer +extmodSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + int i; + + /* XXX the option stuff here is largely a sample/test case */ + + for (i = 0; extensionModules[i].name != NULL; i++) { + if (opts) { + char *s; + s = (char *)xalloc(strlen(extensionModules[i].name) + 5); + if (s) { + pointer o; + strcpy(s, "omit"); + strcat(s, extensionModules[i].name); + o = xf86FindOption(opts, s); + xfree(s); + if (o) { + xf86MarkOptionUsed(o); + continue; + } + } + } + LoadExtension(&extensionModules[i], FALSE); + } + /* Need a non-NULL return */ + return (pointer)1; +} + +#endif /* XFree86LOADER */ diff --git a/nx-X11/programs/Xserver/Xext/extmod/modinit.h b/nx-X11/programs/Xserver/Xext/extmod/modinit.h new file mode 100644 index 000000000..2bafdb2b0 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/extmod/modinit.h @@ -0,0 +1,149 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/extmod/modinit.h,v 1.5 2005/07/03 07:01:06 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/Xext/extmod/modinit.h,v 1.1 2003/07/16 01:38:33 dawes Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef INITARGS +#define INITARGS void +#endif + +#ifdef SHAPE +extern void ShapeExtensionInit(INITARGS); +#define _SHAPE_SERVER_ /* don't want Xlib structures */ +#include <X11/extensions/shapestr.h> +#endif + +#ifdef MULTIBUFFER +extern void MultibufferExtensionInit(INITARGS); +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#include <X11/extensions/multibufst.h> +#endif + +#ifdef MITMISC +extern void MITMiscExtensionInit(INITARGS); +#define _MITMISC_SERVER_ +#include <X11/extensions/mitmiscstr.h> +#endif + +#ifdef XTEST +extern void XTestExtensionInit(INITARGS); +#define _XTEST_SERVER_ +#include <X11/extensions/XTest.h> +#include <X11/extensions/xteststr.h> +#endif + +#if 1 +extern void XTestExtension1Init(INITARGS); +#endif + +#ifdef BIGREQS +extern void BigReqExtensionInit(INITARGS); +#include <X11/extensions/bigreqstr.h> +#endif + +#ifdef XSYNC +extern void SyncExtensionInit(INITARGS); +#define _SYNC_SERVER +#include <X11/extensions/sync.h> +#include <X11/extensions/syncstr.h> +#endif + +#ifdef SCREENSAVER +extern void ScreenSaverExtensionInit (INITARGS); +#include <X11/extensions/saver.h> +#endif + +#ifdef XCMISC +extern void XCMiscExtensionInit(INITARGS); +#include <X11/extensions/xcmiscstr.h> +#endif + +#ifdef XF86VIDMODE +extern void XFree86VidModeExtensionInit(INITARGS); +#define _XF86VIDMODE_SERVER_ +#include <X11/extensions/xf86vmstr.h> +#endif + +#ifdef XF86MISC +extern void XFree86MiscExtensionInit(INITARGS); +#define _XF86MISC_SERVER_ +#define _XF86MISC_SAVER_COMPAT_ +#include <X11/extensions/xf86mscstr.h> +#endif + +#ifdef XFreeXDGA +extern void XFree86DGAExtensionInit(INITARGS); +extern void XFree86DGARegister(INITARGS); +#define _XF86DGA_SERVER_ +#include <X11/extensions/xf86dgastr.h> +#endif + +#ifdef DPMSExtension +extern void DPMSExtensionInit(INITARGS); +#include <X11/extensions/dpmsstr.h> +#endif + +#ifdef FONTCACHE +extern void FontCacheExtensionInit(INITARGS); +#define _FONTCACHE_SERVER_ +#include "fontcacheP.h" +#include "fontcachstr.h" +#endif + +#ifdef TOGCUP +extern void XcupExtensionInit(INITARGS); +#define _XCUP_SERVER_ +#include <X11/extensions/Xcupstr.h> +#endif + +#ifdef EVI +extern void EVIExtensionInit(INITARGS); +#define _XEVI_SERVER_ +#include <X11/extensions/XEVIstr.h> +#endif + +#ifdef XV +extern void XvExtensionInit(INITARGS); +extern void XvMCExtensionInit(INITARGS); +extern void XvRegister(INITARGS); +#include <X11/extensions/Xv.h> +#include <X11/extensions/XvMC.h> +#endif + +#ifdef RES +extern void ResExtensionInit(INITARGS); +#include <X11/extensions/XResproto.h> +#endif + +#ifdef SHM +extern void ShmExtensionInit(INITARGS); +#include <X11/extensions/shmstr.h> +extern void ShmSetPixmapFormat( + ScreenPtr pScreen, + int format); +extern void ShmRegisterFuncs( + ScreenPtr pScreen, + ShmFuncsPtr funcs); +#endif + +#if 1 +extern void SecurityExtensionInit(INITARGS); +#endif + +#if 1 +extern void XagExtensionInit(INITARGS); +#endif + +#if 1 +extern void XpExtensionInit(INITARGS); +#endif + +#if 1 +extern void PanoramiXExtensionInit(int argc, char *argv[]); +#endif + +#if 1 +extern void XkbExtensionInit(INITARGS); +#endif diff --git a/nx-X11/programs/Xserver/Xext/fontcache.c b/nx-X11/programs/Xserver/Xext/fontcache.c new file mode 100644 index 000000000..9ab23a122 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/fontcache.c @@ -0,0 +1,333 @@ +/*- + * Copyright (c) 1998-1999 Shunsuke Akiyama <akiyama@jp.FreeBSD.org>. + * All rights reserved. + * Copyright (c) 1998-1999 X-TrueType Server Project, All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: fontcache.c,v 1.12 1999/01/31 13:47:45 akiyama Exp $ + */ +/* $XFree86: xc/programs/Xserver/Xext/fontcache.c,v 1.7 2003/10/28 23:08:43 tsi Exp $ */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "inputstr.h" +#include "servermd.h" +#define _FONTCACHE_SERVER_ +#include "fontcacheP.h" +#include "fontcachstr.h" +#include <X11/Xfuncproto.h> + +#include "swaprep.h" +#include "modinit.h" + +static int miscErrorBase; + +static void FontCacheResetProc( + ExtensionEntry* /* extEntry */ +); + +static DISPATCH_PROC(ProcFontCacheDispatch); +static DISPATCH_PROC(ProcFontCacheGetCacheSettings); +static DISPATCH_PROC(ProcFontCacheGetCacheStatistics); +static DISPATCH_PROC(ProcFontCacheQueryVersion); +static DISPATCH_PROC(ProcFontCacheChangeCacheSettings); +static DISPATCH_PROC(SProcFontCacheDispatch); +static DISPATCH_PROC(SProcFontCacheGetCacheSettings); +static DISPATCH_PROC(SProcFontCacheGetCacheStatistics); +static DISPATCH_PROC(SProcFontCacheQueryVersion); +static DISPATCH_PROC(SProcFontCacheChangeCacheSettings); + +#if 0 +static unsigned char FontCacheReqCode = 0; +#endif + +void +FontCacheExtensionInit(INITARGS) +{ + ExtensionEntry* extEntry; + + if ( + (extEntry = AddExtension(FONTCACHENAME, + FontCacheNumberEvents, + FontCacheNumberErrors, + ProcFontCacheDispatch, + SProcFontCacheDispatch, + FontCacheResetProc, + StandardMinorOpcode))) { +#if 0 + FontCacheReqCode = (unsigned char)extEntry->base; +#endif + miscErrorBase = extEntry->errorBase; + } +} + +/*ARGSUSED*/ +static void +FontCacheResetProc (extEntry) + ExtensionEntry* extEntry; +{ +} + +static int +ProcFontCacheQueryVersion(client) + register ClientPtr client; +{ + xFontCacheQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xFontCacheQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = FONTCACHE_MAJOR_VERSION; + rep.minorVersion = FONTCACHE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, SIZEOF(xFontCacheQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcFontCacheGetCacheSettings(client) + register ClientPtr client; +{ + xFontCacheGetCacheSettingsReply rep; + FontCacheSettings cinfo; + register int n; + + REQUEST_SIZE_MATCH(xFontCacheGetCacheSettingsReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + /* XXX */ + FontCacheGetSettings(&cinfo); + rep.himark = cinfo.himark; + rep.lowmark = cinfo.lowmark; + rep.balance = cinfo.balance; + rep.reserve0 = 0; + rep.reserve1 = 0; + rep.reserve2 = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.himark, n); + swapl(&rep.lowmark, n); + swapl(&rep.balance, n); + swapl(&rep.reserve0, n); + swapl(&rep.reserve1, n); + swapl(&rep.reserve2, n); + } + /* XXX */ + + WriteToClient(client, SIZEOF(xFontCacheGetCacheSettingsReply), + (char *)&rep); + return (client->noClientException); +} + +static int +ProcFontCacheGetCacheStatistics(client) + register ClientPtr client; +{ + xFontCacheGetCacheStatisticsReply rep; + FontCacheStatistics cstats; + register int n; + + REQUEST_SIZE_MATCH(xFontCacheGetCacheStatisticsReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = (sz_xFontCacheGetCacheStatisticsReply - 32) >> 2; + + /* XXX */ + FontCacheGetStatistics(&cstats); + rep.purge_runs = cstats.purge_runs; + rep.purge_stat = cstats.purge_stat; + rep.balance = cstats.balance; + rep.reserve0 = 0; + rep.f_hits = cstats.f.hits; + rep.f_misshits = cstats.f.misshits; + rep.f_purged = cstats.f.purged; + rep.f_usage = cstats.f.usage; + rep.f_reserve0 = 0; + rep.v_hits = cstats.v.hits; + rep.v_misshits = cstats.v.misshits; + rep.v_purged = cstats.v.purged; + rep.v_usage = cstats.v.usage; + rep.v_reserve0 = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.purge_runs, n); + swapl(&rep.purge_stat, n); + swapl(&rep.balance, n); + swapl(&rep.reserve0, n); + swapl(&rep.f_hits, n); + swapl(&rep.f_misshits, n); + swapl(&rep.f_purged, n); + swapl(&rep.f_usage, n); + swapl(&rep.f_reserve0, n); + swapl(&rep.v_hits, n); + swapl(&rep.v_misshits, n); + swapl(&rep.v_purged, n); + swapl(&rep.v_usage, n); + swapl(&rep.v_reserve0, n); + } + /* XXX */ + WriteToClient(client, SIZEOF(xFontCacheGetCacheStatisticsReply), + (char *)&rep); + return (client->noClientException); +} + +static int +ProcFontCacheChangeCacheSettings(client) + register ClientPtr client; +{ + FontCacheSettings cs; + + REQUEST(xFontCacheChangeCacheSettingsReq); + + REQUEST_SIZE_MATCH(xFontCacheChangeCacheSettingsReq); + + /* XXX */ + cs.himark = stuff->himark; + cs.lowmark = stuff->lowmark; + cs.balance = stuff->balance; + + if (cs.himark < 0 || cs.lowmark < 0) + return BadValue; + if (cs.himark <= cs.lowmark) + return BadValue; + if (!(10 <= cs.balance && cs.balance <= 90)) + return BadValue; + + if (FontCacheChangeSettings(&cs) == 0) + return miscErrorBase + FontCacheCannotAllocMemory; + /* XXX */ + + return (client->noClientException); +} + +static int +ProcFontCacheDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_FontCacheQueryVersion: + return ProcFontCacheQueryVersion(client); + case X_FontCacheGetCacheSettings: + return ProcFontCacheGetCacheSettings(client); + case X_FontCacheGetCacheStatistics: + return ProcFontCacheGetCacheStatistics(client); + case X_FontCacheChangeCacheSettings: + return ProcFontCacheChangeCacheSettings(client); + default: + return miscErrorBase + FontCacheBadProtocol; + } +} + +static int +SProcFontCacheQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xFontCacheQueryVersionReq); + swaps(&stuff->length, n); + return ProcFontCacheQueryVersion(client); +} + +static int +SProcFontCacheGetCacheSettings(client) + ClientPtr client; +{ + register int n; + REQUEST(xFontCacheGetCacheSettingsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xFontCacheGetCacheSettingsReq); + return ProcFontCacheGetCacheSettings(client); +} + +static int +SProcFontCacheGetCacheStatistics(client) + ClientPtr client; +{ + register int n; + REQUEST(xFontCacheGetCacheStatisticsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xFontCacheGetCacheStatisticsReq); + return ProcFontCacheGetCacheStatistics(client); +} + +static int +SProcFontCacheChangeCacheSettings(client) + ClientPtr client; +{ + register int n; + REQUEST(xFontCacheChangeCacheSettingsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xFontCacheChangeCacheSettingsReq); + /* XXX */ + swapl(&stuff->himark, n); + swapl(&stuff->lowmark, n); + swapl(&stuff->balance, n); + /* XXX */ + return ProcFontCacheChangeCacheSettings(client); +} + +static int +SProcFontCacheDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_FontCacheQueryVersion: + return SProcFontCacheQueryVersion(client); + case X_FontCacheGetCacheSettings: + return SProcFontCacheGetCacheSettings(client); + case X_FontCacheGetCacheStatistics: + return SProcFontCacheGetCacheStatistics(client); + case X_FontCacheChangeCacheSettings: + return SProcFontCacheChangeCacheSettings(client); + default: + return miscErrorBase + FontCacheBadProtocol; + } +} diff --git a/nx-X11/programs/Xserver/Xext/mbuf.c b/nx-X11/programs/Xserver/Xext/mbuf.c new file mode 100644 index 000000000..3129edd87 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/mbuf.c @@ -0,0 +1,1787 @@ +/* $XFree86: xc/programs/Xserver/Xext/mbuf.c,v 3.15 2003/10/28 23:08:43 tsi Exp $ */ +/************************************************************ + +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 +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "window.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "sleepuntil.h" +#define _MULTIBUF_SERVER_ /* don't want Xlib structures */ +#include <X11/extensions/multibufst.h> + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#else +#include <stdio.h> +#if !defined(WIN32) && !defined(Lynx) +#include <sys/time.h> +#endif +#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) + +#if 0 +static unsigned char MultibufferReqCode; +#endif +static int MultibufferEventBase; +static int MultibufferErrorBase; +int MultibufferScreenIndex = -1; +int MultibufferWindowIndex = -1; + +static void PerformDisplayRequest ( + MultibuffersPtr * /* ppMultibuffers */, + MultibufferPtr * /* pMultibuffer */, + int /* nbuf */ + ); +static Bool QueueDisplayRequest ( + ClientPtr /* client */, + TimeStamp /* activateTime */ + ); + +static void BumpTimeStamp ( + TimeStamp * /* ts */, + CARD32 /* inc */ + ); + +static void AliasMultibuffer ( + MultibuffersPtr /* pMultibuffers */, + int /* i */ + ); +static void RecalculateMultibufferOtherEvents ( + MultibufferPtr /* pMultibuffer */ + ); +static int EventSelectForMultibuffer( + MultibufferPtr /* pMultibuffer */, + ClientPtr /* client */, + Mask /* mask */ + ); + +/* + * The Pixmap associated with a buffer can be found as a resource + * with this type + */ +RESTYPE MultibufferDrawableResType; +static int MultibufferDrawableDelete ( + pointer /* value */, + XID /* id */ + ); +/* + * 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 ( + pointer /* value */, + XID /* id */ + ); + +/* + * The per-window data can be found as a resource with this type, + * using the window resource id + */ +static RESTYPE MultibuffersResType; +static int MultibuffersDelete ( + pointer /* value */, + XID /* id */ + ); + +/* + * 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 ( + pointer /* value */, + XID /* id */ + ); + +/**************** + * MultibufferExtensionInit + * + * Called from InitExtensions in main() + * + ****************/ + +extern DISPATCH_PROC(ProcGetBufferAttributes); + +static DISPATCH_PROC(ProcClearImageBufferArea); +static DISPATCH_PROC(ProcCreateImageBuffers); +static DISPATCH_PROC(ProcDestroyImageBuffers); +static DISPATCH_PROC(ProcDisplayImageBuffers); +static DISPATCH_PROC(ProcGetBufferInfo); +static DISPATCH_PROC(ProcGetBufferVersion); +static DISPATCH_PROC(ProcGetMBufferAttributes); +static DISPATCH_PROC(ProcMultibufferDispatch); +static DISPATCH_PROC(ProcSetBufferAttributes); +static DISPATCH_PROC(ProcSetMBufferAttributes); +static DISPATCH_PROC(SProcClearImageBufferArea); +static DISPATCH_PROC(SProcCreateImageBuffers); +static DISPATCH_PROC(SProcDestroyImageBuffers); +static DISPATCH_PROC(SProcDisplayImageBuffers); +static DISPATCH_PROC(SProcGetBufferAttributes); +static DISPATCH_PROC(SProcGetBufferInfo); +static DISPATCH_PROC(SProcGetBufferVersion); +static DISPATCH_PROC(SProcGetMBufferAttributes); +static DISPATCH_PROC(SProcMultibufferDispatch); +static DISPATCH_PROC(SProcSetBufferAttributes); +static DISPATCH_PROC(SProcSetMBufferAttributes); + +static void MultibufferResetProc( + ExtensionEntry * /* extEntry */ + ); +static void SClobberNotifyEvent( + xMbufClobberNotifyEvent * /* from */, + xMbufClobberNotifyEvent * /* to */ + ); +static void SUpdateNotifyEvent( + xMbufUpdateNotifyEvent * /* from */, + xMbufUpdateNotifyEvent * /* to */ + ); +static Bool MultibufferPositionWindow( + WindowPtr /* pWin */, + int /* x */, + int /* y */ + ); + +static void SetupBackgroundPainter ( + WindowPtr /* pWin */, + GCPtr /* pGC */ + ); + +static int DeliverEventsToMultibuffer ( + MultibufferPtr /* pMultibuffer */, + xEvent * /* pEvents */, + int /* count */, + Mask /* filter */ + ); + +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))) + { +#if 0 + MultibufferReqCode = (unsigned char)extEntry->base; +#endif + MultibufferEventBase = extEntry->eventBase; + MultibufferErrorBase = extEntry->errorBase; + EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = (EventSwapPtr) SClobberNotifyEvent; + EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = (EventSwapPtr) 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; +{ + 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)(long) ts_x_origin; + gcvalues[3] = (pointer)(long) 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; +} + + +static int +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); + } + 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; + + + REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq); + nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2); + if (!nbuf) + return Success; + minDelay = stuff->minDelay; + ids = (XID *) &stuff[1]; + 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++) + { + 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; + BumpTimeStamp (&bufferTime, minDelay); + if (CompareTimeStamps (bufferTime, activateTime) == LATER) + activateTime = bufferTime; + } + UpdateCurrentTime (); + if (CompareTimeStamps (activateTime, currentTime) == LATER && + QueueDisplayRequest (client, activateTime)) + { + ; + } + else + PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf); + + DEALLOCATE_LOCAL(ppMultibuffers); + DEALLOCATE_LOCAL(pMultibuffer); + return Success; +} + + +static int +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; +} + +static int +ProcSetMBufferAttributes (client) + register ClientPtr client; +{ + REQUEST (xMbufSetMBufferAttributesReq); + WindowPtr pWin; + MultibuffersPtr pMultibuffers; + int len; + Mask vmask; + Mask index2; + 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) + { + index2 = (Mask) lowbit (vmask); + vmask &= ~index2; + switch (index2) + { + 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, index2; + 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) + { + index2 = (Mask) lowbit (vmask); + vmask &= ~index2; + switch (index2) + { + 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; +} + +int +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: + return ProcCreateImageBuffers (client); + case X_MbufDisplayImageBuffers: + return ProcDisplayImageBuffers (client); + case X_MbufDestroyImageBuffers: + return ProcDestroyImageBuffers (client); + case X_MbufSetMBufferAttributes: + return ProcSetMBufferAttributes (client); + 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; + + 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(pWin->drawable.pScreen, pWinSize, + -pWin->drawable.x, -pWin->drawable.y); + REGION_INTERSECT(pWin->drawable.pScreen, pExposed, + pExposed, pWinSize); + REGION_DESTROY(pWin->drawable.pScreen, pWinSize); + MultibufferExpose (pPrevMultibuffer, pExposed); + REGION_DESTROY(pWin->drawable.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)) != 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)) != 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, time2) + MultibufferPtr pMultibuffer; + CARD32 time2; +{ + xMbufUpdateNotifyEvent event; + + event.type = MultibufferEventBase + MultibufferUpdateNotify; + event.buffer = pMultibuffer->pPixmap->drawable.id; + event.timeStamp = time2; + (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/nx-X11/programs/Xserver/Xext/mbufbf.c b/nx-X11/programs/Xserver/Xext/mbufbf.c new file mode 100644 index 000000000..8585c52d2 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/mbufbf.c @@ -0,0 +1,1030 @@ +/* $XFree86: xc/programs/Xserver/Xext/mbufbf.c,v 3.5tsi Exp $ */ +/* + +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 +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#include <X11/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 <X11/extensions/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_NULL(pScreen, &pMBPriv->unionRgn); + + /* 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_NULL(pScreen, &exposed); + 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); + } +} + +/* + * 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 (! REGION_EQUAL(pScreen, 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_NULL(pScreen, &tmp_rgn); + 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/nx-X11/programs/Xserver/Xext/mbufpx.c b/nx-X11/programs/Xserver/Xext/mbufpx.c new file mode 100644 index 000000000..c986217ee --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/mbufpx.c @@ -0,0 +1,651 @@ +/* $XFree86: xc/programs/Xserver/Xext/mbufpx.c,v 3.3 2001/07/23 13:15:44 dawes Exp $ */ +/************************************************************ + +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 +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#include <X11/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 <X11/extensions/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/nx-X11/programs/Xserver/Xext/mitmisc.c b/nx-X11/programs/Xserver/Xext/mitmisc.c new file mode 100644 index 000000000..f7b0ee55c --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/mitmisc.c @@ -0,0 +1,176 @@ +/* $XFree86: xc/programs/Xserver/Xext/mitmisc.c,v 3.6 2003/10/28 23:08:43 tsi Exp $ */ +/************************************************************ + +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 $ */ + +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#define _MITMISC_SERVER_ +#include <X11/extensions/mitmiscstr.h> +#include "modinit.h" + +extern Bool permitOldBugs; + +#if 0 +static unsigned char MITReqCode; +#endif + +static void MITResetProc( + ExtensionEntry * /* extEntry */ +); + +static DISPATCH_PROC(ProcMITDispatch); +static DISPATCH_PROC(ProcMITGetBugMode); +static DISPATCH_PROC(ProcMITSetBugMode); +static DISPATCH_PROC(SProcMITDispatch); +static DISPATCH_PROC(SProcMITGetBugMode); +static DISPATCH_PROC(SProcMITSetBugMode); + +void +MITMiscExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(MITMISCNAME, 0, 0, + ProcMITDispatch, SProcMITDispatch, + MITResetProc, StandardMinorOpcode)) != 0) + MITReqCode = (unsigned char)extEntry->base; +#else + (void) AddExtension(MITMISCNAME, 0, 0, + ProcMITDispatch, SProcMITDispatch, + MITResetProc, StandardMinorOpcode); +#endif +} + +/*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; +{ + 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/nx-X11/programs/Xserver/Xext/panoramiX.c b/nx-X11/programs/Xserver/Xext/panoramiX.c new file mode 100644 index 000000000..33faedc57 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/panoramiX.c @@ -0,0 +1,1308 @@ +/* $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. +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/panoramiX.c,v 3.37tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#define NEED_REPLIES +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xarch.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" +#include "panoramiX.h" +#include <X11/extensions/panoramiXproto.h> +#include "panoramiXsrv.h" +#include "globals.h" +#include "servermd.h" +#include "resource.h" +#ifdef RENDER +#include "picturestr.h" +#endif +#include "modinit.h" + + +#ifdef GLXPROXY +extern VisualPtr glxMatchVisual(ScreenPtr pScreen, + VisualPtr pVisual, + ScreenPtr pMatchScreen); +#endif + +#if 0 +static unsigned char PanoramiXReqCode = 0; +#endif +/* + * PanoramiX data declarations + */ + +int PanoramiXPixWidth = 0; +int PanoramiXPixHeight = 0; +int PanoramiXNumScreens = 0; + +PanoramiXData *panoramiXdataPtr = NULL; +RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL}; + +static int PanoramiXNumDepths; +static DepthPtr PanoramiXDepths; +static int PanoramiXNumVisuals; +static VisualPtr PanoramiXVisuals; + +/* We support at most 256 visuals */ +XID *PanoramiXVisualTable = NULL; + +unsigned long XRC_DRAWABLE; +unsigned long XRT_WINDOW; +unsigned long XRT_PIXMAP; +unsigned long XRT_GC; +unsigned long XRT_COLORMAP; + +/* + * Function prototypes + */ + +static int panoramiXGeneration; +static int ProcPanoramiXDispatch(ClientPtr client); + +static void PanoramiXResetProc(ExtensionEntry*); + +/* + * External references for functions and data variables + */ + +#include "panoramiXh.h" + +int (* SavedProcVector[256]) (ClientPtr client) = { NULL, }; +ScreenInfo *GlobalScrInfo = NULL; + +static int PanoramiXGCIndex = -1; +static int PanoramiXScreenIndex = -1; + +typedef struct { + DDXPointRec clipOrg; + DDXPointRec patOrg; + GCFuncs *wrapFuncs; +} PanoramiXGCRec, *PanoramiXGCPtr; + +typedef struct { + CreateGCProcPtr CreateGC; + CloseScreenProcPtr CloseScreen; +} PanoramiXScreenRec, *PanoramiXScreenPtr; + +RegionRec XineramaScreenRegions[MAXSCREENS]; + +static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr); +static void XineramaChangeGC(GCPtr, unsigned long); +static void XineramaCopyGC(GCPtr, unsigned long, GCPtr); +static void XineramaDestroyGC(GCPtr); +static void XineramaChangeClip(GCPtr, int, pointer, int); +static void XineramaDestroyClip(GCPtr); +static void XineramaCopyClip(GCPtr, GCPtr); + +GCFuncs XineramaGCFuncs = { + XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC, + XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip +}; + +#define Xinerama_GC_FUNC_PROLOGUE(pGC)\ + PanoramiXGCPtr pGCPriv = \ + (PanoramiXGCPtr) (pGC)->devPrivates[PanoramiXGCIndex].ptr;\ + (pGC)->funcs = pGCPriv->wrapFuncs; + +#define Xinerama_GC_FUNC_EPILOGUE(pGC)\ + pGCPriv->wrapFuncs = (pGC)->funcs;\ + (pGC)->funcs = &XineramaGCFuncs; + + +static Bool +XineramaCloseScreen (int i, ScreenPtr pScreen) +{ + PanoramiXScreenPtr pScreenPriv = + (PanoramiXScreenPtr) pScreen->devPrivates[PanoramiXScreenIndex].ptr; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->CreateGC = pScreenPriv->CreateGC; + + REGION_UNINIT(pScreen, &XineramaScreenRegions[pScreen->myNum]); + if (pScreen->myNum == 0) + REGION_UNINIT(pScreen, &PanoramiXScreenRegion); + + xfree ((pointer) pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +Bool +XineramaCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + PanoramiXScreenPtr pScreenPriv = + (PanoramiXScreenPtr) pScreen->devPrivates[PanoramiXScreenIndex].ptr; + Bool ret; + + pScreen->CreateGC = pScreenPriv->CreateGC; + if((ret = (*pScreen->CreateGC)(pGC))) { + PanoramiXGCPtr pGCPriv = + (PanoramiXGCPtr) pGC->devPrivates[PanoramiXGCIndex].ptr; + + pGCPriv->wrapFuncs = pGC->funcs; + pGC->funcs = &XineramaGCFuncs; + + pGCPriv->clipOrg.x = pGC->clipOrg.x; + pGCPriv->clipOrg.y = pGC->clipOrg.y; + pGCPriv->patOrg.x = pGC->patOrg.x; + pGCPriv->patOrg.y = pGC->patOrg.y; + } + pScreen->CreateGC = XineramaCreateGC; + + return ret; +} + +static void +XineramaValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + Xinerama_GC_FUNC_PROLOGUE (pGC); + + if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) { + /* the root window */ + int x_off = panoramiXdataPtr[pGC->pScreen->myNum].x; + int y_off = panoramiXdataPtr[pGC->pScreen->myNum].y; + int new_val; + + new_val = pGCPriv->clipOrg.x - x_off; + if(pGC->clipOrg.x != new_val) { + pGC->clipOrg.x = new_val; + changes |= GCClipXOrigin; + } + new_val = pGCPriv->clipOrg.y - y_off; + if(pGC->clipOrg.y != new_val) { + pGC->clipOrg.y = new_val; + changes |= GCClipYOrigin; + } + new_val = pGCPriv->patOrg.x - x_off; + if(pGC->patOrg.x != new_val) { + pGC->patOrg.x = new_val; + changes |= GCTileStipXOrigin; + } + new_val = pGCPriv->patOrg.y - y_off; + if(pGC->patOrg.y != new_val) { + pGC->patOrg.y = new_val; + changes |= GCTileStipYOrigin; + } + } else { + if(pGC->clipOrg.x != pGCPriv->clipOrg.x) { + pGC->clipOrg.x = pGCPriv->clipOrg.x; + changes |= GCClipXOrigin; + } + if(pGC->clipOrg.y != pGCPriv->clipOrg.y) { + pGC->clipOrg.y = pGCPriv->clipOrg.y; + changes |= GCClipYOrigin; + } + if(pGC->patOrg.x != pGCPriv->patOrg.x) { + pGC->patOrg.x = pGCPriv->patOrg.x; + changes |= GCTileStipXOrigin; + } + if(pGC->patOrg.y != pGCPriv->patOrg.y) { + pGC->patOrg.y = pGCPriv->patOrg.y; + changes |= GCTileStipYOrigin; + } + } + + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaDestroyGC(GCPtr pGC) +{ + Xinerama_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaChangeGC ( + GCPtr pGC, + unsigned long mask +){ + Xinerama_GC_FUNC_PROLOGUE (pGC); + + if(mask & GCTileStipXOrigin) + pGCPriv->patOrg.x = pGC->patOrg.x; + if(mask & GCTileStipYOrigin) + pGCPriv->patOrg.y = pGC->patOrg.y; + if(mask & GCClipXOrigin) + pGCPriv->clipOrg.x = pGC->clipOrg.x; + if(mask & GCClipYOrigin) + pGCPriv->clipOrg.y = pGC->clipOrg.y; + + (*pGC->funcs->ChangeGC) (pGC, mask); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaCopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst +){ + PanoramiXGCPtr pSrcPriv = + (PanoramiXGCPtr) pGCSrc->devPrivates[PanoramiXGCIndex].ptr; + Xinerama_GC_FUNC_PROLOGUE (pGCDst); + + if(mask & GCTileStipXOrigin) + pGCPriv->patOrg.x = pSrcPriv->patOrg.x; + if(mask & GCTileStipYOrigin) + pGCPriv->patOrg.y = pSrcPriv->patOrg.y; + if(mask & GCClipXOrigin) + pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x; + if(mask & GCClipYOrigin) + pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y; + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + Xinerama_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +XineramaChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects +){ + Xinerama_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + Xinerama_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + Xinerama_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +XineramaDestroyClip(GCPtr pGC) +{ + Xinerama_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + + + +int +XineramaDeleteResource(pointer data, XID id) +{ + xfree(data); + return 1; +} + + +static Bool +XineramaFindIDOnAnyScreen(pointer resource, XID id, pointer privdata) +{ + PanoramiXRes *res = (PanoramiXRes*)resource; + int j; + + FOR_NSCREENS(j) + if(res->info[j].id == *((XID*)privdata)) return TRUE; + + return FALSE; +} + +PanoramiXRes * +PanoramiXFindIDOnAnyScreen(RESTYPE type, XID id) +{ + return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, + XineramaFindIDOnAnyScreen, &id); +} + +typedef struct { + int screen; + int id; +} PanoramiXSearchData; + + +static Bool +XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata) +{ + PanoramiXRes *res = (PanoramiXRes*)resource; + PanoramiXSearchData *data = (PanoramiXSearchData*)privdata; + + return (res->info[data->screen].id == data->id); +} + +PanoramiXRes * +PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen) +{ + PanoramiXSearchData data; + + if(!screen) + return LookupIDByType(id, type); + + data.screen = screen; + data.id = id; + + return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, + XineramaFindIDByScrnum, &data); +} + +WindowPtr +PanoramiXChangeWindow(int ScrnNum, WindowPtr pWin) +{ + int num = pWin->drawable.pScreen->myNum; + + if(num != ScrnNum) { + PanoramiXRes *win; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, num); + + if (win) + pWin = (WindowPtr) LookupIDByType(win->info[ScrnNum].id, RT_WINDOW); + } + + return pWin; +} + +typedef struct _connect_callback_list { + void (*func)(void); + struct _connect_callback_list *next; +} XineramaConnectionCallbackList; + +static XineramaConnectionCallbackList *ConnectionCallbackList = NULL; + +Bool +XineramaRegisterConnectionBlockCallback(void (*func)(void)) +{ + XineramaConnectionCallbackList *newlist; + + if(!(newlist = xalloc(sizeof(XineramaConnectionCallbackList)))) + return FALSE; + + newlist->next = ConnectionCallbackList; + newlist->func = func; + ConnectionCallbackList = newlist; + + return TRUE; +} + +static void XineramaInitData(ScreenPtr pScreen) +{ + int i, w, h; + + REGION_NULL(pScreen, &PanoramiXScreenRegion) + for (i = 0; i < PanoramiXNumScreens; i++) { + BoxRec TheBox; + + pScreen = screenInfo.screens[i]; + + panoramiXdataPtr[i].x = dixScreenOrigins[i].x; + panoramiXdataPtr[i].y = dixScreenOrigins[i].y; + panoramiXdataPtr[i].width = pScreen->width; + panoramiXdataPtr[i].height = pScreen->height; + + TheBox.x1 = panoramiXdataPtr[i].x; + TheBox.x2 = TheBox.x1 + panoramiXdataPtr[i].width; + TheBox.y1 = panoramiXdataPtr[i].y; + TheBox.y2 = TheBox.y1 + panoramiXdataPtr[i].height; + + REGION_INIT(pScreen, &XineramaScreenRegions[i], &TheBox, 1); + REGION_UNION(pScreen, &PanoramiXScreenRegion, &PanoramiXScreenRegion, + &XineramaScreenRegions[i]); + } + + PanoramiXPixWidth = panoramiXdataPtr[0].x + panoramiXdataPtr[0].width; + PanoramiXPixHeight = panoramiXdataPtr[0].y + panoramiXdataPtr[0].height; + + for (i = 1; i < PanoramiXNumScreens; i++) { + w = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; + h = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; + + if (PanoramiXPixWidth < w) + PanoramiXPixWidth = w; + if (PanoramiXPixHeight < h) + PanoramiXPixHeight = h; + } +} + +void XineramaReinitData(ScreenPtr pScreen) +{ + int i; + + REGION_UNINIT(pScreen, &PanoramiXScreenRegion); + for (i = 0; i < PanoramiXNumScreens; i++) + REGION_UNINIT(pScreen, &XineramaScreenRegions[i]); + + XineramaInitData(pScreen); +} + +/* + * PanoramiXExtensionInit(): + * Called from InitExtensions in main(). + * Register PanoramiXeen Extension + * Initialize global variables. + */ + +void PanoramiXExtensionInit(int argc, char *argv[]) +{ + int i; + Bool success = FALSE; + ExtensionEntry *extEntry; + ScreenPtr pScreen = screenInfo.screens[0]; + PanoramiXScreenPtr pScreenPriv; + + if (noPanoramiXExtension) + return; + + 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; + } + +#if 0 + PanoramiXReqCode = (unsigned char)extEntry->base; +#endif + + /* + * First make sure all the basic allocations succeed. If not, + * run in non-PanoramiXeen mode. + */ + + panoramiXdataPtr = (PanoramiXData *) + xcalloc(PanoramiXNumScreens, sizeof(PanoramiXData)); + + BREAK_IF(!panoramiXdataPtr); + BREAK_IF((PanoramiXGCIndex = AllocateGCPrivateIndex()) < 0); + BREAK_IF((PanoramiXScreenIndex = AllocateScreenPrivateIndex()) < 0); + + for (i = 0; i < PanoramiXNumScreens; i++) { + pScreen = screenInfo.screens[i]; + if(!AllocateGCPrivate(pScreen, PanoramiXGCIndex, + sizeof(PanoramiXGCRec))) { + noPanoramiXExtension = TRUE; + return; + } + + pScreenPriv = xalloc(sizeof(PanoramiXScreenRec)); + pScreen->devPrivates[PanoramiXScreenIndex].ptr = + (pointer)pScreenPriv; + if(!pScreenPriv) { + noPanoramiXExtension = TRUE; + return; + } + + pScreenPriv->CreateGC = pScreen->CreateGC; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + + pScreen->CreateGC = XineramaCreateGC; + pScreen->CloseScreen = XineramaCloseScreen; + } + + XRC_DRAWABLE = CreateNewResourceClass(); + XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource) | + XRC_DRAWABLE; + XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource) | + XRC_DRAWABLE; + XRT_GC = CreateNewResourceType(XineramaDeleteResource); + XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource); + + panoramiXGeneration = serverGeneration; + success = TRUE; + } + + if (!success) { + noPanoramiXExtension = TRUE; + ErrorF("%s Extension failed to initialize\n", PANORAMIX_PROTOCOL_NAME); + return; + } + + XineramaInitData(pScreen); + + /* + * 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_TranslateCoords] = PanoramiXTranslateCoords; + 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_CopyColormapAndFree] = PanoramiXCopyColormapAndFree; + ProcVector[X_InstallColormap] = PanoramiXInstallColormap; + ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; + ProcVector[X_AllocColor] = PanoramiXAllocColor; + ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; + ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; + ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes; + ProcVector[X_FreeColors] = PanoramiXFreeColors; + ProcVector[X_StoreColors] = PanoramiXStoreColors; + ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor; + +#ifdef RENDER + PanoramiXRenderInit (); +#endif +} + +extern Bool CreateConnectionBlock(void); + +Bool PanoramiXCreateConnectionBlock(void) +{ + int i, j, length; + Bool disableBackingStore = FALSE; + Bool disableSaveUnders = FALSE; + int old_width, old_height; + float width_mult, height_mult; + xWindowRoot *root; + xVisualType *visual; + xDepth *depth; + VisualPtr pVisual; + ScreenPtr pScreen; + + /* + * Do normal CreateConnectionBlock but faking it for only one screen + */ + + if(!PanoramiXNumDepths) { + ErrorF("PanoramiX error: Incompatible screens. No common visuals\n"); + return FALSE; + } + + for(i = 1; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) { + ErrorF("PanoramiX error: Incompatible screens. Root window depths differ\n"); + return FALSE; + } + if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) + disableBackingStore = TRUE; + if(pScreen->saveUnderSupport != screenInfo.screens[0]->saveUnderSupport) + disableSaveUnders = TRUE; + } + + if(disableBackingStore || disableSaveUnders) { + for(i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if(disableBackingStore) + pScreen->backingStoreSupport = NotUseful; + if(disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + } + } + + i = screenInfo.numScreens; + screenInfo.numScreens = 1; + if (!CreateConnectionBlock()) { + screenInfo.numScreens = i; + return FALSE; + } + + screenInfo.numScreens = i; + + root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); + length = connBlockScreenStart + sizeof(xWindowRoot); + + /* overwrite the connection block */ + root->nDepths = PanoramiXNumDepths; + + for (i = 0; i < PanoramiXNumDepths; i++) { + depth = (xDepth *) (ConnectionInfo + length); + depth->depth = PanoramiXDepths[i].depth; + depth->nVisuals = PanoramiXDepths[i].numVids; + length += sizeof(xDepth); + visual = (xVisualType *)(ConnectionInfo + length); + + for (j = 0; j < depth->nVisuals; j++, visual++) { + visual->visualID = PanoramiXDepths[i].vids[j]; + + for (pVisual = PanoramiXVisuals; + pVisual->vid != visual->visualID; + pVisual++) + ; + + visual->class = pVisual->class; + visual->bitsPerRGB = pVisual->bitsPerRGBValue; + visual->colormapEntries = pVisual->ColormapEntries; + visual->redMask = pVisual->redMask; + visual->greenMask = pVisual->greenMask; + visual->blueMask = pVisual->blueMask; + } + + length += (depth->nVisuals * sizeof(xVisualType)); + } + + connSetupPrefix.length = length >> 2; + + xfree(PanoramiXVisuals); + for (i = 0; i < PanoramiXNumDepths; i++) + xfree(PanoramiXDepths[i].vids); + xfree(PanoramiXDepths); + + /* + * OK, change some dimensions so it looks as if it were one big screen + */ + + old_width = root->pixWidth; + old_height = root->pixHeight; + + root->pixWidth = PanoramiXPixWidth; + root->pixHeight = PanoramiXPixHeight; + width_mult = (1.0 * root->pixWidth) / old_width; + height_mult = (1.0 * root->pixHeight) / old_height; + root->mmWidth *= width_mult; + root->mmHeight *= height_mult; + + while(ConnectionCallbackList) { + pointer tmp; + + tmp = (pointer)ConnectionCallbackList; + (*ConnectionCallbackList->func)(); + ConnectionCallbackList = ConnectionCallbackList->next; + xfree(tmp); + } + + return TRUE; +} + +extern +void PanoramiXConsolidate(void) +{ + int i, j, k; + VisualPtr pVisual, pVisual2; + ScreenPtr pScreen, pScreen2; + DepthPtr pDepth, pDepth2; + PanoramiXRes *root, *defmap, *saver; + Bool foundDepth, missingDepth; + + if(!PanoramiXVisualTable) + PanoramiXVisualTable = xcalloc(256 * MAXSCREENS, sizeof(XID)); + + pScreen = screenInfo.screens[0]; + pVisual = pScreen->visuals; + pDepth = pScreen->allowedDepths; + + PanoramiXNumDepths = 0; + PanoramiXDepths = xcalloc(pScreen->numDepths,sizeof(DepthRec)); + PanoramiXNumVisuals = 0; + PanoramiXVisuals = xcalloc(pScreen->numVisuals,sizeof(VisualRec)); + + for (i = 0; i < pScreen->numDepths; i++, pDepth++) { + missingDepth = FALSE; + for (j = 1; j < PanoramiXNumScreens; j++) { + pScreen2 = screenInfo.screens[j]; + pDepth2 = pScreen2->allowedDepths; + + foundDepth = FALSE; + for (k = 0; k < pScreen2->numDepths; k++, pDepth2++) { + if(pDepth2->depth == pDepth->depth) { + foundDepth = TRUE; + break; + } + } + + if(!foundDepth) { + missingDepth = TRUE; + break; + } + } + + if(!missingDepth) { + PanoramiXDepths[PanoramiXNumDepths].depth = pDepth->depth; + PanoramiXDepths[PanoramiXNumDepths].numVids = 0; + if(pDepth->numVids) + PanoramiXDepths[PanoramiXNumDepths].vids = + xalloc(sizeof(VisualID) * pDepth->numVids); + else + PanoramiXDepths[PanoramiXNumDepths].vids = NULL; + PanoramiXNumDepths++; + } + } + + for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { + PanoramiXVisualTable[pVisual->vid * MAXSCREENS] = pVisual->vid; + + /* check if the visual exists on all screens */ + for (j = 1; j < PanoramiXNumScreens; j++) { + pScreen2 = screenInfo.screens[j]; + +#ifdef GLXPROXY + pVisual2 = glxMatchVisual(pScreen, pVisual, pScreen2); + if (pVisual2) { + PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j] = + pVisual2->vid; + continue; + } else if (glxMatchVisual(pScreen, pVisual, pScreen)) { + PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j] = 0; + break; + } +#endif + pVisual2 = pScreen2->visuals; + + for (k = 0; k < pScreen2->numVisuals; k++, pVisual2++) { + if ((pVisual->class == pVisual2->class) && + (pVisual->ColormapEntries == pVisual2->ColormapEntries) && + (pVisual->nplanes == pVisual2->nplanes) && + (pVisual->redMask == pVisual2->redMask) && + (pVisual->greenMask == pVisual2->greenMask) && + (pVisual->blueMask == pVisual2->blueMask) && + (pVisual->offsetRed == pVisual2->offsetRed) && + (pVisual->offsetGreen == pVisual2->offsetGreen) && + (pVisual->offsetBlue == pVisual2->offsetBlue)) + { + /* We merely assign the first visual that matches. OpenGL + will need to get involved at some point if you want + match GLX visuals */ + PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j] = + pVisual2->vid; + break; + } + } + } + + /* if it doesn't exist on all screens we can't use it */ + for (j = 0; j < PanoramiXNumScreens; j++) { + if (!PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j]) { + PanoramiXVisualTable[pVisual->vid * MAXSCREENS] = 0; + break; + } + } + + /* if it does, make sure it's in the list of supported depths and visuals */ + if(PanoramiXVisualTable[pVisual->vid * MAXSCREENS]) { + PanoramiXVisuals[PanoramiXNumVisuals].vid = pVisual->vid; + PanoramiXVisuals[PanoramiXNumVisuals].class = pVisual->class; + PanoramiXVisuals[PanoramiXNumVisuals].bitsPerRGBValue = pVisual->bitsPerRGBValue; + PanoramiXVisuals[PanoramiXNumVisuals].ColormapEntries = pVisual->ColormapEntries; + PanoramiXVisuals[PanoramiXNumVisuals].nplanes = pVisual->nplanes; + PanoramiXVisuals[PanoramiXNumVisuals].redMask = pVisual->redMask; + PanoramiXVisuals[PanoramiXNumVisuals].greenMask = pVisual->greenMask; + PanoramiXVisuals[PanoramiXNumVisuals].blueMask = pVisual->blueMask; + PanoramiXVisuals[PanoramiXNumVisuals].offsetRed = pVisual->offsetRed; + PanoramiXVisuals[PanoramiXNumVisuals].offsetGreen = pVisual->offsetGreen; + PanoramiXVisuals[PanoramiXNumVisuals].offsetBlue = pVisual->offsetBlue; + PanoramiXNumVisuals++; + + for (j = 0; j < PanoramiXNumDepths; j++) { + if (PanoramiXDepths[j].depth == pVisual->nplanes) { + PanoramiXDepths[j].vids[PanoramiXDepths[j].numVids] = pVisual->vid; + PanoramiXDepths[j].numVids++; + break; + } + } + } + } + + + root = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); + root->type = XRT_WINDOW; + defmap = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); + defmap->type = XRT_COLORMAP; + saver = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); + saver->type = XRT_WINDOW; + + + for (i = 0; i < PanoramiXNumScreens; i++) { + root->info[i].id = WindowTable[i]->drawable.id; + root->u.win.class = InputOutput; + root->u.win.root = TRUE; + saver->info[i].id = savedScreenInfo[i].wid; + saver->u.win.class = InputOutput; + saver->u.win.root = TRUE; + defmap->info[i].id = (screenInfo.screens[i])->defColormap; + } + + AddResource(root->info[0].id, XRT_WINDOW, root); + AddResource(saver->info[0].id, XRT_WINDOW, saver); + AddResource(defmap->info[0].id, XRT_COLORMAP, defmap); +} + + +/* + * PanoramiXResetProc() + * Exit, deallocating as needed. + */ + +static void PanoramiXResetProc(ExtensionEntry* extEntry) +{ + int i; + +#ifdef RENDER + PanoramiXRenderReset (); +#endif + screenInfo.numScreens = PanoramiXNumScreens; + for (i = 256; i--; ) + ProcVector[i] = SavedProcVector[i]; + + Xfree(panoramiXdataPtr); +} + + +int +ProcPanoramiXQueryVersion (ClientPtr client) +{ + /* 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); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +int +ProcPanoramiXGetState(ClientPtr client) +{ + 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 +ProcPanoramiXGetScreenCount(ClientPtr client) +{ + 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 +ProcPanoramiXGetScreenSize(ClientPtr client) +{ + 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; +} + + +int +ProcXineramaIsActive(ClientPtr client) +{ + /* REQUEST(xXineramaIsActiveReq); */ + xXineramaIsActiveReply rep; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; +#if 1 + { + /* The following hack fools clients into thinking that Xinerama + * is disabled even though it is not. */ + extern Bool PanoramiXExtensionDisabledHack; + rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack; + } +#else + rep.state = !noPanoramiXExtension; +#endif + if (client->swapped) { + register int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.state, n); + } + WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); + return client->noClientException; +} + + +int +ProcXineramaQueryScreens(ClientPtr client) +{ + /* REQUEST(xXineramaQueryScreensReq); */ + xXineramaQueryScreensReply rep; + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; + rep.length = rep.number * sz_XineramaScreenInfo >> 2; + if (client->swapped) { + register int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.number, n); + } + WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); + + if(!noPanoramiXExtension) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < PanoramiXNumScreens; i++) { + scratch.x_org = panoramiXdataPtr[i].x; + scratch.y_org = panoramiXdataPtr[i].y; + scratch.width = panoramiXdataPtr[i].width; + scratch.height = panoramiXdataPtr[i].height; + + if(client->swapped) { + register int n; + swaps (&scratch.x_org, n); + swaps (&scratch.y_org, n); + swaps (&scratch.width, n); + swaps (&scratch.height, n); + } + WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); + } + } + + return client->noClientException; +} + + +static int +ProcPanoramiXDispatch (ClientPtr client) +{ 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); + case X_XineramaIsActive: + return ProcXineramaIsActive(client); + case X_XineramaQueryScreens: + return ProcXineramaQueryScreens(client); + } + return BadRequest; +} + + +#if X_BYTE_ORDER == X_LITTLE_ENDIAN +#define SHIFT_L(v,s) (v) << (s) +#define SHIFT_R(v,s) (v) >> (s) +#else +#define SHIFT_L(v,s) (v) >> (s) +#define SHIFT_R(v,s) (v) << (s) +#endif + +static void +CopyBits(char *dst, int shiftL, char *src, int bytes) +{ + /* Just get it to work. Worry about speed later */ + int shiftR = 8 - shiftL; + + while(bytes--) { + *dst |= SHIFT_L(*src, shiftL); + *(dst + 1) |= SHIFT_R(*src, shiftR); + dst++; src++; + } +} + + +/* Caution. This doesn't support 2 and 4 bpp formats. We expect + 1 bpp and planar data to be already cleared when presented + to this function */ + +void +XineramaGetImageData( + DrawablePtr *pDrawables, + int left, + int top, + int width, + int height, + unsigned int format, + unsigned long planemask, + char *data, + int pitch, + Bool isRoot +){ + RegionRec SrcRegion, GrabRegion; + BoxRec SrcBox, *pbox; + int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth; + DrawablePtr pDraw = pDrawables[0]; + ScreenPtr pScreen = pDraw->pScreen; + char *ScratchMem = NULL; + + size = 0; + + /* find box in logical screen space */ + SrcBox.x1 = left; + SrcBox.y1 = top; + if(!isRoot) { + SrcBox.x1 += pDraw->x + panoramiXdataPtr[0].x; + SrcBox.y1 += pDraw->y + panoramiXdataPtr[0].y; + } + SrcBox.x2 = SrcBox.x1 + width; + SrcBox.y2 = SrcBox.y1 + height; + + REGION_INIT(pScreen, &SrcRegion, &SrcBox, 1); + REGION_NULL(pScreen, &GrabRegion); + + depth = (format == XYPixmap) ? 1 : pDraw->depth; + + for(i = 0; i < PanoramiXNumScreens; i++) { + pDraw = pDrawables[i]; + + inOut = RECT_IN_REGION(pScreen,&XineramaScreenRegions[i],&SrcBox); + + if(inOut == rgnIN) { + (*pDraw->pScreen->GetImage)(pDraw, + SrcBox.x1 - pDraw->x - panoramiXdataPtr[i].x, + SrcBox.y1 - pDraw->y - panoramiXdataPtr[i].y, + width, height, format, planemask, data); + break; + } else if (inOut == rgnOUT) + continue; + + REGION_INTERSECT(pScreen, &GrabRegion, &SrcRegion, + &XineramaScreenRegions[i]); + + nbox = REGION_NUM_RECTS(&GrabRegion); + + if(nbox) { + pbox = REGION_RECTS(&GrabRegion); + + while(nbox--) { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + ScratchPitch = PixmapBytePad(w, depth); + sizeNeeded = ScratchPitch * h; + + if(sizeNeeded > size) { + char *tmpdata = ScratchMem; + ScratchMem = xrealloc(ScratchMem, sizeNeeded); + if(ScratchMem) + size = sizeNeeded; + else { + ScratchMem = tmpdata; + break; + } + } + + x = pbox->x1 - pDraw->x - panoramiXdataPtr[i].x; + y = pbox->y1 - pDraw->y - panoramiXdataPtr[i].y; + + (*pDraw->pScreen->GetImage)(pDraw, x, y, w, h, + format, planemask, ScratchMem); + + /* copy the memory over */ + + if(depth == 1) { + int k, shift, leftover, index, index2; + + x = pbox->x1 - SrcBox.x1; + y = pbox->y1 - SrcBox.y1; + shift = x & 7; + x >>= 3; + leftover = w & 7; + w >>= 3; + + /* clean up the edge */ + if(leftover) { + int mask = (1 << leftover) - 1; + for(j = h, k = w; j--; k += ScratchPitch) + ScratchMem[k] &= mask; + } + + for(j = 0, index = (pitch * y) + x, index2 = 0; j < h; + j++, index += pitch, index2 += ScratchPitch) + { + if(w) { + if(!shift) + memcpy(data + index, ScratchMem + index2, w); + else + CopyBits(data + index, shift, + ScratchMem + index2, w); + } + + if(leftover) { + data[index + w] |= + SHIFT_L(ScratchMem[index2 + w], shift); + if((shift + leftover) > 8) + data[index + w + 1] |= + SHIFT_R(ScratchMem[index2 + w],(8 - shift)); + } + } + } else { + j = BitsPerPixel(depth) >> 3; + x = (pbox->x1 - SrcBox.x1) * j; + y = pbox->y1 - SrcBox.y1; + w *= j; + + for(j = 0; j < h; j++) { + memcpy(data + (pitch * (y + j)) + x, + ScratchMem + (ScratchPitch * j), w); + } + } + pbox++; + } + + REGION_SUBTRACT(pScreen, &SrcRegion, &SrcRegion, &GrabRegion); + if(!REGION_NOTEMPTY(pScreen, &SrcRegion)) + break; + } + + } + + if(ScratchMem) + xfree(ScratchMem); + + REGION_UNINIT(pScreen, &SrcRegion); + REGION_UNINIT(pScreen, &GrabRegion); +} diff --git a/nx-X11/programs/Xserver/Xext/panoramiX.h b/nx-X11/programs/Xserver/Xext/panoramiX.h new file mode 100644 index 000000000..5fa4ed35c --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/panoramiX.h @@ -0,0 +1,115 @@ +/* $TOG: panoramiX.h /main/4 1998/03/17 06:51:02 kaleb $ */ +/* $XdotOrg: xc/programs/Xserver/Xext/panoramiX.h,v 1.5 2005/07/03 07:01:04 daniels 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. + +******************************************************************/ + +/* $XFree86: xc/programs/Xserver/Xext/panoramiX.h,v 1.5 2001/01/03 02:54:17 keithp Exp $ */ + +/* THIS IS NOT AN X PROJECT TEAM SPECIFICATION */ + +/* + * PanoramiX definitions + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _PANORAMIX_H_ +#define _PANORAMIX_H_ + +#include <X11/extensions/panoramiXext.h> +#include "gcstruct.h" + + +typedef struct _PanoramiXData { + int x; + int y; + int width; + int height; +} PanoramiXData; + +typedef struct _PanoramiXInfo { + XID id ; +} PanoramiXInfo; + +typedef struct { + PanoramiXInfo info[MAXSCREENS]; + RESTYPE type; + union { + struct { + char visibility; + char class; + char root; + } win; + struct { + Bool shared; + } pix; +#ifdef RENDER + struct { + Bool root; + } pict; +#endif + char raw_data[4]; + } u; +} PanoramiXRes; + +#define FOR_NSCREENS_FORWARD(j) for(j = 0; j < PanoramiXNumScreens; j++) +#define FOR_NSCREENS_BACKWARD(j) for(j = PanoramiXNumScreens - 1; j >= 0; j--) +#define FOR_NSCREENS(j) FOR_NSCREENS_FORWARD(j) + +#define BREAK_IF(a) if ((a)) break +#define IF_RETURN(a,b) if ((a)) return (b) + +#define FORCE_ROOT(a) { \ + int _j; \ + for (_j = PanoramiXNumScreens - 1; _j; _j--) \ + if ((a).root == WindowTable[_j]->drawable.id) \ + break; \ + (a).rootX += panoramiXdataPtr[_j].x; \ + (a).rootY += panoramiXdataPtr[_j].y; \ + (a).root = WindowTable[0]->drawable.id; \ +} + +#define FORCE_WIN(a) { \ + if ((win = PanoramiXFindIDOnAnyScreen(XRT_WINDOW, a))) { \ + (a) = win->info[0].id; /* Real ID */ \ + } \ +} + +#define FORCE_CMAP(a) { \ + if ((win = PanoramiXFindIDOnAnyScreen(XRT_COLORMAP, a))) { \ + (a) = win->info[0].id; /* Real ID */ \ + } \ +} + +#define IS_SHARED_PIXMAP(r) (((r)->type == XRT_PIXMAP) && (r)->u.pix.shared) + +#define SKIP_FAKE_WINDOW(a) if(!LookupIDByType(a, XRT_WINDOW)) return + +#endif /* _PANORAMIX_H_ */ diff --git a/nx-X11/programs/Xserver/Xext/panoramiXSwap.c b/nx-X11/programs/Xserver/Xext/panoramiXSwap.c new file mode 100644 index 000000000..e0548df7b --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/panoramiXSwap.c @@ -0,0 +1,144 @@ +/* $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. +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/panoramiXSwap.c,v 3.9 2003/07/16 01:38:29 dawes Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#include <X11/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 <X11/extensions/panoramiXproto.h> +#include "panoramiXsrv.h" +#include "globals.h" +#include "panoramiXh.h" + +static int +SProcPanoramiXQueryVersion (ClientPtr client) +{ + REQUEST(xPanoramiXQueryVersionReq); + register int n; + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + return ProcPanoramiXQueryVersion(client); +} + +static int +SProcPanoramiXGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + return ProcPanoramiXGetState(client); +} + +static int +SProcPanoramiXGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return ProcPanoramiXGetScreenCount(client); +} + +static int +SProcPanoramiXGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return ProcPanoramiXGetScreenSize(client); +} + + +static int +SProcXineramaIsActive(ClientPtr client) +{ + REQUEST(xXineramaIsActiveReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + return ProcXineramaIsActive(client); +} + + +static int +SProcXineramaQueryScreens(ClientPtr client) +{ + REQUEST(xXineramaQueryScreensReq); + register int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + return ProcXineramaQueryScreens(client); +} + + +int +SProcPanoramiXDispatch (ClientPtr client) +{ 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); + case X_XineramaIsActive: + return SProcXineramaIsActive(client); + case X_XineramaQueryScreens: + return SProcXineramaQueryScreens(client); + } + return BadRequest; +} diff --git a/nx-X11/programs/Xserver/Xext/panoramiXh.h b/nx-X11/programs/Xserver/Xext/panoramiXh.h new file mode 100644 index 000000000..9da5876fd --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/panoramiXh.h @@ -0,0 +1,78 @@ +/* $XFree86: xc/programs/Xserver/Xext/panoramiXh.h,v 1.2 2003/09/13 21:33:03 dawes Exp $ */ + +/* + * Server dispatcher function replacements + */ + +extern int PanoramiXCreateWindow(ClientPtr client); +extern int PanoramiXChangeWindowAttributes(ClientPtr client); +extern int PanoramiXDestroyWindow(ClientPtr client); +extern int PanoramiXDestroySubwindows(ClientPtr client); +extern int PanoramiXChangeSaveSet(ClientPtr client); +extern int PanoramiXReparentWindow(ClientPtr client); +extern int PanoramiXMapWindow(ClientPtr client); +extern int PanoramiXMapSubwindows(ClientPtr client); +extern int PanoramiXUnmapWindow(ClientPtr client); +extern int PanoramiXUnmapSubwindows(ClientPtr client); +extern int PanoramiXConfigureWindow(ClientPtr client); +extern int PanoramiXCirculateWindow(ClientPtr client); +extern int PanoramiXGetGeometry(ClientPtr client); +extern int PanoramiXTranslateCoords(ClientPtr client); +extern int PanoramiXCreatePixmap(ClientPtr client); +extern int PanoramiXFreePixmap(ClientPtr client); +extern int PanoramiXCreateGC(ClientPtr client); +extern int PanoramiXChangeGC(ClientPtr client); +extern int PanoramiXCopyGC(ClientPtr client); +extern int PanoramiXCopyColormapAndFree(ClientPtr client); +extern int PanoramiXSetDashes(ClientPtr client); +extern int PanoramiXSetClipRectangles(ClientPtr client); +extern int PanoramiXFreeGC(ClientPtr client); +extern int PanoramiXClearToBackground(ClientPtr client); +extern int PanoramiXCopyArea(ClientPtr client); +extern int PanoramiXCopyPlane(ClientPtr client); +extern int PanoramiXPolyPoint(ClientPtr client); +extern int PanoramiXPolyLine(ClientPtr client); +extern int PanoramiXPolySegment(ClientPtr client); +extern int PanoramiXPolyRectangle(ClientPtr client); +extern int PanoramiXPolyArc(ClientPtr client); +extern int PanoramiXFillPoly(ClientPtr client); +extern int PanoramiXPolyFillArc(ClientPtr client); +extern int PanoramiXPolyFillRectangle(ClientPtr client); +extern int PanoramiXPutImage(ClientPtr client); +extern int PanoramiXGetImage(ClientPtr client); +extern int PanoramiXPolyText8(ClientPtr client); +extern int PanoramiXPolyText16(ClientPtr client); +extern int PanoramiXImageText8(ClientPtr client); +extern int PanoramiXImageText16(ClientPtr client); +extern int PanoramiXCreateColormap(ClientPtr client); +extern int PanoramiXFreeColormap(ClientPtr client); +extern int PanoramiXInstallColormap(ClientPtr client); +extern int PanoramiXUninstallColormap(ClientPtr client); +extern int PanoramiXAllocColor(ClientPtr client); +extern int PanoramiXAllocNamedColor(ClientPtr client); +extern int PanoramiXAllocColorCells(ClientPtr client); +extern int PanoramiXStoreNamedColor(ClientPtr client); +extern int PanoramiXFreeColors(ClientPtr client); +extern int PanoramiXStoreColors(ClientPtr client); +extern int PanoramiXAllocColorPlanes(ClientPtr client); + +#define PROC_EXTERN(pfunc) extern int pfunc(ClientPtr) + +PROC_EXTERN(ProcPanoramiXQueryVersion); +PROC_EXTERN(ProcPanoramiXGetState); +PROC_EXTERN(ProcPanoramiXGetScreenCount); +PROC_EXTERN(ProcPanoramiXGetScreenSize); + +PROC_EXTERN(ProcXineramaQueryScreens); +PROC_EXTERN(ProcXineramaIsActive); +extern Bool XineramaCreateGC(GCPtr pGC); + +extern int SProcPanoramiXDispatch(ClientPtr client); + +extern char *ConnectionInfo; +extern int connBlockScreenStart; +extern xConnSetupPrefix connSetupPrefix; + +extern ScreenInfo *GlobalScrInfo; +extern int (* SavedProcVector[256]) (ClientPtr client); + diff --git a/nx-X11/programs/Xserver/Xext/panoramiXprocs.c b/nx-X11/programs/Xserver/Xext/panoramiXprocs.c new file mode 100644 index 000000000..79a5a3290 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/panoramiXprocs.c @@ -0,0 +1,2372 @@ +/* $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. +******************************************************************/ + +/* Massively rewritten by Mark Vojkovich <markv@valinux.com> */ + +/* $XFree86: xc/programs/Xserver/Xext/panoramiXprocs.c,v 3.36tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/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" +#include "panoramiXsrv.h" +#include "resource.h" +#include "panoramiXh.h" + +#define XINERAMA_IMAGE_BUFSIZE (256*1024) +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#if 0 +extern void (* EventSwapVector[128]) (fsError *, fsError *); + +extern void Swap32Write(); +extern void SLHostsExtend(); +extern void SQColorsExtend(); +WriteSConnectionInfo(); +extern void WriteSConnSetupPrefix(); +#endif + +/* 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. + */ +extern XID clientErrorValue; /* XXX this is a kludge */ + +int PanoramiXCreateWindow(ClientPtr client) +{ + PanoramiXRes *parent, *newWin; + PanoramiXRes *backPix = NULL; + PanoramiXRes *bordPix = NULL; + PanoramiXRes *cmap = NULL; + REQUEST(xCreateWindowReq); + int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; + int result = 0, len, j; + int orig_x, orig_y; + XID orig_visual, tmp; + Bool parentIsRoot; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + if (!(parent = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->parent, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + if(stuff->class == CopyFromParent) + stuff->class = parent->u.win.class; + + if((stuff->class == InputOnly) && (stuff->mask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + if ((Mask)stuff->mask & CWBackPixmap) { + pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pback_offset); + if ((tmp != None) && (tmp != ParentRelative)) { + if(!(backPix = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->mask & CWBorderPixmap) { + pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pbord_offset); + if (tmp != CopyFromParent) { + if(!(bordPix = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->mask & CWColormap) { + cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); + tmp = *((CARD32 *) &stuff[1] + cmap_offset); + if ((tmp != CopyFromParent) && (tmp != None)) { + if(!(cmap = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_COLORMAP, SecurityReadAccess))) + return BadColor; + } + } + + if(!(newWin = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newWin->type = XRT_WINDOW; + newWin->u.win.visibility = VisibilityNotViewable; + newWin->u.win.class = stuff->class; + newWin->u.win.root = FALSE; + newWin->info[0].id = stuff->wid; + for(j = 1; j < PanoramiXNumScreens; j++) + newWin->info[j].id = FakeClientID(client->index); + + if (stuff->class == InputOnly) + stuff->visual = CopyFromParent; + orig_visual = stuff->visual; + orig_x = stuff->x; + orig_y = stuff->y; + parentIsRoot = (stuff->parent == WindowTable[0]->drawable.id) || + (stuff->parent == savedScreenInfo[0].wid); + FOR_NSCREENS_BACKWARD(j) { + stuff->wid = newWin->info[j].id; + stuff->parent = parent->info[j].id; + if (parentIsRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + if (backPix) + *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id; + if (bordPix) + *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id; + if (cmap) + *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id; + if ( orig_visual != CopyFromParent ) + stuff->visual = PanoramiXVisualTable[(orig_visual*MAXSCREENS) + j]; + result = (*SavedProcVector[X_CreateWindow])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newWin->info[0].id, XRT_WINDOW, newWin); + else + xfree(newWin); + + return (result); +} + + +int PanoramiXChangeWindowAttributes(ClientPtr client) +{ + PanoramiXRes *win; + PanoramiXRes *backPix = NULL; + PanoramiXRes *bordPix = NULL; + PanoramiXRes *cmap = NULL; + REQUEST(xChangeWindowAttributesReq); + int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; + int result = 0, len, j; + XID tmp; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (Ones(stuff->valueMask) != len) + return BadLength; + + if (!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->window, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + if((win->u.win.class == InputOnly) && + (stuff->valueMask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + if ((Mask)stuff->valueMask & CWBackPixmap) { + pback_offset = Ones((Mask)stuff->valueMask & (CWBackPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pback_offset); + if ((tmp != None) && (tmp != ParentRelative)) { + if(!(backPix = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->valueMask & CWBorderPixmap) { + pbord_offset = Ones((Mask)stuff->valueMask & (CWBorderPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pbord_offset); + if (tmp != CopyFromParent) { + if(!(bordPix = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->valueMask & CWColormap) { + cmap_offset = Ones((Mask)stuff->valueMask & (CWColormap - 1)); + tmp = *((CARD32 *) &stuff[1] + cmap_offset); + if ((tmp != CopyFromParent) && (tmp != None)) { + if(!(cmap = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_COLORMAP, SecurityReadAccess))) + return BadColor; + } + } + + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + if (backPix) + *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id; + if (bordPix) + *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id; + if (cmap) + *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id; + result = (*SavedProcVector[X_ChangeWindowAttributes])(client); + } + + return (result); +} + + +int PanoramiXDestroyWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_WINDOW, SecurityDestroyAccess))) + return BadWindow; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_DestroyWindow])(client); + if(result != Success) break; + } + + /* Since ProcDestroyWindow is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXDestroySubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_WINDOW, SecurityDestroyAccess))) + return BadWindow; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_DestroySubwindows])(client); + if(result != Success) break; + } + + /* DestroySubwindows is using FreeResource which will free + our resources for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXChangeSaveSet(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xChangeSaveSetReq); + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->window, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + result = (*SavedProcVector[X_ChangeSaveSet])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXReparentWindow(ClientPtr client) +{ + PanoramiXRes *win, *parent; + int result = 0, j; + int x, y; + Bool parentIsRoot; + REQUEST(xReparentWindowReq); + + REQUEST_SIZE_MATCH(xReparentWindowReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->window, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + if(!(parent = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->parent, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + x = stuff->x; + y = stuff->y; + parentIsRoot = (stuff->parent == WindowTable[0]->drawable.id) || + (stuff->parent == savedScreenInfo[0].wid); + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + stuff->parent = parent->info[j].id; + if(parentIsRoot) { + stuff->x = x - panoramiXdataPtr[j].x; + stuff->y = y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ReparentWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXMapWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_MapWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXMapSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_MapSubwindows])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXUnmapWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_UnmapWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXUnmapSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_UnmapSubwindows])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXConfigureWindow(ClientPtr client) +{ + PanoramiXRes *win; + PanoramiXRes *sib = NULL; + WindowPtr pWin; + int result = 0, j, len, sib_offset = 0, x = 0, y = 0; + int x_offset = -1; + int y_offset = -1; + REQUEST(xConfigureWindowReq); + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + /* because we need the parent */ + if (!(pWin = (WindowPtr)SecurityLookupIDByType( + client, stuff->window, RT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + if (!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->window, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + if ((Mask)stuff->mask & CWSibling) { + XID tmp; + sib_offset = Ones((Mask)stuff->mask & (CWSibling - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + sib_offset))) { + if(!(sib = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + } + } + + if(pWin->parent && ((pWin->parent == WindowTable[0]) || + (pWin->parent->drawable.id == savedScreenInfo[0].wid))) + { + if ((Mask)stuff->mask & CWX) { + x_offset = 0; + x = *((CARD32 *)&stuff[1]); + } + if ((Mask)stuff->mask & CWY) { + y_offset = (x_offset == -1) ? 0 : 1; + y = *((CARD32 *) &stuff[1] + y_offset); + } + } + + /* have to go forward or you get expose events before + ConfigureNotify events */ + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + if(sib) + *((CARD32 *) &stuff[1] + sib_offset) = sib->info[j].id; + if(x_offset >= 0) + *((CARD32 *) &stuff[1] + x_offset) = x - panoramiXdataPtr[j].x; + if(y_offset >= 0) + *((CARD32 *) &stuff[1] + y_offset) = y - panoramiXdataPtr[j].y; + result = (*SavedProcVector[X_ConfigureWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXCirculateWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->window, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + result = (*SavedProcVector[X_CirculateWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXGetGeometry(ClientPtr client) +{ + xGetGeometryReply rep; + 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[0]->drawable.id; + rep.depth = pDraw->depth; + rep.width = pDraw->width; + rep.height = pDraw->height; + rep.x = rep.y = rep.borderWidth = 0; + + if (stuff->id == rep.root) { + xWindowRoot *root = (xWindowRoot *) + (ConnectionInfo + connBlockScreenStart); + + rep.width = root->pixWidth; + rep.height = root->pixHeight; + } else + if ((pDraw->type == UNDRAWABLE_WINDOW) || (pDraw->type == DRAWABLE_WINDOW)) + { + WindowPtr pWin = (WindowPtr)pDraw; + rep.x = pWin->origin.x - wBorderWidth (pWin); + rep.y = pWin->origin.y - wBorderWidth (pWin); + if((pWin->parent == WindowTable[0]) || + (pWin->parent->drawable.id == savedScreenInfo[0].wid)) + { + rep.x += panoramiXdataPtr[0].x; + rep.y += panoramiXdataPtr[0].y; + } + rep.borderWidth = pWin->borderWidth; + } + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return (client->noClientException); +} + +int PanoramiXTranslateCoords(ClientPtr client) +{ + INT16 x, y; + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sameScreen = xTrue; + rep.child = None; + + if((pWin == WindowTable[0]) || + (pWin->drawable.id == savedScreenInfo[0].wid)) + { + x = stuff->srcX - panoramiXdataPtr[0].x; + y = stuff->srcY - panoramiXdataPtr[0].y; + } else { + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + } + pWin = pDst->firstChild; + while (pWin) { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wBoundingShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + if((pDst == WindowTable[0]) || + (pDst->drawable.id == savedScreenInfo[0].wid)) + { + rep.dstX += panoramiXdataPtr[0].x; + rep.dstY += panoramiXdataPtr[0].y; + } + + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int PanoramiXCreatePixmap(ClientPtr client) +{ + PanoramiXRes *refDraw, *newPix; + int result = 0, j; + REQUEST(xCreatePixmapReq); + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityReadAccess))) + return BadDrawable; + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = FALSE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPix->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*SavedProcVector[X_CreatePixmap])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPix->info[0].id, XRT_PIXMAP, newPix); + else + xfree(newPix); + + return (result); +} + + +int PanoramiXFreePixmap(ClientPtr client) +{ + PanoramiXRes *pix; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + if(!(pix = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_PIXMAP, SecurityDestroyAccess))) + return BadPixmap; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = pix->info[j].id; + result = (*SavedProcVector[X_FreePixmap])(client); + if(result != Success) break; + } + + /* Since ProcFreePixmap is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXCreateGC(ClientPtr client) +{ + PanoramiXRes *refDraw; + PanoramiXRes *newGC; + PanoramiXRes *stip = NULL; + PanoramiXRes *tile = NULL; + PanoramiXRes *clip = NULL; + REQUEST(xCreateGCReq); + int tile_offset = 0, stip_offset = 0, clip_offset = 0; + int result = 0, len, j; + XID tmp; + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + + client->errorValue = stuff->gc; + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + if (!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityReadAccess))) + return BadDrawable; + + if ((Mask)stuff->mask & GCTile) { + tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) { + if(!(tile = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->mask & GCStipple) { + stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) { + if(!(stip = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->mask & GCClipMask) { + clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) { + if(!(clip = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + + if(!(newGC = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newGC->type = XRT_GC; + newGC->info[0].id = stuff->gc; + for(j = 1; j < PanoramiXNumScreens; j++) + newGC->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = newGC->info[j].id; + stuff->drawable = refDraw->info[j].id; + if (tile) + *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id; + if (stip) + *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id; + if (clip) + *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id; + result = (*SavedProcVector[X_CreateGC])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newGC->info[0].id, XRT_GC, newGC); + else + xfree(newGC); + + return (result); +} + +int PanoramiXChangeGC(ClientPtr client) +{ + PanoramiXRes *gc; + PanoramiXRes *stip = NULL; + PanoramiXRes *tile = NULL; + PanoramiXRes *clip = NULL; + REQUEST(xChangeGCReq); + int tile_offset = 0, stip_offset = 0, clip_offset = 0; + int result = 0, len, j; + XID tmp; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + if (!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if ((Mask)stuff->mask & GCTile) { + tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) { + if(!(tile = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->mask & GCStipple) { + stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) { + if(!(stip = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + if ((Mask)stuff->mask & GCClipMask) { + clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) { + if(!(clip = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + if (tile) + *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id; + if (stip) + *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id; + if (clip) + *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id; + result = (*SavedProcVector[X_ChangeGC])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXCopyGC(ClientPtr client) +{ + PanoramiXRes *srcGC, *dstGC; + int result = 0, j; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + + if(!(srcGC = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->srcGC, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(dstGC = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->dstGC, XRT_GC, SecurityWriteAccess))) + return BadGC; + + FOR_NSCREENS(j) { + stuff->srcGC = srcGC->info[j].id; + stuff->dstGC = dstGC->info[j].id; + result = (*SavedProcVector[X_CopyGC])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXSetDashes(ClientPtr client) +{ + PanoramiXRes *gc; + int result = 0, j; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityWriteAccess))) + return BadGC; + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + result = (*SavedProcVector[X_SetDashes])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXSetClipRectangles(ClientPtr client) +{ + PanoramiXRes *gc; + int result = 0, j; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityWriteAccess))) + return BadGC; + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + result = (*SavedProcVector[X_SetClipRectangles])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXFreeGC(ClientPtr client) +{ + PanoramiXRes *gc; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_GC, SecurityDestroyAccess))) + return BadGC; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = gc->info[j].id; + result = (*SavedProcVector[X_FreeGC])(client); + if(result != Success) break; + } + + /* Since ProcFreeGC is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXClearToBackground(ClientPtr client) +{ + PanoramiXRes *win; + int result = 0, j, x, y; + Bool isRoot; + REQUEST(xClearAreaReq); + + REQUEST_SIZE_MATCH(xClearAreaReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->window, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + x = stuff->x; + y = stuff->y; + isRoot = win->u.win.root; + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + if(isRoot) { + stuff->x = x - panoramiXdataPtr[j].x; + stuff->y = y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ClearArea])(client); + if(result != Success) break; + } + + return (result); +} + + +/* + For Window to Pixmap copies you're screwed since each screen's + pixmap will look like what it sees on its screen. Unless the + screens overlap and the window lies on each, the two copies + will be out of sync. To remedy this we do a GetImage and PutImage + in place of the copy. Doing this as a single Image isn't quite + correct since it will include the obscured areas but we will + have to fix this later. (MArk). +*/ + +int PanoramiXCopyArea(ClientPtr client) +{ + int j, result = 0, srcx, srcy, dstx, dsty; + PanoramiXRes *gc, *src, *dst; + Bool srcIsRoot = FALSE; + Bool dstIsRoot = FALSE; + Bool srcShared, dstShared; + REQUEST(xCopyAreaReq); + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + if(!(src = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->srcDrawable, XRC_DRAWABLE, SecurityReadAccess))) + return BadDrawable; + + srcShared = IS_SHARED_PIXMAP(src); + + if(!(dst = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->dstDrawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + dstShared = IS_SHARED_PIXMAP(dst); + + if(dstShared && srcShared) + return (* SavedProcVector[X_CopyArea])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if((dst->type == XRT_WINDOW) && dst->u.win.root) + dstIsRoot = TRUE; + if((src->type == XRT_WINDOW) && src->u.win.root) + srcIsRoot = TRUE; + + srcx = stuff->srcX; srcy = stuff->srcY; + dstx = stuff->dstX; dsty = stuff->dstY; + if((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) { + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDst; + GCPtr pGC; + char *data; + int pitch; + + FOR_NSCREENS(j) + VERIFY_DRAWABLE(drawables[j], src->info[j].id, client); + + pitch = PixmapBytePad(stuff->width, drawables[0]->depth); + if(!(data = xcalloc(1, stuff->height * pitch))) + return BadAlloc; + + XineramaGetImageData(drawables, srcx, srcy, + stuff->width, stuff->height, ZPixmap, ~0, data, pitch, + srcIsRoot); + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + VALIDATE_DRAWABLE_AND_GC(dst->info[j].id, pDst, pGC, client); + + if(drawables[0]->depth != pDst->depth) { + client->errorValue = stuff->dstDrawable; + xfree(data); + return (BadMatch); + } + + (*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx, dsty, + stuff->width, stuff->height, + 0, ZPixmap, data); + + if(dstShared) break; + } + + xfree(data); + + result = Success; + } else { + DrawablePtr pDst = NULL, pSrc = NULL; + GCPtr pGC = NULL; + RegionPtr pRgn[MAXSCREENS]; + + FOR_NSCREENS_BACKWARD(j) { + stuff->dstDrawable = dst->info[j].id; + stuff->srcDrawable = src->info[j].id; + stuff->gc = gc->info[j].id; + if (srcIsRoot) { + stuff->srcX = srcx - panoramiXdataPtr[j].x; + stuff->srcY = srcy - panoramiXdataPtr[j].y; + } + if (dstIsRoot) { + stuff->dstX = dstx - panoramiXdataPtr[j].x; + stuff->dstY = dsty - panoramiXdataPtr[j].y; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || + (pDst->depth != pSrc->depth)) { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } else + pSrc = pDst; + + pRgn[j] = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, + stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + + if(dstShared) { + while(j--) pRgn[j] = NULL; + break; + } + } + + if(pGC->graphicsExposures) { + ScreenPtr pScreen = pDst->pScreen; + RegionRec totalReg; + Bool overlap; + + REGION_NULL(pScreen, &totalReg); + FOR_NSCREENS_BACKWARD(j) { + if(pRgn[j]) { + if(srcIsRoot) { + REGION_TRANSLATE(pScreen, pRgn[j], + panoramiXdataPtr[j].x, panoramiXdataPtr[j].y); + } + REGION_APPEND(pScreen, &totalReg, pRgn[j]); + REGION_DESTROY(pScreen, pRgn[j]); + } + } + REGION_VALIDATE(pScreen, &totalReg, &overlap); + (*pScreen->SendGraphicsExpose)( + client, &totalReg, stuff->dstDrawable, X_CopyArea, 0); + REGION_UNINIT(pScreen, &totalReg); + } + + result = client->noClientException; + } + + return (result); +} + + +int PanoramiXCopyPlane(ClientPtr client) +{ + int j, srcx, srcy, dstx, dsty; + PanoramiXRes *gc, *src, *dst; + Bool srcIsRoot = FALSE; + Bool dstIsRoot = FALSE; + Bool srcShared, dstShared; + DrawablePtr psrcDraw, pdstDraw = NULL; + GCPtr pGC = NULL; + RegionPtr pRgn[MAXSCREENS]; + REQUEST(xCopyPlaneReq); + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + if(!(src = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->srcDrawable, XRC_DRAWABLE, SecurityReadAccess))) + return BadDrawable; + + srcShared = IS_SHARED_PIXMAP(src); + + if(!(dst = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->dstDrawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + dstShared = IS_SHARED_PIXMAP(dst); + + if(dstShared && srcShared) + return (* SavedProcVector[X_CopyPlane])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if((dst->type == XRT_WINDOW) && dst->u.win.root) + dstIsRoot = TRUE; + if((src->type == XRT_WINDOW) && src->u.win.root) + srcIsRoot = TRUE; + + srcx = stuff->srcX; srcy = stuff->srcY; + dstx = stuff->dstX; dsty = stuff->dstY; + + FOR_NSCREENS_BACKWARD(j) { + stuff->dstDrawable = dst->info[j].id; + stuff->srcDrawable = src->info[j].id; + stuff->gc = gc->info[j].id; + if (srcIsRoot) { + stuff->srcX = srcx - panoramiXdataPtr[j].x; + stuff->srcY = srcy - panoramiXdataPtr[j].y; + } + if (dstIsRoot) { + stuff->dstX = dstx - panoramiXdataPtr[j].x; + stuff->dstY = dsty - panoramiXdataPtr[j].y; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } else + psrcDraw = pdstDraw; + + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn[j] = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, + stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + + if(dstShared) { + while(j--) pRgn[j] = NULL; + break; + } + } + + if(pGC->graphicsExposures) { + ScreenPtr pScreen = pdstDraw->pScreen; + RegionRec totalReg; + Bool overlap; + + REGION_NULL(pScreen, &totalReg); + FOR_NSCREENS_BACKWARD(j) { + if(pRgn[j]) { + REGION_APPEND(pScreen, &totalReg, pRgn[j]); + REGION_DESTROY(pScreen, pRgn[j]); + } + } + REGION_VALIDATE(pScreen, &totalReg, &overlap); + (*pScreen->SendGraphicsExpose)( + client, &totalReg, stuff->dstDrawable, X_CopyPlane, 0); + REGION_UNINIT(pScreen, &totalReg); + } + + return (client->noClientException); +} + + +int PanoramiXPolyPoint(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + int result = 0, npoint, j; + xPoint *origPts; + Bool isRoot; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyPoint])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + 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_FORWARD(j){ + + if(j) memcpy(&stuff[1], origPts, npoint * sizeof(xPoint)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPoint *pnts = (xPoint*)&stuff[1]; + int i = (stuff->coordMode==CoordModePrevious) ? 1 : npoint; + + while(i--) { + pnts->x -= x_off; + pnts->y -= y_off; + pnts++; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyPoint])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(origPts); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXPolyLine(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + int result = 0, npoint, j; + xPoint *origPts; + Bool isRoot; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyLine])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + 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_FORWARD(j){ + + if(j) memcpy(&stuff[1], origPts, npoint * sizeof(xPoint)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPoint *pnts = (xPoint*)&stuff[1]; + int i = (stuff->coordMode==CoordModePrevious) ? 1 : npoint; + + while(i--) { + pnts->x -= x_off; + pnts->y -= y_off; + pnts++; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyLine])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(origPts); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXPolySegment(ClientPtr client) +{ + int result = 0, nsegs, i, j; + PanoramiXRes *gc, *draw; + xSegment *origSegs; + Bool isRoot; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolySegment])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if(nsegs & 4) return BadLength; + nsegs >>= 3; + if (nsegs > 0) { + origSegs = (xSegment *) ALLOCATE_LOCAL(nsegs * sizeof(xSegment)); + memcpy((char *) origSegs, (char *) &stuff[1], nsegs * sizeof(xSegment)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origSegs, nsegs * sizeof(xSegment)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xSegment *segs = (xSegment*)&stuff[1]; + + for (i = nsegs; i--; segs++) { + segs->x1 -= x_off; + segs->x2 -= x_off; + segs->y1 -= y_off; + segs->y2 -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolySegment])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(origSegs); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXPolyRectangle(ClientPtr client) +{ + int result = 0, nrects, i, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + xRectangle *origRecs; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyRectangle])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if(nrects & 4) return BadLength; + nrects >>= 3; + if (nrects > 0){ + origRecs = (xRectangle *) ALLOCATE_LOCAL(nrects * sizeof(xRectangle)); + memcpy((char *)origRecs,(char *)&stuff[1],nrects * sizeof(xRectangle)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origRecs, nrects * sizeof(xRectangle)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) &stuff[1]; + + for (i = nrects; i--; rects++) { + rects->x -= x_off; + rects->y -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyRectangle])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(origRecs); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXPolyArc(ClientPtr client) +{ + int result = 0, narcs, i, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + xArc *origArcs; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyArc])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if(narcs % sizeof(xArc)) return 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_FORWARD(j){ + + if(j) memcpy(&stuff[1], origArcs, narcs * sizeof(xArc)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xArc *arcs = (xArc *) &stuff[1]; + + for (i = narcs; i--; arcs++) { + arcs->x -= x_off; + arcs->y -= y_off; + } + } + } + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyArc])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(origArcs); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXFillPoly(ClientPtr client) +{ + int result = 0, count, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + DDXPointPtr locPts; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_FillPoly])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + 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_FORWARD(j){ + + if(j) memcpy(&stuff[1], locPts, count * sizeof(DDXPointRec)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + DDXPointPtr pnts = (DDXPointPtr)&stuff[1]; + int i = (stuff->coordMode==CoordModePrevious) ? 1 : count; + + while(i--) { + pnts->x -= x_off; + pnts->y -= y_off; + pnts++; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_FillPoly])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(locPts); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXPolyFillRectangle(ClientPtr client) +{ + int result = 0, things, i, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + xRectangle *origRects; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyFillRectangle])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if(things & 4) return BadLength; + things >>= 3; + if (things > 0){ + origRects = (xRectangle *) ALLOCATE_LOCAL(things * sizeof(xRectangle)); + memcpy((char*)origRects,(char*)&stuff[1], things * sizeof(xRectangle)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origRects, things * sizeof(xRectangle)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) &stuff[1]; + + for (i = things; i--; rects++) { + rects->x -= x_off; + rects->y -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyFillRectangle])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(origRects); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXPolyFillArc(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int result = 0, narcs, i, j; + xArc *origArcs; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyFillArc])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + 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_FORWARD(j){ + + if(j) memcpy(&stuff[1], origArcs, narcs * sizeof(xArc)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xArc *arcs = (xArc *) &stuff[1]; + + for (i = narcs; i--; arcs++) { + arcs->x -= x_off; + arcs->y -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyFillArc])(client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(origArcs); + return (result); + } else + return (client->noClientException); +} + + +int PanoramiXPutImage(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int j, result = 0, orig_x, orig_y; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PutImage])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + FOR_NSCREENS_BACKWARD(j){ + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PutImage])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXGetImage(ClientPtr client) +{ + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + PanoramiXRes *draw; + xGetImageReply xgi; + Bool isRoot; + char *pBuf; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + int linesDone, nlines, linesPerBuf; + long widthBytesLine, length; + + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(draw->type == XRT_PIXMAP) + return (*SavedProcVector[X_GetImage])(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + if(!((WindowPtr)pDraw)->realized) + return(BadMatch); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual (((WindowPtr) pDraw)); + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + + + } else { + widthBytesLine = BitmapBytePad(w); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * h * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = (length + 3) >> 2; + + if (widthBytesLine == 0 || h == 0) + linesPerBuf = 0; + else if (widthBytesLine >= XINERAMA_IMAGE_BUFSIZE) + linesPerBuf = 1; + else { + linesPerBuf = XINERAMA_IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > h) + linesPerBuf = h; + } + length = linesPerBuf * widthBytesLine; + if(!(pBuf = xalloc(length))) + return (BadAlloc); + + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + + if (linesPerBuf == 0) { + /* nothing to do */ + } + else if (format == ZPixmap) { + linesDone = 0; + while (h - linesDone > 0) { + nlines = min(linesPerBuf, h - linesDone); + + if(pDraw->depth == 1) + bzero(pBuf, nlines * widthBytesLine); + + XineramaGetImageData(drawables, x, y + linesDone, w, nlines, + format, planemask, pBuf, widthBytesLine, isRoot); + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + linesDone += nlines; + } + } else { /* XYPixmap */ + for (; plane; plane >>= 1) { + if (planemask & plane) { + linesDone = 0; + while (h - linesDone > 0) { + nlines = min(linesPerBuf, h - linesDone); + + bzero(pBuf, nlines * widthBytesLine); + + XineramaGetImageData(drawables, x, y + linesDone, w, + nlines, format, plane, pBuf, + widthBytesLine, isRoot); + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + + linesDone += nlines; + } + } + } + } + xfree(pBuf); + return (client->noClientException); +} + + +/* The text stuff should be rewritten so that duplication happens + at the GlyphBlt level. That is, loading the font and getting + the glyphs should only happen once */ + +int +PanoramiXPolyText8(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int result = 0, j; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyText8])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_PolyText8])(client); + if(result != Success) break; + } + return (result); +} + +int +PanoramiXPolyText16(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int result = 0, j; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyText16])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_PolyText16])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXImageText8(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_ImageText8])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ImageText8])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXImageText16(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_ImageText16])(client); + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ImageText16])(client); + if(result != Success) break; + } + return (result); +} + + + +int PanoramiXCreateColormap(ClientPtr client) +{ + PanoramiXRes *win, *newCmap; + int result = 0, j, orig_visual; + REQUEST(xCreateColormapReq); + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->window, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + + if(!stuff->visual || (stuff->visual > 255)) + return BadValue; + + if(!(newCmap = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newCmap->type = XRT_COLORMAP; + newCmap->info[0].id = stuff->mid; + for(j = 1; j < PanoramiXNumScreens; j++) + newCmap->info[j].id = FakeClientID(client->index); + + orig_visual = stuff->visual; + FOR_NSCREENS_BACKWARD(j){ + stuff->mid = newCmap->info[j].id; + stuff->window = win->info[j].id; + stuff->visual = PanoramiXVisualTable[(orig_visual * MAXSCREENS) + j]; + result = (* SavedProcVector[X_CreateColormap])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap); + else + xfree(newCmap); + + return (result); +} + + +int PanoramiXFreeColormap(ClientPtr client) +{ + PanoramiXRes *cmap; + int result = 0, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_COLORMAP, SecurityDestroyAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = cmap->info[j].id; + result = (* SavedProcVector[X_FreeColormap])(client); + if(result != Success) break; + } + + /* Since ProcFreeColormap is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int +PanoramiXCopyColormapAndFree(ClientPtr client) +{ + PanoramiXRes *cmap, *newCmap; + int result = 0, j; + REQUEST(xCopyColormapAndFreeReq); + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + + client->errorValue = stuff->srcCmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->srcCmap, XRT_COLORMAP, + SecurityReadAccess | SecurityWriteAccess))) + return BadColor; + + if(!(newCmap = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newCmap->type = XRT_COLORMAP; + newCmap->info[0].id = stuff->mid; + for(j = 1; j < PanoramiXNumScreens; j++) + newCmap->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j){ + stuff->srcCmap = cmap->info[j].id; + stuff->mid = newCmap->info[j].id; + result = (* SavedProcVector[X_CopyColormapAndFree])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap); + else + xfree(newCmap); + + return (result); +} + + +int PanoramiXInstallColormap(ClientPtr client) +{ + REQUEST(xResourceReq); + int result = 0, j; + PanoramiXRes *cmap; + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_COLORMAP, SecurityReadAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j){ + stuff->id = cmap->info[j].id; + result = (* SavedProcVector[X_InstallColormap])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXUninstallColormap(ClientPtr client) +{ + REQUEST(xResourceReq); + int result = 0, j; + PanoramiXRes *cmap; + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->id, XRT_COLORMAP, SecurityReadAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = cmap->info[j].id; + result = (* SavedProcVector[X_UninstallColormap])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocColor(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *cmap; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + + client->errorValue = stuff->cmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->cmap, XRT_COLORMAP, SecurityWriteAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocColor])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocNamedColor(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *cmap; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + + client->errorValue = stuff->cmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->cmap, XRT_COLORMAP, SecurityWriteAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocNamedColor])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocColorCells(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *cmap; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + + client->errorValue = stuff->cmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->cmap, XRT_COLORMAP, SecurityWriteAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocColorCells])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocColorPlanes(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *cmap; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + + client->errorValue = stuff->cmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->cmap, XRT_COLORMAP, SecurityWriteAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocColorPlanes])(client); + if(result != Success) break; + } + return (result); +} + + + +int PanoramiXFreeColors(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *cmap; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + + client->errorValue = stuff->cmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->cmap, XRT_COLORMAP, SecurityWriteAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j) { + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_FreeColors])(client); + } + return (result); +} + + +int PanoramiXStoreColors(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *cmap; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + + client->errorValue = stuff->cmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->cmap, XRT_COLORMAP, SecurityWriteAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_StoreColors])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXStoreNamedColor(ClientPtr client) +{ + int result = 0, j; + PanoramiXRes *cmap; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + + client->errorValue = stuff->cmap; + + if(!(cmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->cmap, XRT_COLORMAP, SecurityWriteAccess))) + return BadColor; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_StoreNamedColor])(client); + if(result != Success) break; + } + return (result); +} diff --git a/nx-X11/programs/Xserver/Xext/panoramiXsrv.h b/nx-X11/programs/Xserver/Xext/panoramiXsrv.h new file mode 100644 index 000000000..dc3b3d805 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/panoramiXsrv.h @@ -0,0 +1,50 @@ +/* $XFree86: xc/programs/Xserver/Xext/panoramiXsrv.h,v 1.8 2001/08/01 00:44:44 tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _PANORAMIXSRV_H_ +#define _PANORAMIXSRV_H_ + +#include "panoramiX.h" + +extern int PanoramiXNumScreens; +extern PanoramiXData *panoramiXdataPtr; +extern int PanoramiXPixWidth; +extern int PanoramiXPixHeight; +extern RegionRec PanoramiXScreenRegion; +extern XID *PanoramiXVisualTable; + +extern void PanoramiXConsolidate(void); +extern Bool PanoramiXCreateConnectionBlock(void); +extern PanoramiXRes * PanoramiXFindIDByScrnum(RESTYPE, XID, int); +extern PanoramiXRes * PanoramiXFindIDOnAnyScreen(RESTYPE, XID); +extern WindowPtr PanoramiXChangeWindow(int, WindowPtr); +extern Bool XineramaRegisterConnectionBlockCallback(void (*func)(void)); +extern int XineramaDeleteResource(pointer, XID); + +extern void XineramaReinitData(ScreenPtr); + +extern RegionRec XineramaScreenRegions[MAXSCREENS]; + +extern unsigned long XRC_DRAWABLE; +extern unsigned long XRT_WINDOW; +extern unsigned long XRT_PIXMAP; +extern unsigned long XRT_GC; +extern unsigned long XRT_COLORMAP; + +extern void XineramaGetImageData( + DrawablePtr *pDrawables, + int left, + int top, + int width, + int height, + unsigned int format, + unsigned long planemask, + char *data, + int pitch, + Bool isRoot +); + +#endif /* _PANORAMIXSRV_H_ */ diff --git a/nx-X11/programs/Xserver/Xext/sampleEVI.c b/nx-X11/programs/Xserver/Xext/sampleEVI.c new file mode 100644 index 000000000..500a585c9 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/sampleEVI.c @@ -0,0 +1,125 @@ +/* $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. +********************************************************/ +/* $XFree86$ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "dixstruct.h" +#include "extnsionst.h" +#include "dix.h" +#define _XEVI_SERVER_ +#include <X11/extensions/XEVIstr.h> +#include "EVIstruct.h" +#include "scrnintstr.h" + +#if HAVE_STDINT_H +#include <stdint.h> +#elif !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +static int sampleGetVisualInfo( + VisualID32 *visual, + int n_visual, + xExtendedVisualInfo **evi_rn, + int *n_info_rn, + VisualID32 **conflict_rn, + int *n_conflict_rn) +{ + unsigned int max_sz_evi; + VisualID32 *temp_conflict; + xExtendedVisualInfo *evi; + unsigned int max_visuals = 0, max_sz_conflict, sz_conflict = 0; + register int visualI, scrI, sz_evi = 0, conflictI, n_conflict; + + if (n_visual > UINT32_MAX/(sz_xExtendedVisualInfo * screenInfo.numScreens)) + return BadAlloc; + max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens; + + for (scrI = 0; scrI < screenInfo.numScreens; scrI++) { + if (screenInfo.screens[scrI]->numVisuals > max_visuals) + max_visuals = screenInfo.screens[scrI]->numVisuals; + } + + if (n_visual > UINT32_MAX/(sz_VisualID32 * screenInfo.numScreens + * max_visuals)) + return BadAlloc; + max_sz_conflict = n_visual * sz_VisualID32 * screenInfo.numScreens * max_visuals; + + *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi); + if (!*evi_rn) + return BadAlloc; + + 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(void) +{ + static EviPrivRec eviPriv; + eviPriv.getVisualInfo = sampleGetVisualInfo; + eviPriv.freeVisualInfo = sampleFreeVisualInfo; + return &eviPriv; +} + +void eviDDXReset(void) +{ +} diff --git a/nx-X11/programs/Xserver/Xext/saver.c b/nx-X11/programs/Xserver/Xext/saver.c new file mode 100644 index 000000000..14b0d2751 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/saver.c @@ -0,0 +1,1415 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/saver.c,v 1.10 2005/07/03 08:53:36 daniels Exp $ */ +/* + * $XConsortium: saver.c,v 1.12 94/04/17 20:59:36 dpw Exp $ + * +Copyright (c) 1992 X Consortium + +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, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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 +X CONSORTIUM 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 X Consortium 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 X Consortium. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* $XFree86: xc/programs/Xserver/Xext/saver.c,v 3.7 2003/10/28 23:08:43 tsi Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/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 <X11/extensions/saverproto.h> +#include "gcstruct.h" +#include "cursorstr.h" +#include "colormapst.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + + +#ifdef IN_MODULE +#include <xf86_ansic.h> +#else +#include <stdio.h> +#endif + +#include "modinit.h" + +#if 0 +static unsigned char ScreenSaverReqCode = 0; +#endif +static int ScreenSaverEventBase = 0; + +extern DISPATCH_PROC(ProcScreenSaverQueryInfo); +static DISPATCH_PROC(ProcScreenSaverDispatch); +static DISPATCH_PROC(ProcScreenSaverQueryVersion); +static DISPATCH_PROC(ProcScreenSaverSelectInput); +static DISPATCH_PROC(ProcScreenSaverSetAttributes); +static DISPATCH_PROC(ProcScreenSaverUnsetAttributes); +static DISPATCH_PROC(SProcScreenSaverDispatch); +static DISPATCH_PROC(SProcScreenSaverQueryInfo); +static DISPATCH_PROC(SProcScreenSaverQueryVersion); +static DISPATCH_PROC(SProcScreenSaverSelectInput); +static DISPATCH_PROC(SProcScreenSaverSetAttributes); +static DISPATCH_PROC(SProcScreenSaverUnsetAttributes); + +static Bool ScreenSaverHandle ( + ScreenPtr /* pScreen */, + int /* xstate */, + Bool /* force */ + ); + +static Bool +CreateSaverWindow ( + ScreenPtr /* pScreen */ + ); + +static Bool +DestroySaverWindow ( + ScreenPtr /* pScreen */ + ); + +static void +UninstallSaverColormap ( + ScreenPtr /* pScreen */ + ); + +static void +CheckScreenPrivate ( + ScreenPtr /* pScreen */ + ); + +static void SScreenSaverNotifyEvent ( + xScreenSaverNotifyEvent * /* from */, + xScreenSaverNotifyEvent * /* to */ + ); + +static void ScreenSaverResetProc ( + ExtensionEntry * /* extEntry */ + ); + +/* + * each screen has a list of clients requesting + * ScreenSaverNotify events. Each client has a resource + * for each screen it selects ScreenSaverNotify input for, + * this resource is used to delete the ScreenSaverNotifyRec + * entry from the per-screen queue. + */ + +static RESTYPE EventType; /* resource type for event masks */ + +typedef struct _ScreenSaverEvent *ScreenSaverEventPtr; + +typedef struct _ScreenSaverEvent { + ScreenSaverEventPtr next; + ClientPtr client; + ScreenPtr screen; + XID resource; + CARD32 mask; +} ScreenSaverEventRec; + +static int ScreenSaverFreeEvents( + pointer /* value */, + XID /* id */ +); + +static Bool setEventMask ( + ScreenPtr /* pScreen */, + ClientPtr /* client */, + unsigned long /* mask */ +); + +static unsigned long getEventMask ( + ScreenPtr /* pScreen */, + ClientPtr /* client */ +); + +/* + * when a client sets the screen saver attributes, a resource is + * kept to be freed when the client exits + */ + +static RESTYPE AttrType; /* resource type for attributes */ + +typedef struct _ScreenSaverAttr { + ScreenPtr screen; + ClientPtr client; + XID resource; + short x, y; + unsigned short width, height, borderWidth; + unsigned char class; + unsigned char depth; + VisualID visual; + CursorPtr pCursor; + PixmapPtr pBackgroundPixmap; + PixmapPtr pBorderPixmap; + Colormap colormap; + unsigned long mask; /* no pixmaps or cursors */ + unsigned long *values; +} ScreenSaverAttrRec, *ScreenSaverAttrPtr; + +static int ScreenSaverFreeAttr ( + pointer /* value */, + XID /* id */ +); + +static void FreeAttrs ( + ScreenSaverAttrPtr /* pAttr */ +); + +static void FreeScreenAttr ( + ScreenSaverAttrPtr /* pAttr */ +); + +static void +SendScreenSaverNotify ( + ScreenPtr /* pScreen */, + int /* state */, + Bool /* forced */ +); + +typedef struct _ScreenSaverScreenPrivate { + ScreenSaverEventPtr events; + ScreenSaverAttrPtr attr; + Bool hasWindow; + Colormap installedMap; +} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr; + +static ScreenSaverScreenPrivatePtr +MakeScreenPrivate ( + ScreenPtr /* pScreen */ + ); + +static int ScreenPrivateIndex; + +#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr)(s)->devPrivates[ScreenPrivateIndex].ptr) +#define SetScreenPrivate(s,v) ((s)->devPrivates[ScreenPrivateIndex].ptr = (pointer) v); +#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL) + +#define New(t) ((t *) xalloc (sizeof (t))) + +/**************** + * ScreenSaverExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ + +void +ScreenSaverExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + ScreenPtr pScreen; + + AttrType = CreateNewResourceType(ScreenSaverFreeAttr); + EventType = CreateNewResourceType(ScreenSaverFreeEvents); + ScreenPrivateIndex = AllocateScreenPrivateIndex (); + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + SetScreenPrivate (pScreen, NULL); + } + if (AttrType && EventType && ScreenPrivateIndex != -1 && + (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0, + ProcScreenSaverDispatch, SProcScreenSaverDispatch, + ScreenSaverResetProc, StandardMinorOpcode))) + { +#if 0 + ScreenSaverReqCode = (unsigned char)extEntry->base; +#endif + ScreenSaverEventBase = extEntry->eventBase; + EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent; + } +} + +/*ARGSUSED*/ +static void +ScreenSaverResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static void +CheckScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (!pPriv) + return; + if (!pPriv->attr && !pPriv->events && + !pPriv->hasWindow && pPriv->installedMap == None) + { + xfree (pPriv); + SetScreenPrivate (pScreen, NULL); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + } +} + +static ScreenSaverScreenPrivatePtr +MakeScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (pPriv) + return pPriv; + pPriv = New (ScreenSaverScreenPrivateRec); + if (!pPriv) + return 0; + pPriv->events = 0; + pPriv->attr = 0; + pPriv->hasWindow = FALSE; + pPriv->installedMap = None; + SetScreenPrivate (pScreen, pPriv); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = ScreenSaverHandle; + return pPriv; +} + +static unsigned long +getEventMask (pScreen, client) + ScreenPtr pScreen; + ClientPtr client; +{ + SetupScreen(pScreen); + ScreenSaverEventPtr pEv; + + if (!pPriv) + return 0; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + if (pEv->client == client) + return pEv->mask; + return 0; +} + +static Bool +setEventMask (pScreen, client, mask) + ScreenPtr pScreen; + ClientPtr client; + unsigned long mask; +{ + SetupScreen(pScreen); + ScreenSaverEventPtr pEv, *pPrev; + + if (getEventMask (pScreen, client) == mask) + return TRUE; + if (!pPriv) + { + pPriv = MakeScreenPrivate (pScreen); + if (!pPriv) + return FALSE; + } + for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) + if (pEv->client == client) + break; + if (mask == 0) + { + FreeResource (pEv->resource, EventType); + *pPrev = pEv->next; + xfree (pEv); + CheckScreenPrivate (pScreen); + } + else + { + if (!pEv) + { + pEv = New (ScreenSaverEventRec); + if (!pEv) + { + CheckScreenPrivate (pScreen); + return FALSE; + } + *pPrev = pEv; + pEv->next = NULL; + pEv->client = client; + pEv->screen = pScreen; + pEv->resource = FakeClientID (client->index); + if (!AddResource (pEv->resource, EventType, (pointer) pEv)) + return FALSE; + } + pEv->mask = mask; + } + return TRUE; +} + +static void +FreeAttrs (pAttr) + ScreenSaverAttrPtr pAttr; +{ + PixmapPtr pPixmap; + CursorPtr pCursor; + + if ((pPixmap = pAttr->pBackgroundPixmap) != 0) + (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); + if ((pPixmap = pAttr->pBorderPixmap) != 0) + (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); + if ((pCursor = pAttr->pCursor) != 0) + FreeCursor (pCursor, (Cursor) 0); +} + +static void +FreeScreenAttr (pAttr) + ScreenSaverAttrPtr pAttr; +{ + FreeAttrs (pAttr); + xfree (pAttr->values); + xfree (pAttr); +} + +static int +ScreenSaverFreeEvents (value, id) + pointer value; + XID id; +{ + ScreenSaverEventPtr pOld = (ScreenSaverEventPtr)value; + ScreenPtr pScreen = pOld->screen; + SetupScreen (pScreen); + ScreenSaverEventPtr pEv, *pPrev; + + if (!pPriv) + return TRUE; + for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) + if (pEv == pOld) + break; + if (!pEv) + return TRUE; + *pPrev = pEv->next; + xfree (pEv); + CheckScreenPrivate (pScreen); + return TRUE; +} + +static int +ScreenSaverFreeAttr (value, id) + pointer value; + XID id; +{ + ScreenSaverAttrPtr pOldAttr = (ScreenSaverAttrPtr)value; + ScreenPtr pScreen = pOldAttr->screen; + SetupScreen (pScreen); + + if (!pPriv) + return TRUE; + if (pPriv->attr != pOldAttr) + return TRUE; + FreeScreenAttr (pOldAttr); + pPriv->attr = NULL; + if (pPriv->hasWindow) + { + SaveScreens (SCREEN_SAVER_FORCER, ScreenSaverReset); + SaveScreens (SCREEN_SAVER_FORCER, ScreenSaverActive); + } + CheckScreenPrivate (pScreen); + return TRUE; +} + +static void +SendScreenSaverNotify (pScreen, state, forced) + ScreenPtr pScreen; + int state; + Bool forced; +{ + ScreenSaverScreenPrivatePtr pPriv; + ScreenSaverEventPtr pEv; + unsigned long mask; + xScreenSaverNotifyEvent ev; + ClientPtr client; + int kind; + + UpdateCurrentTimeIf (); + mask = ScreenSaverNotifyMask; + if (state == ScreenSaverCycle) + mask = ScreenSaverCycleMask; + pScreen = screenInfo.screens[pScreen->myNum]; + pPriv = GetScreenPrivate(pScreen); + if (!pPriv) + return; + if (pPriv->attr) + kind = ScreenSaverExternal; + else if (ScreenSaverBlanking != DontPreferBlanking) + kind = ScreenSaverBlanked; + else + kind = ScreenSaverInternal; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + { + client = pEv->client; + if (client->clientGone) + continue; + if (!(pEv->mask & mask)) + continue; + ev.type = ScreenSaverNotify + ScreenSaverEventBase; + ev.state = state; + ev.sequenceNumber = client->sequence; + ev.timestamp = currentTime.milliseconds; + ev.root = WindowTable[pScreen->myNum]->drawable.id; + ev.window = savedScreenInfo[pScreen->myNum].wid; + ev.kind = kind; + ev.forced = forced; + WriteEventsToClient (client, 1, (xEvent *) &ev); + } +} + +static void +SScreenSaverNotifyEvent (from, to) + xScreenSaverNotifyEvent *from, *to; +{ + to->type = from->type; + to->state = from->state; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->timestamp, to->timestamp); + cpswapl (from->root, to->root); + cpswapl (from->window, to->window); + to->kind = from->kind; + to->forced = from->forced; +} + +static void +UninstallSaverColormap (pScreen) + ScreenPtr pScreen; +{ + SetupScreen(pScreen); + ColormapPtr pCmap; + + if (pPriv && pPriv->installedMap != None) + { + pCmap = (ColormapPtr) LookupIDByType (pPriv->installedMap, RT_COLORMAP); + if (pCmap) + (*pCmap->pScreen->UninstallColormap) (pCmap); + pPriv->installedMap = None; + CheckScreenPrivate (pScreen); + } +} + +static Bool +CreateSaverWindow (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + ScreenSaverStuffPtr pSaver; + ScreenSaverAttrPtr pAttr; + WindowPtr pWin; + int result; + unsigned long mask; + Colormap *installedMaps; + int numInstalled; + int i; + Colormap wantMap; + ColormapPtr pCmap; + + pSaver = &savedScreenInfo[pScreen->myNum]; + if (pSaver->pWindow) + { + pSaver->pWindow = NullWindow; + FreeResource (pSaver->wid, RT_NONE); + if (pPriv) + { + UninstallSaverColormap (pScreen); + pPriv->hasWindow = FALSE; + CheckScreenPrivate (pScreen); + } + } + + if (!pPriv || !(pAttr = pPriv->attr)) + return FALSE; + + pPriv->installedMap = None; + + if (GrabInProgress && GrabInProgress != pAttr->client->index) + return FALSE; + + pWin = CreateWindow (pSaver->wid, WindowTable[pScreen->myNum], + pAttr->x, pAttr->y, pAttr->width, pAttr->height, + pAttr->borderWidth, pAttr->class, + pAttr->mask, (XID *)pAttr->values, + pAttr->depth, serverClient, pAttr->visual, + &result); + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin)) + return FALSE; + + mask = 0; + if (pAttr->pBackgroundPixmap) + { + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pAttr->pBackgroundPixmap; + pAttr->pBackgroundPixmap->refcnt++; + mask |= CWBackPixmap; + } + if (pAttr->pBorderPixmap) + { + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pAttr->pBorderPixmap; + pAttr->pBorderPixmap->refcnt++; + mask |= CWBorderPixmap; + } + if (pAttr->pCursor) + { + if (!pWin->optional) + if (!MakeWindowOptional (pWin)) + { + FreeResource (pWin->drawable.id, RT_NONE); + return FALSE; + } + if (pWin->optional->cursor) + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->optional->cursor = pAttr->pCursor; + pAttr->pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + CheckWindowOptionalNeed (pWin); + mask |= CWCursor; + } + if (mask) + (*pScreen->ChangeWindowAttributes) (pWin, mask); + + if (pAttr->colormap != None) + (void) ChangeWindowAttributes (pWin, CWColormap, &pAttr->colormap, + serverClient); + + MapWindow (pWin, serverClient); + + pPriv->hasWindow = TRUE; + pSaver->pWindow = pWin; + + /* check and install our own colormap if it isn't installed now */ + wantMap = wColormap (pWin); + if (wantMap == None) + return TRUE; + installedMaps = (Colormap *) ALLOCATE_LOCAL (pScreen->maxInstalledCmaps * + sizeof (Colormap)); + numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pScreen, installedMaps); + for (i = 0; i < numInstalled; i++) + if (installedMaps[i] == wantMap) + break; + + DEALLOCATE_LOCAL ((char *) installedMaps); + + if (i < numInstalled) + return TRUE; + + pCmap = (ColormapPtr) LookupIDByType (wantMap, RT_COLORMAP); + if (!pCmap) + return TRUE; + + pPriv->installedMap = wantMap; + + (*pCmap->pScreen->InstallColormap) (pCmap); + + return TRUE; +} + +static Bool +DestroySaverWindow (pScreen) + ScreenPtr pScreen; +{ + SetupScreen(pScreen); + ScreenSaverStuffPtr pSaver; + + if (!pPriv || !pPriv->hasWindow) + return FALSE; + + pSaver = &savedScreenInfo[pScreen->myNum]; + if (pSaver->pWindow) + { + pSaver->pWindow = NullWindow; + FreeResource (pSaver->wid, RT_NONE); + } + pPriv->hasWindow = FALSE; + CheckScreenPrivate (pScreen); + UninstallSaverColormap (pScreen); + return TRUE; +} + +static Bool +ScreenSaverHandle (pScreen, xstate, force) + ScreenPtr pScreen; + int xstate; + Bool force; +{ + int state = 0; + Bool ret = FALSE; + ScreenSaverScreenPrivatePtr pPriv; + + switch (xstate) + { + case SCREEN_SAVER_ON: + state = ScreenSaverOn; + ret = CreateSaverWindow (pScreen); + break; + case SCREEN_SAVER_OFF: + state = ScreenSaverOff; + ret = DestroySaverWindow (pScreen); + break; + case SCREEN_SAVER_CYCLE: + state = ScreenSaverCycle; + pPriv = GetScreenPrivate (pScreen); + if (pPriv && pPriv->hasWindow) + ret = TRUE; + + } +#ifdef PANORAMIX + if(noPanoramiXExtension || !pScreen->myNum) +#endif + SendScreenSaverNotify (pScreen, state, force); + return ret; +} + +static int +ProcScreenSaverQueryVersion (client) + register ClientPtr client; +{ + xScreenSaverQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = ScreenSaverMajorVersion; + rep.minorVersion = ScreenSaverMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +int +ProcScreenSaverQueryInfo (client) + register ClientPtr client; +{ + REQUEST(xScreenSaverQueryInfoReq); + xScreenSaverQueryInfoReply rep; + register int n; + ScreenSaverStuffPtr pSaver; + DrawablePtr pDraw; + CARD32 lastInput; + ScreenSaverScreenPrivatePtr pPriv; + + REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq); + pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client); + if (!pDraw) + return BadDrawable; + + pSaver = &savedScreenInfo[pDraw->pScreen->myNum]; + pPriv = GetScreenPrivate (pDraw->pScreen); + + UpdateCurrentTime (); + lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.window = pSaver->wid; + if (screenIsSaved != SCREEN_SAVER_OFF) + { + rep.state = ScreenSaverOn; + if (ScreenSaverTime) + rep.tilOrSince = lastInput - ScreenSaverTime; + else + rep.tilOrSince = 0; + } + else + { + if (ScreenSaverTime) + { + rep.state = ScreenSaverOff; + if (ScreenSaverTime < lastInput) + rep.tilOrSince = 0; + else + rep.tilOrSince = ScreenSaverTime - lastInput; + } + else + { + rep.state = ScreenSaverDisabled; + rep.tilOrSince = 0; + } + } + rep.idle = lastInput; + rep.eventMask = getEventMask (pDraw->pScreen, client); + if (pPriv && pPriv->attr) + rep.kind = ScreenSaverExternal; + else if (ScreenSaverBlanking != DontPreferBlanking) + rep.kind = ScreenSaverBlanked; + else + rep.kind = ScreenSaverInternal; + if (client->swapped) + { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.window, n); + swapl (&rep.tilOrSince, n); + swapl (&rep.idle, n); + swapl (&rep.eventMask, n); + } + WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcScreenSaverSelectInput (client) + register ClientPtr client; +{ + REQUEST(xScreenSaverSelectInputReq); + DrawablePtr pDraw; + + REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq); + pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client); + if (!pDraw) + return BadDrawable; + if (!setEventMask (pDraw->pScreen, client, stuff->eventMask)) + return BadAlloc; + return Success; +} + +static int +ScreenSaverSetAttributes (ClientPtr client) +{ + REQUEST(xScreenSaverSetAttributesReq); + DrawablePtr pDraw; + WindowPtr pParent; + ScreenPtr pScreen; + ScreenSaverScreenPrivatePtr pPriv = 0; + ScreenSaverAttrPtr pAttr = 0; + int ret; + int len; + int class, bw, depth; + unsigned long visual; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + WindowOptPtr ancwopt; + unsigned int *pVlist; + unsigned long *values = 0; + unsigned long tmask, imask; + unsigned long val; + Pixmap pixID; + PixmapPtr pPixmap; + Cursor cursorID; + CursorPtr pCursor; + Colormap cmap; + ColormapPtr pCmap; + + REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq); + pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client); + if (!pDraw) + return BadDrawable; + pScreen = pDraw->pScreen; + pParent = WindowTable[pScreen->myNum]; + + len = stuff->length - (sizeof(xScreenSaverSetAttributesReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + switch (class = stuff->c_class) + { + case CopyFromParent: + case InputOnly: + case InputOutput: + break; + default: + client->errorValue = class; + return BadValue; + } + bw = stuff->borderWidth; + depth = stuff->depth; + visual = stuff->visualID; + + /* copied directly from CreateWindow */ + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + client->errorValue = class; + return BadValue; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + return BadMatch; + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + return BadMatch; + + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) + visual = ancwopt->visual; + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + return BadMatch; + } + + if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + return BadMatch; + } + + if (((stuff->mask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + return BadMatch; + } + + /* end of errors from CreateWindow */ + + pPriv = GetScreenPrivate (pScreen); + if (pPriv && pPriv->attr) + { + if (pPriv->attr->client != client) + return BadAccess; + } + if (!pPriv) + { + pPriv = MakeScreenPrivate (pScreen); + if (!pPriv) + return FALSE; + } + pAttr = New (ScreenSaverAttrRec); + if (!pAttr) + { + ret = BadAlloc; + goto bail; + } + /* over allocate for override redirect */ + values = (unsigned long *) xalloc ((len + 1) * sizeof (unsigned long)); + if (!values) + { + ret = BadAlloc; + goto bail; + } + pAttr->screen = pScreen; + pAttr->client = client; + pAttr->x = stuff->x; + pAttr->y = stuff->y; + pAttr->width = stuff->width; + pAttr->height = stuff->height; + pAttr->borderWidth = stuff->borderWidth; + pAttr->class = stuff->c_class; + pAttr->depth = depth; + pAttr->visual = visual; + pAttr->colormap = None; + pAttr->pCursor = NullCursor; + pAttr->pBackgroundPixmap = NullPixmap; + pAttr->pBorderPixmap = NullPixmap; + pAttr->values = values; + /* + * go through the mask, checking the values, + * looking up pixmaps and cursors and hold a reference + * to them. + */ + pAttr->mask = tmask = stuff->mask | CWOverrideRedirect; + pVlist = (unsigned int *) (stuff + 1); + while (tmask) { + imask = lowbit (tmask); + tmask &= ~imask; + switch (imask) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + if (pixID == None) + { + *values++ = None; + } + else if (pixID == ParentRelative) + { + if (depth != pParent->drawable.depth) + { + ret = BadMatch; + goto PatchUp; + } + *values++ = ParentRelative; + } + else + { + pPixmap = (PixmapPtr)LookupIDByType(pixID, RT_PIXMAP); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + ret = BadMatch; + goto PatchUp; + } + pAttr->pBackgroundPixmap = pPixmap; + pPixmap->refcnt++; + pAttr->mask &= ~CWBackPixmap; + } + else + { + ret = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + *values++ = (CARD32) *pVlist; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + if (pixID == CopyFromParent) + { + if (depth != pParent->drawable.depth) + { + ret = BadMatch; + goto PatchUp; + } + *values++ = CopyFromParent; + } + else + { + pPixmap = (PixmapPtr)LookupIDByType(pixID, RT_PIXMAP); + if (pPixmap) + { + if ((pPixmap->drawable.depth != depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + ret = BadMatch; + goto PatchUp; + } + pAttr->pBorderPixmap = pPixmap; + pPixmap->refcnt++; + pAttr->mask &= ~CWBorderPixmap; + } + else + { + ret = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + *values++ = (CARD32) *pVlist; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + if (val > StaticGravity) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + if (val > StaticGravity) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWBackingPlanes: + *values++ = (CARD32) *pVlist; + break; + case CWBackingPixel: + *values++ = (CARD32) *pVlist; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + if ((val != xTrue) && (val != xFalse)) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWEventMask: + *values++ = (CARD32) *pVlist; + break; + case CWDontPropagate: + *values++ = (CARD32) *pVlist; + break; + case CWOverrideRedirect: + if (!(stuff->mask & CWOverrideRedirect)) + pVlist--; + else + { + val = (BOOL ) *pVlist; + if ((val != xTrue) && (val != xFalse)) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + } + *values++ = xTrue; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pCmap = (ColormapPtr)LookupIDByType(cmap, RT_COLORMAP); + if (!pCmap) + { + ret = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen) + { + ret = BadMatch; + goto PatchUp; + } + pAttr->colormap = cmap; + pAttr->mask &= ~CWColormap; + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + if ( cursorID == None) + { + *values++ = None; + } + else + { + pCursor = (CursorPtr)LookupIDByType(cursorID, RT_CURSOR); + if (!pCursor) + { + ret = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + pCursor->refcnt++; + pAttr->pCursor = pCursor; + pAttr->mask &= ~CWCursor; + } + break; + default: + ret = BadValue; + client->errorValue = stuff->mask; + goto PatchUp; + } + pVlist++; + } + if (pPriv->attr) + FreeScreenAttr (pPriv->attr); + pPriv->attr = pAttr; + pAttr->resource = FakeClientID (client->index); + if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr)) + return BadAlloc; + return Success; +PatchUp: + FreeAttrs (pAttr); +bail: + CheckScreenPrivate (pScreen); + if (pAttr) xfree (pAttr->values); + xfree (pAttr); + return ret; +} + +static int +ScreenSaverUnsetAttributes (ClientPtr client) +{ + REQUEST(xScreenSaverSetAttributesReq); + DrawablePtr pDraw; + ScreenSaverScreenPrivatePtr pPriv; + + REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq); + pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client); + if (!pDraw) + return BadDrawable; + pPriv = GetScreenPrivate (pDraw->pScreen); + if (pPriv && pPriv->attr && pPriv->attr->client == client) + { + FreeResource (pPriv->attr->resource, AttrType); + FreeScreenAttr (pPriv->attr); + pPriv->attr = NULL; + CheckScreenPrivate (pDraw->pScreen); + } + return Success; +} + +static int +ProcScreenSaverSetAttributes (ClientPtr client) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + REQUEST(xScreenSaverSetAttributesReq); + PanoramiXRes *draw; + PanoramiXRes *backPix = NULL; + PanoramiXRes *bordPix = NULL; + PanoramiXRes *cmap = NULL; + int i, status = 0, len; + int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; + XID orig_visual, tmp; + + REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + len = stuff->length - (sizeof(xScreenSaverSetAttributesReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + if((Mask)stuff->mask & CWBackPixmap) { + pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pback_offset); + if ((tmp != None) && (tmp != ParentRelative)) { + if(!(backPix = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + + if ((Mask)stuff->mask & CWBorderPixmap) { + pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pbord_offset); + if (tmp != CopyFromParent) { + if(!(bordPix = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } + } + + if ((Mask)stuff->mask & CWColormap) { + cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); + tmp = *((CARD32 *) &stuff[1] + cmap_offset); + if ((tmp != CopyFromParent) && (tmp != None)) { + if(!(cmap = (PanoramiXRes*) SecurityLookupIDByType( + client, tmp, XRT_COLORMAP, SecurityReadAccess))) + return BadColor; + } + } + + orig_visual = stuff->visualID; + + FOR_NSCREENS_BACKWARD(i) { + stuff->drawable = draw->info[i].id; + if (backPix) + *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id; + if (bordPix) + *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id; + if (cmap) + *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id; + + if (orig_visual != CopyFromParent) + stuff->visualID = + PanoramiXVisualTable[(orig_visual*MAXSCREENS) + i]; + + status = ScreenSaverSetAttributes(client); + } + + return status; + } +#endif + + return ScreenSaverSetAttributes(client); +} + +static int +ProcScreenSaverUnsetAttributes (ClientPtr client) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + REQUEST(xScreenSaverUnsetAttributesReq); + PanoramiXRes *draw; + int i; + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + for(i = PanoramiXNumScreens - 1; i > 0; i--) { + stuff->drawable = draw->info[i].id; + ScreenSaverUnsetAttributes(client); + } + + stuff->drawable = draw->info[0].id; + } +#endif + + return ScreenSaverUnsetAttributes(client); +} + +static DISPATCH_PROC((*NormalVector[])) = { + ProcScreenSaverQueryVersion, + ProcScreenSaverQueryInfo, + ProcScreenSaverSelectInput, + ProcScreenSaverSetAttributes, + ProcScreenSaverUnsetAttributes, +}; + +#define NUM_REQUESTS ((sizeof NormalVector) / (sizeof NormalVector[0])) + +static int +ProcScreenSaverDispatch (client) + ClientPtr client; +{ + REQUEST(xReq); + + if (stuff->data < NUM_REQUESTS) + return (*NormalVector[stuff->data])(client); + return BadRequest; +} + +static int +SProcScreenSaverQueryVersion (client) + ClientPtr client; +{ + REQUEST(xScreenSaverQueryVersionReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq); + return ProcScreenSaverQueryVersion (client); +} + +static int +SProcScreenSaverQueryInfo (client) + ClientPtr client; +{ + REQUEST(xScreenSaverQueryInfoReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq); + swapl (&stuff->drawable, n); + return ProcScreenSaverQueryInfo (client); +} + +static int +SProcScreenSaverSelectInput (client) + ClientPtr client; +{ + REQUEST(xScreenSaverSelectInputReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq); + swapl (&stuff->drawable, n); + swapl (&stuff->eventMask, n); + return ProcScreenSaverSelectInput (client); +} + +static int +SProcScreenSaverSetAttributes (client) + ClientPtr client; +{ + REQUEST(xScreenSaverSetAttributesReq); + int n; + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq); + swapl (&stuff->drawable, n); + swaps (&stuff->x, n); + swaps (&stuff->y, n); + swaps (&stuff->width, n); + swaps (&stuff->height, n); + swaps (&stuff->borderWidth, n); + swapl (&stuff->visualID, n); + swapl (&stuff->mask, n); + SwapRestL(stuff); + return ProcScreenSaverSetAttributes (client); +} + +static int +SProcScreenSaverUnsetAttributes (client) + ClientPtr client; +{ + REQUEST(xScreenSaverUnsetAttributesReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq); + swapl (&stuff->drawable, n); + return ProcScreenSaverUnsetAttributes (client); +} + +static DISPATCH_PROC((*SwappedVector[])) = { + SProcScreenSaverQueryVersion, + SProcScreenSaverQueryInfo, + SProcScreenSaverSelectInput, + SProcScreenSaverSetAttributes, + SProcScreenSaverUnsetAttributes, +}; + +static int +SProcScreenSaverDispatch (client) + ClientPtr client; +{ + REQUEST(xReq); + + if (stuff->data < NUM_REQUESTS) + return (*SwappedVector[stuff->data])(client); + return BadRequest; +} diff --git a/nx-X11/programs/Xserver/Xext/security.c b/nx-X11/programs/Xserver/Xext/security.c new file mode 100644 index 000000000..2139425b4 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/security.c @@ -0,0 +1,2245 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/security.c,v 1.5 2005/07/03 07:01:04 daniels Exp $ */ +/* $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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/security.c,v 1.16tsi Exp $ */ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NX-X11, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "propertyst.h" +#define _SECURITY_SERVER +#include <X11/extensions/securstr.h> +#include <assert.h> +#include <stdarg.h> +#ifdef LBX +#define _XLBX_SERVER_ +#include <X11/extensions/XLbx.h> +extern unsigned char LbxReqCode; +#endif +#ifdef XAPPGROUP +#include <X11/extensions/Xagsrv.h> +#endif +#include <stdio.h> /* for file reading operations */ +#include <X11/Xatom.h> /* for XA_STRING */ + +#ifdef NXAGENT_SERVER + +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> + +#endif + +#ifndef DEFAULTPOLICYFILE +# define DEFAULTPOLICYFILE NULL +#endif + +#ifdef NXAGENT_SERVER + +#define NX_ALTERNATIVEPOLICYFILE "/usr/lib/xserver/SecurityPolicy" + +#endif + +#if defined(WIN32) || defined(__CYGWIN__) +#include <X11/Xos.h> +#undef index +#endif + +/* + * Set here the required NX log level. + */ + +#ifdef NXAGENT_SERVER + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#endif + +#ifdef NXAGENT_SERVER + +static char _NXPolicyFilePath[1024]; + +#endif + +#include "modinit.h" + +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])( + ClientPtr /*client*/ +); +int (*SwappedUntrustedProcVector[256])( + ClientPtr /*client*/ +); + +#ifdef NXAGENT_SERVER + +/* + * This function returns the SecurityPolicy + * file full path. This path is referred by + * SecurityPolicyFile variable (generally it + * contains the hardcoded path at compile time). + * If the path does not exist, the function will + * try a set of well known paths. + */ + +const char *_NXGetPolicyFilePath(const char *path) +{ + + struct stat SecurityPolicyStat; + + /* + * Check the policy file path only once. + */ + + if (*_NXPolicyFilePath != '\0') + { + return _NXPolicyFilePath; + } + + if (stat(path, &SecurityPolicyStat) == 0) + { + if (strlen(path) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n"); + #endif + + goto _NXGetPolicyFilePathError; + } + + strcpy(_NXPolicyFilePath, path); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; + } + + if (stat(DEFAULTPOLICYFILE, &SecurityPolicyStat) == 0) + { + if (strlen(DEFAULTPOLICYFILE) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n"); + #endif + + goto _NXGetPolicyFilePathError; + } + + strcpy(_NXPolicyFilePath, DEFAULTPOLICYFILE); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; + } + + if (stat(NX_ALTERNATIVEPOLICYFILE, &SecurityPolicyStat) == 0) + { + if (strlen(NX_ALTERNATIVEPOLICYFILE) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n"); + #endif + + goto _NXGetPolicyFilePathError; + } + + strcpy(_NXPolicyFilePath, NX_ALTERNATIVEPOLICYFILE); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; + } + +_NXGetPolicyFilePathError: + + if (strlen(path) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file exceeded.\n"); + #endif + } + + strcpy(_NXPolicyFilePath, path); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using default SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; +} + +#endif + +/* 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; + va_start(args, format); + VAuditF(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( + 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); + (void)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( + 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( + 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( + 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( + 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( + 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( + 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( + 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 */ + 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( + 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( + 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( + 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( + ClientPtr client) +{ + REQUEST(xSecurityGenerateAuthorizationReq); + register char n; + CARD32 *values; + unsigned long nvalues; + int values_offset; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + swaps(&stuff->nbytesAuthProto, n); + swaps(&stuff->nbytesAuthData, n); + swapl(&stuff->valueMask, n); + values_offset = ((stuff->nbytesAuthProto + (unsigned)3) >> 2) + + ((stuff->nbytesAuthData + (unsigned)3) >> 2); + if (values_offset > + stuff->length - (sz_xSecurityGenerateAuthorizationReq >> 2)) + return BadLength; + values = (CARD32 *)(&stuff[1]) + values_offset; + nvalues = (((CARD32 *)stuff) + stuff->length) - values; + SwapLongs(values, nvalues); + return ProcSecurityGenerateAuthorization(client); +} /* SProcSecurityGenerateAuthorization */ + + +static int +SProcSecurityRevokeAuthorization( + 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( + 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( + xSecurityAuthorizationRevokedEvent *from, + xSecurityAuthorizationRevokedEvent *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( + 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 = 0; + + /* 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( + 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( + 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( + 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; +{ + ScreenPtr pScreen = pDraw->pScreen; + 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_NULL(pScreen, &censorRegion); + + /* 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(void) +{ + while (PropertyAccessList) + { + PropertyAccessPtr freeit = PropertyAccessList; + PropertyAccessList = PropertyAccessList->next; + xfree(freeit); + } +} /* SecurityFreePropertyAccessList */ + +#ifndef __UNIXOS2__ +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') ) +#else +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') ) +#endif + +static char * +SecuritySkipWhitespace( + char *p) +{ + while (SecurityIsWhitespace(*p)) + p++; + return p; +} /* SecuritySkipWhitespace */ + + +static char * +SecurityParseString( + 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( + 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( + char *p) +{ + char *propname; + char c; + char action = SecurityDefaultAction; + char readAction, writeAction, destroyAction; + PropertyAccessPtr pacl, prev, cur; + 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( + 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(void) +{ + if (SecurityPolicyStrings) + { + assert(nSecurityPolicyStrings); + while (nSecurityPolicyStrings--) + { + Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]); + } + Xfree(SecurityPolicyStrings); + SecurityPolicyStrings = NULL; + nSecurityPolicyStrings = 0; + } +} /* SecurityFreeSitePolicyStrings */ + + +static void +SecurityLoadPropertyAccessList(void) +{ + FILE *f; + int lineNumber = 0; + + SecurityMaxPropertyName = 0; + +#ifdef NXAGENT_SERVER + + if (!_NXGetPolicyFilePath(SecurityPolicyFile)) + { + return; + } + +#else + + if (!SecurityPolicyFile) + return; + +#endif + +#ifndef __UNIXOS2__ + +#ifdef NXAGENT_SERVER + + f = Fopen(_NXGetPolicyFilePath(SecurityPolicyFile), "r"); + +#else + + f = Fopen(SecurityPolicyFile, "r"); + +#endif + +#else + +#ifdef NXAGENT_SERVER + + f = Fopen((char*)__XOS2RedirRoot( _NXGetPolicyFilePath(SecurityPolicyFile)), "r"); + +#else + + f = Fopen((char*)__XOS2RedirRoot(SecurityPolicyFile), "r"); + +#endif + +#endif + + if (!f) + { +#ifdef NXAGENT_SERVER + + ErrorF("error opening security policy file %s\n", + _NXGetPolicyFilePath(SecurityPolicyFile)); + +#else + + ErrorF("error opening security policy file %s\n", + SecurityPolicyFile); + +#endif + + 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) + { + +#ifdef NXAGENT_SERVER + + ErrorF("%s: invalid security policy file version, ignoring file\n", + _NXGetPolicyFilePath(SecurityPolicyFile)); + +#else + + ErrorF("%s: invalid security policy file version, ignoring file\n", + SecurityPolicyFile); + +#endif + + 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; + } + } + +#ifdef NXAGENT_SERVER + + if (!validLine) + { + ErrorF("Line %d of %s invalid, ignoring\n", + lineNumber, _NXGetPolicyFilePath(SecurityPolicyFile)); + } + +#else + + if (!validLine) + ErrorF("Line %d of %s invalid, ignoring\n", + lineNumber, SecurityPolicyFile); + +#endif + + } /* 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( + 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; + +#ifdef NXAGENT_SERVER + + int ret = stat(_NXGetPolicyFilePath(SecurityPolicyFile), &buf); + +#else + + int ret = stat(SecurityPolicyFile , &buf); + +#endif + + 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( + 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(INITARGS) +{ + 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] = + (EventSwapPtr)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/nx-X11/programs/Xserver/Xext/security.c.NX.original b/nx-X11/programs/Xserver/Xext/security.c.NX.original new file mode 100644 index 000000000..2139425b4 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/security.c.NX.original @@ -0,0 +1,2245 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/security.c,v 1.5 2005/07/03 07:01:04 daniels Exp $ */ +/* $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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/security.c,v 1.16tsi Exp $ */ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NX-X11, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "propertyst.h" +#define _SECURITY_SERVER +#include <X11/extensions/securstr.h> +#include <assert.h> +#include <stdarg.h> +#ifdef LBX +#define _XLBX_SERVER_ +#include <X11/extensions/XLbx.h> +extern unsigned char LbxReqCode; +#endif +#ifdef XAPPGROUP +#include <X11/extensions/Xagsrv.h> +#endif +#include <stdio.h> /* for file reading operations */ +#include <X11/Xatom.h> /* for XA_STRING */ + +#ifdef NXAGENT_SERVER + +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> + +#endif + +#ifndef DEFAULTPOLICYFILE +# define DEFAULTPOLICYFILE NULL +#endif + +#ifdef NXAGENT_SERVER + +#define NX_ALTERNATIVEPOLICYFILE "/usr/lib/xserver/SecurityPolicy" + +#endif + +#if defined(WIN32) || defined(__CYGWIN__) +#include <X11/Xos.h> +#undef index +#endif + +/* + * Set here the required NX log level. + */ + +#ifdef NXAGENT_SERVER + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#endif + +#ifdef NXAGENT_SERVER + +static char _NXPolicyFilePath[1024]; + +#endif + +#include "modinit.h" + +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])( + ClientPtr /*client*/ +); +int (*SwappedUntrustedProcVector[256])( + ClientPtr /*client*/ +); + +#ifdef NXAGENT_SERVER + +/* + * This function returns the SecurityPolicy + * file full path. This path is referred by + * SecurityPolicyFile variable (generally it + * contains the hardcoded path at compile time). + * If the path does not exist, the function will + * try a set of well known paths. + */ + +const char *_NXGetPolicyFilePath(const char *path) +{ + + struct stat SecurityPolicyStat; + + /* + * Check the policy file path only once. + */ + + if (*_NXPolicyFilePath != '\0') + { + return _NXPolicyFilePath; + } + + if (stat(path, &SecurityPolicyStat) == 0) + { + if (strlen(path) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n"); + #endif + + goto _NXGetPolicyFilePathError; + } + + strcpy(_NXPolicyFilePath, path); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; + } + + if (stat(DEFAULTPOLICYFILE, &SecurityPolicyStat) == 0) + { + if (strlen(DEFAULTPOLICYFILE) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n"); + #endif + + goto _NXGetPolicyFilePathError; + } + + strcpy(_NXPolicyFilePath, DEFAULTPOLICYFILE); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; + } + + if (stat(NX_ALTERNATIVEPOLICYFILE, &SecurityPolicyStat) == 0) + { + if (strlen(NX_ALTERNATIVEPOLICYFILE) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n"); + #endif + + goto _NXGetPolicyFilePathError; + } + + strcpy(_NXPolicyFilePath, NX_ALTERNATIVEPOLICYFILE); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; + } + +_NXGetPolicyFilePathError: + + if (strlen(path) + 1 > 1024) + { + #ifdef WARNING + fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file exceeded.\n"); + #endif + } + + strcpy(_NXPolicyFilePath, path); + + #ifdef TEST + fprintf(stderr, "_NXGetPolicyFilePath: Using default SecurityPolicy file path [%s].\n", + _NXPolicyFilePath); + #endif + + return _NXPolicyFilePath; +} + +#endif + +/* 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; + va_start(args, format); + VAuditF(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( + 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); + (void)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( + 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( + 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( + 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( + 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( + 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( + 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( + 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 */ + 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( + 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( + 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( + 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( + ClientPtr client) +{ + REQUEST(xSecurityGenerateAuthorizationReq); + register char n; + CARD32 *values; + unsigned long nvalues; + int values_offset; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + swaps(&stuff->nbytesAuthProto, n); + swaps(&stuff->nbytesAuthData, n); + swapl(&stuff->valueMask, n); + values_offset = ((stuff->nbytesAuthProto + (unsigned)3) >> 2) + + ((stuff->nbytesAuthData + (unsigned)3) >> 2); + if (values_offset > + stuff->length - (sz_xSecurityGenerateAuthorizationReq >> 2)) + return BadLength; + values = (CARD32 *)(&stuff[1]) + values_offset; + nvalues = (((CARD32 *)stuff) + stuff->length) - values; + SwapLongs(values, nvalues); + return ProcSecurityGenerateAuthorization(client); +} /* SProcSecurityGenerateAuthorization */ + + +static int +SProcSecurityRevokeAuthorization( + 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( + 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( + xSecurityAuthorizationRevokedEvent *from, + xSecurityAuthorizationRevokedEvent *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( + 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 = 0; + + /* 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( + 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( + 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( + 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; +{ + ScreenPtr pScreen = pDraw->pScreen; + 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_NULL(pScreen, &censorRegion); + + /* 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(void) +{ + while (PropertyAccessList) + { + PropertyAccessPtr freeit = PropertyAccessList; + PropertyAccessList = PropertyAccessList->next; + xfree(freeit); + } +} /* SecurityFreePropertyAccessList */ + +#ifndef __UNIXOS2__ +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') ) +#else +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') ) +#endif + +static char * +SecuritySkipWhitespace( + char *p) +{ + while (SecurityIsWhitespace(*p)) + p++; + return p; +} /* SecuritySkipWhitespace */ + + +static char * +SecurityParseString( + 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( + 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( + char *p) +{ + char *propname; + char c; + char action = SecurityDefaultAction; + char readAction, writeAction, destroyAction; + PropertyAccessPtr pacl, prev, cur; + 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( + 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(void) +{ + if (SecurityPolicyStrings) + { + assert(nSecurityPolicyStrings); + while (nSecurityPolicyStrings--) + { + Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]); + } + Xfree(SecurityPolicyStrings); + SecurityPolicyStrings = NULL; + nSecurityPolicyStrings = 0; + } +} /* SecurityFreeSitePolicyStrings */ + + +static void +SecurityLoadPropertyAccessList(void) +{ + FILE *f; + int lineNumber = 0; + + SecurityMaxPropertyName = 0; + +#ifdef NXAGENT_SERVER + + if (!_NXGetPolicyFilePath(SecurityPolicyFile)) + { + return; + } + +#else + + if (!SecurityPolicyFile) + return; + +#endif + +#ifndef __UNIXOS2__ + +#ifdef NXAGENT_SERVER + + f = Fopen(_NXGetPolicyFilePath(SecurityPolicyFile), "r"); + +#else + + f = Fopen(SecurityPolicyFile, "r"); + +#endif + +#else + +#ifdef NXAGENT_SERVER + + f = Fopen((char*)__XOS2RedirRoot( _NXGetPolicyFilePath(SecurityPolicyFile)), "r"); + +#else + + f = Fopen((char*)__XOS2RedirRoot(SecurityPolicyFile), "r"); + +#endif + +#endif + + if (!f) + { +#ifdef NXAGENT_SERVER + + ErrorF("error opening security policy file %s\n", + _NXGetPolicyFilePath(SecurityPolicyFile)); + +#else + + ErrorF("error opening security policy file %s\n", + SecurityPolicyFile); + +#endif + + 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) + { + +#ifdef NXAGENT_SERVER + + ErrorF("%s: invalid security policy file version, ignoring file\n", + _NXGetPolicyFilePath(SecurityPolicyFile)); + +#else + + ErrorF("%s: invalid security policy file version, ignoring file\n", + SecurityPolicyFile); + +#endif + + 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; + } + } + +#ifdef NXAGENT_SERVER + + if (!validLine) + { + ErrorF("Line %d of %s invalid, ignoring\n", + lineNumber, _NXGetPolicyFilePath(SecurityPolicyFile)); + } + +#else + + if (!validLine) + ErrorF("Line %d of %s invalid, ignoring\n", + lineNumber, SecurityPolicyFile); + +#endif + + } /* 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( + 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; + +#ifdef NXAGENT_SERVER + + int ret = stat(_NXGetPolicyFilePath(SecurityPolicyFile), &buf); + +#else + + int ret = stat(SecurityPolicyFile , &buf); + +#endif + + 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( + 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(INITARGS) +{ + 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] = + (EventSwapPtr)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/nx-X11/programs/Xserver/Xext/security.c.X.original b/nx-X11/programs/Xserver/Xext/security.c.X.original new file mode 100644 index 000000000..c6a516733 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/security.c.X.original @@ -0,0 +1,2008 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/security.c,v 1.5 2005/07/03 07:01:04 daniels Exp $ */ +/* $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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/security.c,v 1.16tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "propertyst.h" +#define _SECURITY_SERVER +#include <X11/extensions/securstr.h> +#include <assert.h> +#include <stdarg.h> +#ifdef LBX +#define _XLBX_SERVER_ +#include <X11/extensions/XLbx.h> +extern unsigned char LbxReqCode; +#endif +#ifdef XAPPGROUP +#include <X11/extensions/Xagsrv.h> +#endif +#include <stdio.h> /* for file reading operations */ +#include <X11/Xatom.h> /* for XA_STRING */ + +#ifndef DEFAULTPOLICYFILE +# define DEFAULTPOLICYFILE NULL +#endif +#if defined(WIN32) || defined(__CYGWIN__) +#include <X11/Xos.h> +#undef index +#endif + +#include "modinit.h" + +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])( + ClientPtr /*client*/ +); +int (*SwappedUntrustedProcVector[256])( + ClientPtr /*client*/ +); + +/* 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; + va_start(args, format); + VAuditF(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( + 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); + (void)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( + 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( + 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( + 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( + 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( + 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( + 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( + 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 */ + 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( + 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( + 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( + 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( + ClientPtr client) +{ + REQUEST(xSecurityGenerateAuthorizationReq); + register char n; + CARD32 *values; + unsigned long nvalues; + int values_offset; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + swaps(&stuff->nbytesAuthProto, n); + swaps(&stuff->nbytesAuthData, n); + swapl(&stuff->valueMask, n); + values_offset = ((stuff->nbytesAuthProto + (unsigned)3) >> 2) + + ((stuff->nbytesAuthData + (unsigned)3) >> 2); + if (values_offset > + stuff->length - (sz_xSecurityGenerateAuthorizationReq >> 2)) + return BadLength; + values = (CARD32 *)(&stuff[1]) + values_offset; + nvalues = (((CARD32 *)stuff) + stuff->length) - values; + SwapLongs(values, nvalues); + return ProcSecurityGenerateAuthorization(client); +} /* SProcSecurityGenerateAuthorization */ + + +static int +SProcSecurityRevokeAuthorization( + 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( + 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( + xSecurityAuthorizationRevokedEvent *from, + xSecurityAuthorizationRevokedEvent *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( + 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 = 0; + + /* 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( + 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( + 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( + 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; +{ + ScreenPtr pScreen = pDraw->pScreen; + 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_NULL(pScreen, &censorRegion); + + /* 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(void) +{ + while (PropertyAccessList) + { + PropertyAccessPtr freeit = PropertyAccessList; + PropertyAccessList = PropertyAccessList->next; + xfree(freeit); + } +} /* SecurityFreePropertyAccessList */ + +#ifndef __UNIXOS2__ +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') ) +#else +#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') ) +#endif + +static char * +SecuritySkipWhitespace( + char *p) +{ + while (SecurityIsWhitespace(*p)) + p++; + return p; +} /* SecuritySkipWhitespace */ + + +static char * +SecurityParseString( + 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( + 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( + char *p) +{ + char *propname; + char c; + char action = SecurityDefaultAction; + char readAction, writeAction, destroyAction; + PropertyAccessPtr pacl, prev, cur; + 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( + 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(void) +{ + if (SecurityPolicyStrings) + { + assert(nSecurityPolicyStrings); + while (nSecurityPolicyStrings--) + { + Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]); + } + Xfree(SecurityPolicyStrings); + SecurityPolicyStrings = NULL; + nSecurityPolicyStrings = 0; + } +} /* SecurityFreeSitePolicyStrings */ + + +static void +SecurityLoadPropertyAccessList(void) +{ + FILE *f; + int lineNumber = 0; + + SecurityMaxPropertyName = 0; + + if (!SecurityPolicyFile) + return; + +#ifndef __UNIXOS2__ + f = Fopen(SecurityPolicyFile, "r"); +#else + f = Fopen((char*)__XOS2RedirRoot(SecurityPolicyFile), "r"); +#endif + 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( + 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( + 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(INITARGS) +{ + 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] = + (EventSwapPtr)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/nx-X11/programs/Xserver/Xext/shape.c b/nx-X11/programs/Xserver/Xext/shape.c new file mode 100644 index 000000000..3fa16081a --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/shape.c @@ -0,0 +1,1335 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/shape.c,v 1.9 2005/07/03 08:53:36 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/Xext/shape.c,v 3.18 2003/10/28 23:08:43 tsi Exp $ */ +/************************************************************ + +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 +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/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 <X11/extensions/shapestr.h> +#include "regionstr.h" +#include "gcstruct.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif +#include "modinit.h" + +typedef RegionPtr (*CreateDftPtr)( + WindowPtr /* pWin */ + ); + +static int ShapeFreeClient( + pointer /* data */, + XID /* id */ + ); +static int ShapeFreeEvents( + pointer /* data */, + XID /* id */ + ); +static void ShapeResetProc( + ExtensionEntry * /* extEntry */ + ); +static void SShapeNotifyEvent( + xShapeNotifyEvent * /* from */, + xShapeNotifyEvent * /* to */ + ); +static int +RegionOperate ( + ClientPtr /* client */, + WindowPtr /* pWin */, + int /* kind */, + RegionPtr * /* destRgnp */, + RegionPtr /* srcRgn */, + int /* op */, + int /* xoff */, + int /* yoff */, + CreateDftPtr /* create */ + ); + +/* SendShapeNotify, CreateBoundingShape and CreateClipShape are used + * externally by the Xfixes extension and are now defined in window.h + */ + +static DISPATCH_PROC(ProcShapeCombine); +static DISPATCH_PROC(ProcShapeDispatch); +static DISPATCH_PROC(ProcShapeGetRectangles); +static DISPATCH_PROC(ProcShapeInputSelected); +static DISPATCH_PROC(ProcShapeMask); +static DISPATCH_PROC(ProcShapeOffset); +static DISPATCH_PROC(ProcShapeQueryExtents); +static DISPATCH_PROC(ProcShapeQueryVersion); +static DISPATCH_PROC(ProcShapeRectangles); +static DISPATCH_PROC(ProcShapeSelectInput); +static DISPATCH_PROC(SProcShapeCombine); +static DISPATCH_PROC(SProcShapeDispatch); +static DISPATCH_PROC(SProcShapeGetRectangles); +static DISPATCH_PROC(SProcShapeInputSelected); +static DISPATCH_PROC(SProcShapeMask); +static DISPATCH_PROC(SProcShapeOffset); +static DISPATCH_PROC(SProcShapeQueryExtents); +static DISPATCH_PROC(SProcShapeQueryVersion); +static DISPATCH_PROC(SProcShapeRectangles); +static DISPATCH_PROC(SProcShapeSelectInput); + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#if 0 +static unsigned char ShapeReqCode = 0; +#endif +static int ShapeEventBase = 0; +static RESTYPE ClientType, EventType; /* resource types for event masks */ + +/* + * 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(INITARGS) +{ + ExtensionEntry *extEntry; + + ClientType = CreateNewResourceType(ShapeFreeClient); + EventType = CreateNewResourceType(ShapeFreeEvents); + if (ClientType && EventType && + (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, + ProcShapeDispatch, SProcShapeDispatch, + ShapeResetProc, StandardMinorOpcode))) + { +#if 0 + ShapeReqCode = (unsigned char)extEntry->base; +#endif + ShapeEventBase = extEntry->eventBase; + EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent; + } +} + +/*ARGSUSED*/ +static void +ShapeResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +RegionOperate (client, pWin, kind, destRgnp, srcRgn, op, xoff, yoff, create) + ClientPtr client; + WindowPtr pWin; + int kind; + RegionPtr *destRgnp, srcRgn; + int op; + int xoff, yoff; + CreateDftPtr 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; + } + + /* May/30/2001: + * The shape.PS specs say if src is None, existing shape is to be + * removed (and so the op-code has no meaning in such removal); + * see shape.PS, page 3, ShapeMask. + */ + if (srcRgn == NULL) { + if (*destRgnp != NULL) { + REGION_DESTROY (pScreen, *destRgnp); + *destRgnp = 0; + /* go on to remove shape and generate ShapeNotify */ + } + else { + /* May/30/2001: + * The target currently has no shape in effect, so nothing to + * do here. The specs say that ShapeNotify is generated whenever + * the client region is "modified"; since no modification is done + * here, we do not generate that event. The specs does not say + * "it is an error to request removal when there is no shape in + * effect", so we return good status. + */ + return Success; + } + } + else 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; +} + +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); +} + +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; +{ + 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 + * + *****************/ + +static int +ProcShapeRectangles (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeRectanglesReq); + xRectangle *prects; + int nrects, ctype; + RegionPtr srcRgn; + RegionPtr *destRgn; + CreateDftPtr createDefault; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + UpdateCurrentTime(); + pWin = LookupWindow (stuff->dest, client); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + 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); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeRectangles( + register ClientPtr client) +{ + REQUEST(xShapeRectanglesReq); + PanoramiXRes *win; + int j, result = 0; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->dest, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + result = ProcShapeRectangles (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + + +/************** + * ProcShapeMask + **************/ + + +static int +ProcShapeMask (client) + register ClientPtr client; +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeMaskReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + PixmapPtr pPixmap; + CreateDftPtr createDefault; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + UpdateCurrentTime(); + pWin = SecurityLookupWindow (stuff->dest, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + 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); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeMask( + register ClientPtr client) +{ + REQUEST(xShapeMaskReq); + PanoramiXRes *win, *pmap; + int j, result = 0; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->dest, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + if(stuff->src != None) { + if(!(pmap = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->src, XRT_PIXMAP, SecurityReadAccess))) + return BadPixmap; + } else + pmap = NULL; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + if(pmap) + stuff->src = pmap->info[j].id; + result = ProcShapeMask (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + + +/************ + * ProcShapeCombine + ************/ + +static int +ProcShapeCombine (client) + register ClientPtr client; +{ + WindowPtr pSrcWin, pDestWin; + ScreenPtr pScreen; + REQUEST(xShapeCombineReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + CreateDftPtr createDefault; + CreateDftPtr createSrc; + RegionPtr tmp; + + REQUEST_SIZE_MATCH (xShapeCombineReq); + UpdateCurrentTime(); + pDestWin = LookupWindow (stuff->dest, client); + if (!pDestWin) + return BadWindow; + if (!pDestWin->optional) + MakeWindowOptional (pDestWin); + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + 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; + case ShapeInput: + srcRgn = wInputShape (pSrcWin); + createSrc = CreateBoundingShape; + 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); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pDestWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pDestWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pDestWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate (client, pDestWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeCombine( + register ClientPtr client) +{ + REQUEST(xShapeCombineReq); + PanoramiXRes *win, *win2; + int j, result = 0; + + REQUEST_AT_LEAST_SIZE (xShapeCombineReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->dest, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + if(!(win2 = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->src, XRT_WINDOW, SecurityReadAccess))) + return BadWindow; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + stuff->src = win2->info[j].id; + result = ProcShapeCombine (client); + BREAK_IF(result != Success); + } + return (result); +} +#endif + +/************* + * ProcShapeOffset + *************/ + +static int +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; + case ShapeInput: + srcRgn = wInputShape (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; +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeOffset( + register ClientPtr client) +{ + REQUEST(xShapeOffsetReq); + PanoramiXRes *win; + int j, result = 0; + + REQUEST_AT_LEAST_SIZE (xShapeOffsetReq); + + if(!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->dest, XRT_WINDOW, SecurityWriteAccess))) + return BadWindow; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + result = ProcShapeOffset (client); + if(result != Success) break; + } + return (result); +} +#endif + + +static int +ProcShapeQueryExtents (client) + register ClientPtr client; +{ + REQUEST(xShapeQueryExtentsReq); + WindowPtr pWin; + xShapeQueryExtentsReply rep; + BoxRec extents, *pExtents; + register int n; + RegionPtr region; + + 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 ((region = wBoundingShape(pWin))) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, region); + 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 ((region = wClipShape(pWin))) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, region); + 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 + */ + +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; + switch (which) { + case 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; + } + break; + case ShapeClip: + 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; + } + break; + case ShapeInput: + region = wInputShape(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; + } + break; + default: + return; + } + 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; + case ShapeInput: + region = wInputShape (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; + case ShapeInput: + 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; + } + } 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 +#endif + return ProcShapeRectangles (client); + case X_ShapeMask: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeMask (client); + else +#endif + return ProcShapeMask (client); + case X_ShapeCombine: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeCombine (client); + else +#endif + return ProcShapeCombine (client); + case X_ShapeOffset: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeOffset (client); + else +#endif + return ProcShapeOffset (client); + 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/nx-X11/programs/Xserver/Xext/shm.c b/nx-X11/programs/Xserver/Xext/shm.c new file mode 100644 index 000000000..f25bb9b5d --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/shm.c @@ -0,0 +1,1310 @@ +/* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.41 2003/12/17 23:28:56 alanh Exp $ */ +/************************************************************ + +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 $ */ + +#define SHM + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <sys/types.h> +#ifndef Lynx +#include <sys/ipc.h> +#include <sys/shm.h> +#else +#include <ipc.h> +#include <shm.h> +#endif +#include <unistd.h> +#include <sys/stat.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/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 <X11/extensions/shmstr.h> +#include <X11/Xfuncproto.h> +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "modinit.h" + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( + pointer /* value */, + XID /* shmseg */ + ); +static void ShmResetProc( + ExtensionEntry * /* extEntry */ + ); +static void SShmCompletionEvent( + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +#ifdef PIXPRIV +static int shmPixmapPrivate; +#endif +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; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) +#include <sys/signal.h> + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall() +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + + if (shmid != -1) + { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + else + { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + +void +ShmExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + 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; + if (sharedPixmaps) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } +#ifdef PIXPRIV + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } +#endif + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) 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( + ScreenPtr pScreen, + ShmFuncsPtr funcs) +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat( + ScreenPtr pScreen, + int format) +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; +#ifdef PIXPRIV + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; +#else + char *base = (char *) pPixmap->devPrivate.ptr; + + if (base != (pointer) (pPixmap + 1)) + { + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) + { + if (shmdesc->addr <= base && base <= shmdesc->addr + shmdesc->size) + break; + } + } + else + shmdesc = 0; +#endif + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + 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); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +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; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + 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, + BitsPerPixel(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); +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(register ClientPtr client) +{ + int j, result = 0, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != client->noClientException) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + + if (client->swapped) { + register int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static int +ProcPanoramiXShmCreatePixmap( + register ClientPtr client) +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + unsigned int width, height, depth; + unsigned long size; + PanoramiXRes *newPix; + + 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); + + width = stuff->width; + height = stuff->height; + depth = stuff->depth; + if (!width || !height || !depth) + { + client->errorValue = 0; + return BadValue; + } + if (width > 32767 || height > 32767) + return BadAlloc; + + 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: + size = PixmapBytePad(width, depth) * height; + if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { + if (size < width * height) + return BadAlloc; + /* thankfully, offset is unsigned */ + if (stuff->offset + size < size) + return BadAlloc; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = (client->noClientException); + + FOR_NSCREENS(j) { + pScreen = screenInfo.screens[j]; + + pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + xfree(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; + 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); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + /* + * There's a potential integer overflow in this check: + * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + * client); + * the version below ought to avoid it + */ + if (stuff->totalHeight != 0 && + length > (shmdesc->size - stuff->offset)/stuff->totalHeight) { + client->errorValue = stuff->totalWidth; + return BadValue; + } + 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; + } + + 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, + shmdesc->addr + stuff->offset + + (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, + shmdesc->addr + stuff->offset); + + 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); + } + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; + + 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) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + 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))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + 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); + + 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, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { + (*pScreen->DestroyPixmap)(pPixmap); + 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); + unsigned int width, height, depth; + unsigned long size; + + 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); + + width = stuff->width; + height = stuff->height; + depth = stuff->depth; + if (!width || !height || !depth) + { + client->errorValue = 0; + return BadValue; + } + if (width > 32767 || height > 32767) + return BadAlloc; + + 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: + size = PixmapBytePad(width, depth) * height; + if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { + if (size < width * height) + return BadAlloc; + /* thankfully, offset is unsigned */ + if (stuff->offset + size < size) + return BadAlloc; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return(client->noClientException); + } + } + 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: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmPutImage(client); +#endif + return ProcShmPutImage(client); + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + 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->pid, n); + 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/nx-X11/programs/Xserver/Xext/sleepuntil.c b/nx-X11/programs/Xserver/Xext/sleepuntil.c new file mode 100644 index 000000000..8e0008cab --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/sleepuntil.c @@ -0,0 +1,239 @@ +/* + * $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 + */ +/* $XFree86: xc/programs/Xserver/Xext/sleepuntil.c,v 3.6 2003/07/16 01:38:30 dawes Exp $ */ + +/* dixsleep.c - implement millisecond timeouts for X clients */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "sleepuntil.h" +#include <X11/X.h> +#include <X11/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)( + ClientPtr /* client */, + pointer /* closure */ + ); + + pointer closure; +} SertafiedRec, *SertafiedPtr; + +static SertafiedPtr pPending; +static RESTYPE SertafiedResType; +static Bool BlockHandlerRegistered; +static int SertafiedGeneration; + +static void ClientAwaken( + ClientPtr /* client */, + pointer /* closure */ +); +static int SertafiedDelete( + pointer /* value */, + XID /* id */ +); +static void SertafiedBlockHandler( + pointer /* data */, + OSTimePtr /* wt */, + pointer /* LastSelectMask */ +); +static void SertafiedWakeupHandler( + pointer /* data */, + int /* i */, + pointer /* LastSelectMask */ +); + +int +ClientSleepUntil (client, revive, notifyFunc, closure) + ClientPtr client; + TimeStamp *revive; + void (*notifyFunc)( + ClientPtr /* client */, + pointer /* closure */); + 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 delay; + 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; + delay = pReq->revive.milliseconds - now.milliseconds; + AdjustWaitForDelay (wt, delay); +} + +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/nx-X11/programs/Xserver/Xext/sleepuntil.h b/nx-X11/programs/Xserver/Xext/sleepuntil.h new file mode 100644 index 000000000..0b99148a4 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/sleepuntil.h @@ -0,0 +1,47 @@ +/* $XFree86: xc/programs/Xserver/Xext/sleepuntil.h,v 1.2 2003/11/17 22:20:27 dawes Exp $ */ +/* + * Copyright (C) 2001 The XFree86 Project, Inc. All Rights Reserved. + * + * 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, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 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 + * XFREE86 PROJECT 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 XFree86 Project 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 + * XFree86 Project. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _SLEEPUNTIL_H_ +#define _SLEEPUNTIL_H_ 1 + +#include "dix.h" + +extern int ClientSleepUntil( + ClientPtr client, + TimeStamp *revive, + void (*notifyFunc)( + ClientPtr /* client */, + pointer /* closure */ + ), + pointer Closure +); + +#endif diff --git a/nx-X11/programs/Xserver/Xext/sync.c b/nx-X11/programs/Xserver/Xext/sync.c new file mode 100644 index 000000000..0e0df8305 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/sync.c @@ -0,0 +1,2513 @@ +/* $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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/sync.c,v 3.13 2003/09/02 18:19:01 tsi Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xmd.h> +#include "misc.h" +#include "os.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _SYNC_SERVER +#include <X11/extensions/sync.h> +#include <X11/extensions/syncstr.h> + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#else +#include <stdio.h> +#if !defined(WIN32) && !defined(Lynx) +#include <sys/time.h> +#endif +#endif + +#include "modinit.h" + +/* + * Local Global Variables + */ +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 int +FreeAlarm( + pointer /* addr */, + XID /* id */ +); + +static int +FreeAlarmClient( + pointer /* value */, + XID /* id */ +); + +static int +FreeAwait( + pointer /* addr */, + XID /* id */ +); + +static void +ServertimeBracketValues( + pointer /* pCounter */, + CARD64 * /* pbracket_less */, + CARD64 * /* pbracket_greater */ +); + +static void +ServertimeQueryValue( + pointer /* pCounter */, + CARD64 * /* pValue_return */ +); + +static void +ServertimeWakeupHandler( + pointer /* env */, + int /* rc */, + pointer /* LastSelectMask */ +); + +static int +SyncInitTrigger( + ClientPtr /* client */, + SyncTrigger * /* pTrigger */, + XSyncCounter /* counter */, + Mask /* changes */ +); + +static void +SAlarmNotifyEvent( + xSyncAlarmNotifyEvent * /* from */, + xSyncAlarmNotifyEvent * /* to */ +); + +static void +SCounterNotifyEvent( + xSyncCounterNotifyEvent * /* from */, + xSyncCounterNotifyEvent * /* to */ +); + +static void +ServertimeBlockHandler( + pointer /* env */, + struct timeval ** /* wt */, + pointer /* LastSelectMask */ +); + +static int +SyncAddTriggerToCounter( + SyncTrigger * /* pTrigger */ +); + +extern void +SyncAlarmCounterDestroyed( + SyncTrigger * /* pTrigger */ +); + +static void +SyncAlarmTriggerFired( + SyncTrigger * /* pTrigger */ +); + +static void +SyncAwaitTriggerFired( + SyncTrigger * /* pTrigger */ +); + +static int +SyncChangeAlarmAttributes( + ClientPtr /* client */, + SyncAlarm * /* pAlarm */, + Mask /* mask */, + CARD32 * /* values */ +); + +static Bool +SyncCheckTriggerNegativeComparison( + SyncTrigger * /* pTrigger */, + CARD64 /* oldval */ +); + +static Bool +SyncCheckTriggerNegativeTransition( + SyncTrigger * /* pTrigger */, + CARD64 /* oldval */ +); + +static Bool +SyncCheckTriggerPositiveComparison( + SyncTrigger * /* pTrigger */, + CARD64 /* oldval */ +); + +static Bool +SyncCheckTriggerPositiveTransition( + SyncTrigger * /* pTrigger */, + CARD64 /* oldval */ +); + +static SyncCounter * +SyncCreateCounter( + ClientPtr /* client */, + XSyncCounter /* id */, + CARD64 /* initialvalue */ +); + +static void SyncComputeBracketValues( + SyncCounter * /* pCounter */, + Bool /* startOver */ +); + +static void +SyncDeleteTriggerFromCounter( + SyncTrigger * /* pTrigger */ +); + +static Bool +SyncEventSelectForAlarm( + SyncAlarm * /* pAlarm */, + ClientPtr /* client */, + Bool /* wantevents */ +); + +static void +SyncInitServerTime( + void +); + +static void +SyncResetProc( + ExtensionEntry * /* extEntry */ +); + +static void +SyncSendAlarmNotifyEvents( + SyncAlarm * /* pAlarm */ +); + +static void +SyncSendCounterNotifyEvents( + ClientPtr /* client */, + SyncAwait ** /* ppAwait */, + int /* num_events */ +); + +static DISPATCH_PROC(ProcSyncAwait); +static DISPATCH_PROC(ProcSyncChangeAlarm); +static DISPATCH_PROC(ProcSyncChangeCounter); +static DISPATCH_PROC(ProcSyncCreateAlarm); +static DISPATCH_PROC(ProcSyncCreateCounter); +static DISPATCH_PROC(ProcSyncDestroyAlarm); +static DISPATCH_PROC(ProcSyncDestroyCounter); +static DISPATCH_PROC(ProcSyncDispatch); +static DISPATCH_PROC(ProcSyncGetPriority); +static DISPATCH_PROC(ProcSyncInitialize); +static DISPATCH_PROC(ProcSyncListSystemCounters); +static DISPATCH_PROC(ProcSyncQueryAlarm); +static DISPATCH_PROC(ProcSyncQueryCounter); +static DISPATCH_PROC(ProcSyncSetCounter); +static DISPATCH_PROC(ProcSyncSetPriority); +static DISPATCH_PROC(SProcSyncAwait); +static DISPATCH_PROC(SProcSyncChangeAlarm); +static DISPATCH_PROC(SProcSyncChangeCounter); +static DISPATCH_PROC(SProcSyncCreateAlarm); +static DISPATCH_PROC(SProcSyncCreateCounter); +static DISPATCH_PROC(SProcSyncDestroyAlarm); +static DISPATCH_PROC(SProcSyncDestroyCounter); +static DISPATCH_PROC(SProcSyncDispatch); +static DISPATCH_PROC(SProcSyncGetPriority); +static DISPATCH_PROC(SProcSyncInitialize); +static DISPATCH_PROC(SProcSyncListSystemCounters); +static DISPATCH_PROC(SProcSyncQueryAlarm); +static DISPATCH_PROC(SProcSyncQueryCounter); +static DISPATCH_PROC(SProcSyncSetCounter); +static DISPATCH_PROC(SProcSyncSetPriority); + +/* 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 CheckTrigger function */ + + switch (pTrigger->test_type) + { + case XSyncPositiveTransition: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; + break; + case XSyncNegativeTransition: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; + break; + case XSyncPositiveComparison: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; + break; + case XSyncNegativeComparison: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; + break; + } + } + + if (changes & (XSyncCAValueType | XSyncCAValue)) + { + if (pTrigger->value_type == XSyncAbsolute) + pTrigger->test_value = pTrigger->wait_value; + else /* relative */ + { + Bool overflow; + if (pCounter == NULL) + return BadMatch; + + XSyncValueAdd(&pTrigger->test_value, pCounter->value, + pTrigger->wait_value, &overflow); + if (overflow) + { + client->errorValue = XSyncValueHigh32(pTrigger->wait_value); + return BadValue; + } + } + } + + /* we wait until we're sure there are no errors before registering + * a new counter on a trigger + */ + if (newcounter) + { + if ((status = SyncAddTriggerToCounter(pTrigger)) != Success) + return status; + } + else if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter, /*startOver*/ TRUE); + } + + return Success; +} + +/* AlarmNotify events happen in response to actions taken on an Alarm or + * the counter used by the alarm. AlarmNotify may be sent to multiple + * clients. The alarm maintains a list of clients interested in events. + */ +static void +SyncSendAlarmNotifyEvents(pAlarm) + SyncAlarm *pAlarm; +{ + SyncAlarmClientList *pcl; + xSyncAlarmNotifyEvent ane; + SyncTrigger *pTrigger = &pAlarm->trigger; + + UpdateCurrentTime(); + + ane.type = SyncEventBase + XSyncAlarmNotify; + ane.kind = XSyncAlarmNotify; + ane.sequenceNumber = pAlarm->client->sequence; + ane.alarm = pAlarm->alarm_id; + if (pTrigger->pCounter) + { + ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + } + else + { /* XXX what else can we do if there's no counter? */ + ane.counter_value_hi = ane.counter_value_lo = 0; + } + + ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); + ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); + ane.time = currentTime.milliseconds; + ane.state = pAlarm->state; + + /* send to owner */ + if (pAlarm->events && !pAlarm->client->clientGone) + WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); + + /* send to other interested clients */ + for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) + { + if (!pAlarm->client->clientGone) + { + ane.sequenceNumber = pcl->client->sequence; + WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); + } + } +} + + +/* CounterNotify events only occur in response to an Await. The events + * go only to the Awaiting client. + */ +static void +SyncSendCounterNotifyEvents(client, ppAwait, num_events) + ClientPtr client; + SyncAwait **ppAwait; + int num_events; +{ + xSyncCounterNotifyEvent *pEvents, *pev; + int i; + + if (client->clientGone) + return; + pev = pEvents = (xSyncCounterNotifyEvent *) + ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent)); + if (!pEvents) + return; + UpdateCurrentTime(); + for (i = 0; i < num_events; i++, ppAwait++, pev++) + { + SyncTrigger *pTrigger = &(*ppAwait)->trigger; + pev->type = SyncEventBase + XSyncCounterNotify; + pev->kind = XSyncCounterNotify; + pev->sequenceNumber = client->sequence; + pev->counter = pTrigger->pCounter->id; + pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); + pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + pev->time = currentTime.milliseconds; + pev->count = num_events - i - 1; /* events remaining */ + pev->destroyed = pTrigger->pCounter->beingDestroyed; + } + /* swapping will be taken care of by this */ + WriteEventsToClient(client, num_events, (xEvent *)pEvents); + DEALLOCATE_LOCAL(pEvents); +} + + +/* This function is called when an alarm's counter is destroyed. + * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). + */ +void +SyncAlarmCounterDestroyed(pTrigger) + SyncTrigger *pTrigger; +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + + pAlarm->state = XSyncAlarmInactive; + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->pCounter = NULL; +} + + +/* This function is called when an alarm "goes off." + * It is plugged into pTrigger->TriggerFired (for alarm triggers). + */ +static void +SyncAlarmTriggerFired(pTrigger) + SyncTrigger *pTrigger; +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + CARD64 new_test_value; + + /* no need to check alarm unless it's active */ + if (pAlarm->state != XSyncAlarmActive) + return; + + /* " if the counter value is None, or if the delta is 0 and + * the test-type is PositiveComparison or NegativeComparison, + * no change is made to value (test-value) and the alarm + * state is changed to Inactive before the event is generated." + */ + if (pAlarm->trigger.pCounter == NULL + || (XSyncValueIsZero(pAlarm->delta) + && (pAlarm->trigger.test_type == XSyncPositiveComparison + || pAlarm->trigger.test_type == XSyncNegativeComparison))) + pAlarm->state = XSyncAlarmInactive; + + new_test_value = pAlarm->trigger.test_value; + + if (pAlarm->state == XSyncAlarmActive) + { + Bool overflow; + CARD64 oldvalue; + SyncTrigger *paTrigger = &pAlarm->trigger; + + /* "The alarm is updated by repeatedly adding delta to the + * value of the trigger and re-initializing it until it + * becomes FALSE." + */ + oldvalue = paTrigger->test_value; + + /* XXX really should do something smarter here */ + + do + { + XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, + pAlarm->delta, &overflow); + } while (!overflow && + (*paTrigger->CheckTrigger)(paTrigger, + paTrigger->pCounter->value)); + + new_test_value = paTrigger->test_value; + paTrigger->test_value = oldvalue; + + /* "If this update would cause value to fall outside the range + * for an INT64...no change is made to value (test-value) and + * the alarm state is changed to Inactive before the event is + * generated." + */ + if (overflow) + { + new_test_value = oldvalue; + pAlarm->state = XSyncAlarmInactive; + } + } + /* The AlarmNotify event has to have the "new state of the alarm" + * which we can't be sure of until this point. However, it has + * to have the "old" trigger test value. That's the reason for + * all the newvalue/oldvalue shuffling above. After we send the + * events, give the trigger its new test value. + */ + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->test_value = new_test_value; +} + + +/* This function is called when an Await unblocks, either as a result + * of the trigger firing OR the counter being destroyed. + * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed + * (for Await triggers). + */ +static void +SyncAwaitTriggerFired(pTrigger) + SyncTrigger *pTrigger; +{ + SyncAwait *pAwait = (SyncAwait *)pTrigger; + int numwaits; + SyncAwaitUnion *pAwaitUnion; + SyncAwait **ppAwait; + int num_events = 0; + + pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; + numwaits = pAwaitUnion->header.num_waitconditions; + ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *)); + if (!ppAwait) + goto bail; + + pAwait = &(pAwaitUnion+1)->await; + + /* "When a client is unblocked, all the CounterNotify events for + * the Await request are generated contiguously. If count is 0 + * there are no more events to follow for this request. If + * count is n, there are at least n more events to follow." + * + * Thus, it is best to find all the counters for which events + * need to be sent first, so that an accurate count field can + * be stored in the events. + */ + for ( ; numwaits; numwaits--, pAwait++) + { + CARD64 diff; + Bool overflow, diffgreater, diffequal; + + /* "A CounterNotify event with the destroyed flag set to TRUE is + * always generated if the counter for one of the triggers is + * destroyed." + */ + if (pAwait->trigger.pCounter->beingDestroyed) + { + ppAwait[num_events++] = pAwait; + continue; + } + + /* "The difference between the counter and the test value is + * calculated by subtracting the test value from the value of + * the counter." + */ + XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, + pAwait->trigger.test_value, &overflow); + + /* "If the difference lies outside the range for an INT64, an + * event is not generated." + */ + if (overflow) + continue; + diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); + diffequal = XSyncValueEqual(diff, pAwait->event_threshold); + + /* "If the test-type is PositiveTransition or + * PositiveComparison, a CounterNotify event is generated if + * the difference is at least event-threshold. If the test-type + * is NegativeTransition or NegativeComparison, a CounterNotify + * event is generated if the difference is at most + * event-threshold." + */ + + if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || + pAwait->trigger.test_type == XSyncPositiveTransition) + && (diffgreater || diffequal)) + || + ((pAwait->trigger.test_type == XSyncNegativeComparison || + pAwait->trigger.test_type == XSyncNegativeTransition) + && (!diffgreater) /* less or equal */ + ) + ) + { + ppAwait[num_events++] = pAwait; + } + } + if (num_events) + SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, + num_events); + DEALLOCATE_LOCAL(ppAwait); + +bail: + /* unblock the client */ + AttendClient(pAwaitUnion->header.client); + /* delete the await */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); +} + + +/* This function should always be used to change a counter's value so that + * any triggers depending on the counter will be checked. + */ +void +SyncChangeCounter(pCounter, newval) + SyncCounter *pCounter; + CARD64 newval; +{ + SyncTriggerList *ptl, *pnext; + CARD64 oldval; + + oldval = pCounter->value; + pCounter->value = newval; + + /* run through triggers to see if any become true */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + pnext = ptl->next; + if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) + (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); + } + + if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter, /* startOver */ FALSE); + } +} + + +/* loosely based on dix/events.c/EventSelectForWindow */ +static Bool +SyncEventSelectForAlarm(pAlarm, client, wantevents) + SyncAlarm *pAlarm; + ClientPtr client; + Bool wantevents; +{ + SyncAlarmClientList *pClients; + + if (client == pAlarm->client) /* alarm owner */ + { + pAlarm->events = wantevents; + return Success; + } + + /* see if the client is already on the list (has events selected) */ + + for (pClients = pAlarm->pEventClients; pClients; + pClients = pClients->next) + { + if (pClients->client == client) + { + /* client's presence on the list indicates desire for + * events. If the client doesn't want events, remove it + * from the list. If the client does want events, do + * nothing, since it's already got them. + */ + if (!wantevents) + { + FreeResource(pClients->delete_id, RT_NONE); + } + return Success; + } + } + + /* if we get here, this client does not currently have + * events selected on the alarm + */ + + if (!wantevents) + /* client doesn't want events, and we just discovered that it + * doesn't have them, so there's nothing to do. + */ + return Success; + + /* add new client to pAlarm->pEventClients */ + + pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList)); + if (!pClients) + return BadAlloc; + + /* register it as a resource so it will be cleaned up + * if the client dies + */ + + pClients->delete_id = FakeClientID(client->index); + if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) + { + xfree(pClients); + return BadAlloc; + } + + /* link it into list after we know all the allocations succeed */ + + pClients->next = pAlarm->pEventClients; + pAlarm->pEventClients = pClients; + pClients->client = client; + return Success; +} + +/* + * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm + */ +static int +SyncChangeAlarmAttributes(client, pAlarm, mask, values) + ClientPtr client; + SyncAlarm *pAlarm; + Mask mask; + CARD32 *values; +{ + int status; + XSyncCounter counter; + Mask origmask = mask; + + counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; + + while (mask) + { + int index2 = lowbit(mask); + mask &= ~index2; + switch (index2) + { + case XSyncCACounter: + mask &= ~XSyncCACounter; + /* sanity check in SyncInitTrigger */ + counter = *values++; + break; + + case XSyncCAValueType: + mask &= ~XSyncCAValueType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.value_type = *values++; + break; + + case XSyncCAValue: + mask &= ~XSyncCAValue; + XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); + values += 2; + break; + + case XSyncCATestType: + mask &= ~XSyncCATestType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.test_type = *values++; + break; + + case XSyncCADelta: + mask &= ~XSyncCADelta; + XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); + values += 2; + break; + + case XSyncCAEvents: + mask &= ~XSyncCAEvents; + if ((*values != xTrue) && (*values != xFalse)) + { + client->errorValue = *values; + return BadValue; + } + status = SyncEventSelectForAlarm(pAlarm, client, + (Bool)(*values++)); + if (status != Success) + return status; + break; + + default: + client->errorValue = mask; + return BadValue; + } + } + + /* "If the test-type is PositiveComparison or PositiveTransition + * and delta is less than zero, or if the test-type is + * NegativeComparison or NegativeTransition and delta is + * greater than zero, a Match error is generated." + */ + if (origmask & (XSyncCADelta|XSyncCATestType)) + { + CARD64 zero; + XSyncIntToValue(&zero, 0); + if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || + (pAlarm->trigger.test_type == XSyncPositiveTransition)) + && XSyncValueLessThan(pAlarm->delta, zero)) + || + (((pAlarm->trigger.test_type == XSyncNegativeComparison) || + (pAlarm->trigger.test_type == XSyncNegativeTransition)) + && XSyncValueGreaterThan(pAlarm->delta, zero)) + ) + { + return BadMatch; + } + } + + /* postpone this until now, when we're sure nothing else can go wrong */ + if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, + origmask & XSyncCAAllTrigger)) != Success) + return status; + + /* XXX spec does not really say to do this - needs clarification */ + pAlarm->state = XSyncAlarmActive; + return Success; +} + + +static SyncCounter * +SyncCreateCounter(client, id, initialvalue) + ClientPtr client; + XSyncCounter id; + CARD64 initialvalue; +{ + SyncCounter *pCounter; + + if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter)))) + return (SyncCounter *)NULL; + + if (!AddResource(id, RTCounter, (pointer) pCounter)) + { + xfree((pointer) pCounter); + return (SyncCounter *)NULL; + } + + pCounter->client = client; + pCounter->id = id; + pCounter->value = initialvalue; + pCounter->pTriglist = NULL; + pCounter->beingDestroyed = FALSE; + pCounter->pSysCounterInfo = NULL; + return pCounter; +} + +static int FreeCounter( + pointer /*env*/, + XID /*id*/ +); + +/* + * ***** System Counter utilities + */ + +pointer +SyncCreateSystemCounter(name, initial, resolution, counterType, + QueryValue, BracketValues) + char *name; + CARD64 initial; + CARD64 resolution; + SyncCounterType counterType; + void (*QueryValue) ( + pointer /* pCounter */, + CARD64 * /* pValue_return */); + void (*BracketValues) ( + pointer /* pCounter */, + CARD64 * /* pbracket_less */, + CARD64 * /* pbracket_greater */); +{ + SyncCounter *pCounter; + + SysCounterList = (SyncCounter **)xrealloc(SysCounterList, + (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); + if (!SysCounterList) + return (pointer)NULL; + + /* this function may be called before SYNC has been initialized, so we + * have to make sure RTCounter is created. + */ + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter); + if (RTCounter == 0) + { + return (pointer)NULL; + } + } + + pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial); + + if (pCounter) + { + SysCounterInfo *psci; + + psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo)); + if (!psci) + { + FreeResource(pCounter->id, RT_NONE); + return (pointer) pCounter; + } + pCounter->pSysCounterInfo = psci; + psci->name = name; + psci->resolution = resolution; + psci->counterType = counterType; + psci->QueryValue = QueryValue; + psci->BracketValues = BracketValues; + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + SysCounterList[SyncNumSystemCounters++] = pCounter; + } + return (pointer) pCounter; +} + +void +SyncDestroySystemCounter(pSysCounter) + pointer pSysCounter; +{ + SyncCounter *pCounter = (SyncCounter *)pSysCounter; + FreeResource(pCounter->id, RT_NONE); +} + +static void +SyncComputeBracketValues(pCounter, startOver) + SyncCounter *pCounter; + Bool startOver; +{ + SyncTriggerList *pCur; + SyncTrigger *pTrigger; + SysCounterInfo *psci = pCounter->pSysCounterInfo; + CARD64 *pnewgtval = NULL; + CARD64 *pnewltval = NULL; + SyncCounterType ct; + + if (!pCounter) + return; + + ct = pCounter->pSysCounterInfo->counterType; + if (ct == XSyncCounterNeverChanges) + return; + + if (startOver) + { + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + } + + for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) + { + pTrigger = pCur->pTrigger; + + if (pTrigger->test_type == XSyncPositiveComparison && + ct != XSyncCounterNeverIncreases) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && + XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + } + else if (pTrigger->test_type == XSyncNegativeComparison && + ct != XSyncCounterNeverDecreases) + { + if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && + XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + else if ( (pTrigger->test_type == XSyncPositiveTransition && + ct != XSyncCounterNeverIncreases) + || + (pTrigger->test_type == XSyncNegativeTransition && + ct != XSyncCounterNeverDecreases) + ) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value)) + { + if (XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + else + if (XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + } + } /* end for each trigger */ + + if (pnewgtval || pnewltval) + { + (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); + } +} + +/* + * ***** Resource delete functions + */ + +/* ARGSUSED */ +static int +FreeAlarm(addr, id) + pointer addr; + XID id; +{ + SyncAlarm *pAlarm = (SyncAlarm *) addr; + + pAlarm->state = XSyncAlarmDestroyed; + + SyncSendAlarmNotifyEvents(pAlarm); + + /* delete event selections */ + + while (pAlarm->pEventClients) + FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); + + SyncDeleteTriggerFromCounter(&pAlarm->trigger); + + xfree(pAlarm); + return Success; +} + + +/* + * ** Cleanup after the destruction of a Counter + */ +/* ARGSUSED */ +static int +FreeCounter(env, id) + pointer env; + XID id; +{ + SyncCounter *pCounter = (SyncCounter *) env; + SyncTriggerList *ptl, *pnext; + + pCounter->beingDestroyed = TRUE; + /* tell all the counter's triggers that the counter has been destroyed */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); + pnext = ptl->next; + xfree(ptl); /* destroy the trigger list as we go */ + } + if (IsSystemCounter(pCounter)) + { + int i, found = 0; + + xfree(pCounter->pSysCounterInfo); + + /* find the counter in the list of system counters and remove it */ + + if (SysCounterList) + { + for (i = 0; i < SyncNumSystemCounters; i++) + { + if (SysCounterList[i] == pCounter) + { + found = i; + break; + } + } + if (found < (SyncNumSystemCounters-1)) + { + for (i = found; i < SyncNumSystemCounters-1; i++) + { + SysCounterList[i] = SysCounterList[i+1]; + } + } + } + SyncNumSystemCounters--; + } + xfree(pCounter); + return Success; +} + +/* + * ** Cleanup after Await + */ +/* ARGSUSED */ +static int +FreeAwait(addr, id) + pointer addr; + XID id; +{ + SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; + SyncAwait *pAwait; + int numwaits; + + pAwait = &(pAwaitUnion+1)->await; /* first await on list */ + + /* remove triggers from counters */ + + for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; + numwaits--, pAwait++) + { + /* If the counter is being destroyed, FreeCounter will delete + * the trigger list itself, so don't do it here. + */ + SyncCounter *pCounter = pAwait->trigger.pCounter; + if (pCounter && !pCounter->beingDestroyed) + SyncDeleteTriggerFromCounter(&pAwait->trigger); + } + xfree(pAwaitUnion); + return Success; +} + +/* loosely based on dix/events.c/OtherClientGone */ +static int +FreeAlarmClient(value, id) + pointer value; /* must conform to DeleteType */ + XID id; +{ + SyncAlarm *pAlarm = (SyncAlarm *)value; + SyncAlarmClientList *pCur, *pPrev; + + for (pPrev = NULL, pCur = pAlarm->pEventClients; + pCur; + pPrev = pCur, pCur = pCur->next) + { + if (pCur->delete_id == id) + { + if (pPrev) + pPrev->next = pCur->next; + else + pAlarm->pEventClients = pCur->next; + xfree(pCur); + return(Success); + } + } + FatalError("alarm client not on event list"); + /*NOTREACHED*/ +} + + +/* + * ***** Proc functions + */ + + +/* + * ** Initialize the extension + */ +static int +ProcSyncInitialize(client) + ClientPtr client; +{ + xSyncInitializeReply rep; + int n; + + REQUEST_SIZE_MATCH(xSyncInitializeReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SYNC_MAJOR_VERSION; + rep.minorVersion = SYNC_MINOR_VERSION; + rep.length = 0; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(rep), (char *) &rep); + return (client->noClientException); +} + +/* + * ** Get list of system counters available through the extension + */ +static int +ProcSyncListSystemCounters(client) + ClientPtr client; +{ + xSyncListSystemCountersReply rep; + int i, len; + xSyncSystemCounter *list = NULL, *walklist = NULL; + + REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nCounters = SyncNumSystemCounters; + + for (i = len = 0; i < SyncNumSystemCounters; i++) + { + char *name = SysCounterList[i]->pSysCounterInfo->name; + /* pad to 4 byte boundary */ + len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3; + } + + if (len) + { + walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len); + if (!list) + return BadAlloc; + } + + rep.length = len >> 2; + + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.nCounters, n); + } + + for (i = 0; i < SyncNumSystemCounters; i++) + { + int namelen; + char *pname_in_reply; + SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; + + walklist->counter = SysCounterList[i]->id; + walklist->resolution_hi = XSyncValueHigh32(psci->resolution); + walklist->resolution_lo = XSyncValueLow32(psci->resolution); + namelen = strlen(psci->name); + walklist->name_length = namelen; + + if (client->swapped) + { + register char n; + swapl(&walklist->counter, n); + swapl(&walklist->resolution_hi, n); + swapl(&walklist->resolution_lo, n); + swaps(&walklist->name_length, n); + } + + pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; + strncpy(pname_in_reply, psci->name, namelen); + walklist = (xSyncSystemCounter *) (((char *)walklist) + + ((sz_xSyncSystemCounter + namelen + 3) & ~3)); + } + + WriteToClient(client, sizeof(rep), (char *) &rep); + if (len) + { + WriteToClient(client, len, (char *) list); + DEALLOCATE_LOCAL(list); + } + + return (client->noClientException); +} + +/* + * ** Set client Priority + */ +static int +ProcSyncSetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncSetPriorityReq); + ClientPtr priorityclient; + + REQUEST_SIZE_MATCH(xSyncSetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else if (!(priorityclient = LookupClient(stuff->id, client))) + { + client->errorValue = stuff->id; + return BadMatch; + } + + if (priorityclient->priority != stuff->priority) + { + priorityclient->priority = stuff->priority; + + /* The following will force the server back into WaitForSomething + * so that the change in this client's priority is immediately + * reflected. + */ + isItTimeToYield = TRUE; + dispatchException |= DE_PRIORITYCHANGE; + } + return Success; +} + +/* + * ** Get client Priority + */ +static int +ProcSyncGetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncGetPriorityReq); + xSyncGetPriorityReply rep; + ClientPtr priorityclient; + + REQUEST_SIZE_MATCH(xSyncGetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else if (!(priorityclient = LookupClient(stuff->id, client))) + { + client->errorValue = stuff->id; + return BadMatch; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.priority = priorityclient->priority; + + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.priority, n); + } + + WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); + + return (client->noClientException); +} + +/* + * ** Create a new counter + */ +static int +ProcSyncCreateCounter(client) + ClientPtr client; +{ + REQUEST(xSyncCreateCounterReq); + CARD64 initial; + + REQUEST_SIZE_MATCH(xSyncCreateCounterReq); + + LEGAL_NEW_RESOURCE(stuff->cid, client); + + XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); + if (!SyncCreateCounter(client, stuff->cid, initial)) + return BadAlloc; + + return (client->noClientException); +} + +/* + * ** Set Counter value + */ +static int +ProcSyncSetCounter(client) + ClientPtr client; +{ + REQUEST(xSyncSetCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + + REQUEST_SIZE_MATCH(xSyncSetCounterReq); + + pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid, + RTCounter, SecurityWriteAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->cid; + return SyncErrorBase + XSyncBadCounter; + } + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Change Counter value + */ +static int +ProcSyncChangeCounter(client) + ClientPtr client; +{ + REQUEST(xSyncChangeCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + Bool overflow; + + REQUEST_SIZE_MATCH(xSyncChangeCounterReq); + + pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid, + RTCounter, SecurityWriteAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->cid; + return SyncErrorBase + XSyncBadCounter; + } + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); + if (overflow) + { + /* XXX 64 bit value can't fit in 32 bits; do the best we can */ + client->errorValue = stuff->value_hi; + return BadValue; + } + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Destroy a counter + */ +static int +ProcSyncDestroyCounter(client) + ClientPtr client; +{ + REQUEST(xSyncDestroyCounterReq); + SyncCounter *pCounter; + + REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); + + pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, + RTCounter, SecurityDestroyAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->counter; + return SyncErrorBase + XSyncBadCounter; + } + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->counter; + return BadAccess; + } + FreeResource(pCounter->id, RT_NONE); + return Success; +} + + +/* + * ** Await + */ +static int +ProcSyncAwait(client) + ClientPtr client; +{ + REQUEST(xSyncAwaitReq); + int len, items; + int i; + xSyncWaitCondition *pProtocolWaitConds; + SyncAwaitUnion *pAwaitUnion; + SyncAwait *pAwait; + int status; + + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + + len = client->req_len << 2; + len -= sz_xSyncAwaitReq; + items = len / sz_xSyncWaitCondition; + + if (items * sz_xSyncWaitCondition != len) + { + return BadLength; + } + if (items == 0) + { + client->errorValue = items; /* XXX protocol change */ + return BadValue; + } + + pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; + + /* all the memory for the entire await list is allocated + * here in one chunk + */ + pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion)); + if (!pAwaitUnion) + return BadAlloc; + + /* first item is the header, remainder are real wait conditions */ + + pAwaitUnion->header.delete_id = FakeClientID(client->index); + if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) + { + xfree(pAwaitUnion); + return BadAlloc; + } + + /* don't need to do any more memory allocation for this request! */ + + pAwaitUnion->header.client = client; + pAwaitUnion->header.num_waitconditions = 0; + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) + { + if (pProtocolWaitConds->counter == None) /* XXX protocol change */ + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + client->errorValue = pProtocolWaitConds->counter; + return SyncErrorBase + XSyncBadCounter; + } + + /* sanity checks are in SyncInitTrigger */ + pAwait->trigger.pCounter = NULL; + pAwait->trigger.value_type = pProtocolWaitConds->value_type; + XSyncIntsToValue(&pAwait->trigger.wait_value, + pProtocolWaitConds->wait_value_lo, + pProtocolWaitConds->wait_value_hi); + pAwait->trigger.test_type = pProtocolWaitConds->test_type; + + status = SyncInitTrigger(client, &pAwait->trigger, + pProtocolWaitConds->counter, XSyncCAAllTrigger); + if (status != Success) + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + return status; + } + /* this is not a mistake -- same function works for both cases */ + pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; + pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; + XSyncIntsToValue(&pAwait->event_threshold, + pProtocolWaitConds->event_threshold_lo, + pProtocolWaitConds->event_threshold_hi); + pAwait->pHeader = &pAwaitUnion->header; + pAwaitUnion->header.num_waitconditions++; + } + + IgnoreClient(client); + + /* see if any of the triggers are already true */ + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pAwait++) + { + /* don't have to worry about NULL counters because the request + * errors before we get here out if they occur + */ + if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, + pAwait->trigger.pCounter->value)) + { + (*pAwait->trigger.TriggerFired)(&pAwait->trigger); + break; /* once is enough */ + } + } + return Success; +} + + +/* + * ** Query a counter + */ +static int +ProcSyncQueryCounter(client) + ClientPtr client; +{ + REQUEST(xSyncQueryCounterReq); + xSyncQueryCounterReply rep; + SyncCounter *pCounter; + + REQUEST_SIZE_MATCH(xSyncQueryCounterReq); + + pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, + RTCounter, SecurityReadAccess); + if (pCounter == NULL) + { + client->errorValue = stuff->counter; + return SyncErrorBase + XSyncBadCounter; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + rep.value_hi = XSyncValueHigh32(pCounter->value); + rep.value_lo = XSyncValueLow32(pCounter->value); + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.value_hi, n); + swapl(&rep.value_lo, n); + } + WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); + return (client->noClientException); +} + + +/* + * ** Create Alarm + */ +static int +ProcSyncCreateAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncCreateAlarmReq); + SyncAlarm *pAlarm; + int status; + unsigned long len, vmask; + SyncTrigger *pTrigger; + + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + + LEGAL_NEW_RESOURCE(stuff->id, client); + + vmask = stuff->valueMask; + len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm)))) + { + return BadAlloc; + } + + /* set up defaults */ + + pTrigger = &pAlarm->trigger; + pTrigger->pCounter = NULL; + pTrigger->value_type = XSyncAbsolute; + XSyncIntToValue(&pTrigger->wait_value, 0L); + pTrigger->test_type = XSyncPositiveComparison; + pTrigger->TriggerFired = SyncAlarmTriggerFired; + pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; + status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); + if (status != Success) + { + xfree(pAlarm); + return status; + } + + pAlarm->client = client; + pAlarm->alarm_id = stuff->id; + XSyncIntToValue(&pAlarm->delta, 1L); + pAlarm->events = TRUE; + pAlarm->state = XSyncAlarmInactive; + pAlarm->pEventClients = NULL; + status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1]); + if (status != Success) + { + xfree(pAlarm); + return status; + } + + if (!AddResource(stuff->id, RTAlarm, pAlarm)) + { + xfree(pAlarm); + return BadAlloc; + } + + /* see if alarm already triggered. NULL counter will not trigger + * in CreateAlarm and sets alarm state to Inactive. + */ + + if (!pTrigger->pCounter) + { + pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ + } + else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) + { + (*pTrigger->TriggerFired)(pTrigger); + } + + return Success; +} + +/* + * ** Change Alarm + */ +static int +ProcSyncChangeAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncChangeAlarmReq); + SyncAlarm *pAlarm; + long vmask; + int len, status; + + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + + if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityWriteAccess))) + { + client->errorValue = stuff->alarm; + return SyncErrorBase + XSyncBadAlarm; + } + + vmask = stuff->valueMask; + len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1])) != Success) + return status; + + /* see if alarm already triggered. NULL counter WILL trigger + * in ChangeAlarm. + */ + + if (!pAlarm->trigger.pCounter || + (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, + pAlarm->trigger.pCounter->value)) + { + (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); + } + return Success; +} + +static int +ProcSyncQueryAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncQueryAlarmReq); + SyncAlarm *pAlarm; + xSyncQueryAlarmReply rep; + SyncTrigger *pTrigger; + + REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); + + pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityReadAccess); + if (!pAlarm) + { + client->errorValue = stuff->alarm; + return (SyncErrorBase + XSyncBadAlarm); + } + + rep.type = X_Reply; + rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + + pTrigger = &pAlarm->trigger; + rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; + +#if 0 /* XXX unclear what to do, depends on whether relative value-types + * are "consumed" immediately and are considered absolute from then + * on. + */ + rep.value_type = pTrigger->value_type; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); +#else + rep.value_type = XSyncAbsolute; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); +#endif + + rep.test_type = pTrigger->test_type; + rep.delta_hi = XSyncValueHigh32(pAlarm->delta); + rep.delta_lo = XSyncValueLow32(pAlarm->delta); + rep.events = pAlarm->events; + rep.state = pAlarm->state; + + if (client->swapped) + { + register char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.counter, n); + swapl(&rep.wait_value_hi, n); + swapl(&rep.wait_value_lo, n); + swapl(&rep.test_type, n); + swapl(&rep.delta_hi, n); + swapl(&rep.delta_lo, n); + } + + WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); + return (client->noClientException); +} + + +static int +ProcSyncDestroyAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncDestroyAlarmReq); + + REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); + + if (!((SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityDestroyAccess))) + { + client->errorValue = stuff->alarm; + return SyncErrorBase + XSyncBadAlarm; + } + + FreeResource(stuff->alarm, RT_NONE); + return (client->noClientException); +} + +/* + * ** Given an extension request, call the appropriate request procedure + */ +static int +ProcSyncDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + + case X_SyncInitialize: + return ProcSyncInitialize(client); + case X_SyncListSystemCounters: + return ProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return ProcSyncCreateCounter(client); + case X_SyncSetCounter: + return ProcSyncSetCounter(client); + case X_SyncChangeCounter: + return ProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return ProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return ProcSyncDestroyCounter(client); + case X_SyncAwait: + return ProcSyncAwait(client); + case X_SyncCreateAlarm: + return ProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return ProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return ProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return ProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return ProcSyncSetPriority(client); + case X_SyncGetPriority: + return ProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Boring Swapping stuff ... + */ + +static int +SProcSyncInitialize(client) + ClientPtr client; +{ + REQUEST(xSyncInitializeReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncInitializeReq); + + return ProcSyncInitialize(client); +} + +static int +SProcSyncListSystemCounters(client) + ClientPtr client; +{ + REQUEST(xSyncListSystemCountersReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); + + return ProcSyncListSystemCounters(client); +} + +static int +SProcSyncCreateCounter(client) + ClientPtr client; +{ + REQUEST(xSyncCreateCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncCreateCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->initial_value_lo, n); + swapl(&stuff->initial_value_hi, n); + + return ProcSyncCreateCounter(client); +} + +static int +SProcSyncSetCounter(client) + ClientPtr client; +{ + REQUEST(xSyncSetCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncSetCounter(client); +} + +static int +SProcSyncChangeCounter(client) + ClientPtr client; +{ + REQUEST(xSyncChangeCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncChangeCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncChangeCounter(client); +} + +static int +SProcSyncQueryCounter(client) + ClientPtr client; +{ + REQUEST(xSyncQueryCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncQueryCounter(client); +} + +static int +SProcSyncDestroyCounter(client) + ClientPtr client; +{ + REQUEST(xSyncDestroyCounterReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncDestroyCounter(client); +} + +static int +SProcSyncAwait(client) + ClientPtr client; +{ + REQUEST(xSyncAwaitReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + SwapRestL(stuff); + + return ProcSyncAwait(client); +} + + +static int +SProcSyncCreateAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncCreateAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + swapl(&stuff->id, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + + return ProcSyncCreateAlarm(client); +} + +static int +SProcSyncChangeAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncChangeAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + swapl(&stuff->alarm, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSyncChangeAlarm(client); +} + +static int +SProcSyncQueryAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncQueryAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncQueryAlarm(client); +} + +static int +SProcSyncDestroyAlarm(client) + ClientPtr client; +{ + REQUEST(xSyncDestroyAlarmReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncDestroyAlarm(client); +} + +static int +SProcSyncSetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncSetPriorityReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetPriorityReq); + swapl(&stuff->id, n); + swapl(&stuff->priority, n); + + return ProcSyncSetPriority(client); +} + +static int +SProcSyncGetPriority(client) + ClientPtr client; +{ + REQUEST(xSyncGetPriorityReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncGetPriorityReq); + swapl(&stuff->id, n); + + return ProcSyncGetPriority(client); +} + + +static int +SProcSyncDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SyncInitialize: + return SProcSyncInitialize(client); + case X_SyncListSystemCounters: + return SProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return SProcSyncCreateCounter(client); + case X_SyncSetCounter: + return SProcSyncSetCounter(client); + case X_SyncChangeCounter: + return SProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return SProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return SProcSyncDestroyCounter(client); + case X_SyncAwait: + return SProcSyncAwait(client); + case X_SyncCreateAlarm: + return SProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return SProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return SProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return SProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return SProcSyncSetPriority(client); + case X_SyncGetPriority: + return SProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Event Swapping + */ + +static void +SCounterNotifyEvent(from, to) + xSyncCounterNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->counter, to->counter); + cpswapl(from->wait_value_lo, to->wait_value_lo); + cpswapl(from->wait_value_hi, to->wait_value_hi); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->time, to->time); + cpswaps(from->count, to->count); + to->destroyed = from->destroyed; +} + + +static void +SAlarmNotifyEvent(from, to) + xSyncAlarmNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->alarm, to->alarm); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->alarm_value_lo, to->alarm_value_lo); + cpswapl(from->alarm_value_hi, to->alarm_value_hi); + cpswapl(from->time, to->time); + to->state = from->state; +} + +/* + * ** Close everything down. ** This is fairly simple for now. + */ +/* ARGSUSED */ +static void +SyncResetProc(extEntry) + ExtensionEntry *extEntry; +{ + xfree(SysCounterList); + SysCounterList = NULL; + RTCounter = 0; +} + + +/* + * ** Initialise the extension. + */ +void +SyncExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter); + } + RTAlarm = CreateNewResourceType(FreeAlarm); + RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN; + RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN; + + if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || + RTAlarmClient == 0 || + (extEntry = AddExtension(SYNC_NAME, + XSyncNumberEvents, XSyncNumberErrors, + ProcSyncDispatch, SProcSyncDispatch, + SyncResetProc, + StandardMinorOpcode)) == NULL) + { + ErrorF("Sync Extension %d.%d failed to Initialise\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); + return; + } + + SyncEventBase = extEntry->eventBase; + SyncErrorBase = extEntry->errorBase; + EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; + EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; + + /* + * Although SERVERTIME is implemented by the OS layer, we initialise it + * here because doing it in OsInit() is too early. The resource database + * is not initialised when OsInit() is called. This is just about OK + * because there is always a servertime counter. + */ + SyncInitServerTime(); + +#ifdef DEBUG + fprintf(stderr, "Sync Extension %d.%d\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); +#endif +} + + +/* + * ***** SERVERTIME implementation - should go in its own file in OS directory? + */ + + + +static pointer ServertimeCounter; +static XSyncValue Now; +static XSyncValue *pnext_time; + +#define GetTime()\ +{\ + unsigned long millis = GetTimeInMillis();\ + unsigned long maxis = XSyncValueHigh32(Now);\ + if (millis < XSyncValueLow32(Now)) maxis++;\ + XSyncIntsToValue(&Now, millis, maxis);\ +} + +/* +*** Server Block Handler +*** code inspired by multibuffer extension + */ +/*ARGSUSED*/ +static void ServertimeBlockHandler(env, wt, LastSelectMask) +pointer env; +struct timeval **wt; +pointer LastSelectMask; +{ + XSyncValue delay; + unsigned long timeout; + + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + timeout = 0; + } + else + { + Bool overflow; + XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); + (void)overflow; + timeout = XSyncValueLow32(delay); + } + AdjustWaitForDelay(wt, timeout); /* os/utils.c */ + } +} + +/* +*** Wakeup Handler + */ +/*ARGSUSED*/ +static void ServertimeWakeupHandler(env, rc, LastSelectMask) +pointer env; +int rc; +pointer LastSelectMask; +{ + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + SyncChangeCounter(ServertimeCounter, Now); + } + } +} + +static void +ServertimeQueryValue(pCounter, pValue_return) + pointer pCounter; + CARD64 *pValue_return; +{ + GetTime(); + *pValue_return = Now; +} + +static void +ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater) + pointer pCounter; + CARD64 *pbracket_less; + CARD64 *pbracket_greater; +{ + if (!pnext_time && pbracket_greater) + { + RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + else if (pnext_time && !pbracket_greater) + { + RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + pnext_time = pbracket_greater; +} + +static void +SyncInitServerTime() +{ + CARD64 resolution; + + XSyncIntsToValue(&Now, GetTimeInMillis(), 0); + XSyncIntToValue(&resolution, 4); + ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, + XSyncCounterNeverDecreases, + ServertimeQueryValue, ServertimeBracketValues); + pnext_time = NULL; +} diff --git a/nx-X11/programs/Xserver/Xext/vidmodeproc.h b/nx-X11/programs/Xserver/Xext/vidmodeproc.h new file mode 100644 index 000000000..918d1e4df --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/vidmodeproc.h @@ -0,0 +1,78 @@ +/* $XFree86: xc/programs/Xserver/Xext/vidmodeproc.h,v 1.4 1999/12/13 01:39:40 robin Exp $ */ + +/* Prototypes for DGA functions that the DDX must provide */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _VIDMODEPROC_H_ +#define _VIDMODEPROC_H_ + + +typedef enum { + VIDMODE_H_DISPLAY, + VIDMODE_H_SYNCSTART, + VIDMODE_H_SYNCEND, + VIDMODE_H_TOTAL, + VIDMODE_H_SKEW, + VIDMODE_V_DISPLAY, + VIDMODE_V_SYNCSTART, + VIDMODE_V_SYNCEND, + VIDMODE_V_TOTAL, + VIDMODE_FLAGS, + VIDMODE_CLOCK +} VidModeSelectMode; + +typedef enum { + VIDMODE_MON_VENDOR, + VIDMODE_MON_MODEL, + VIDMODE_MON_NHSYNC, + VIDMODE_MON_NVREFRESH, + VIDMODE_MON_HSYNC_LO, + VIDMODE_MON_HSYNC_HI, + VIDMODE_MON_VREFRESH_LO, + VIDMODE_MON_VREFRESH_HI +} VidModeSelectMonitor; + +typedef union { + pointer ptr; + int i; + float f; +} vidMonitorValue; + +void XFree86VidModeExtensionInit(void); + +Bool VidModeAvailable(int scrnIndex); +Bool VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock); +Bool VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock); +Bool VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock); +Bool VidModeDeleteModeline(int scrnIndex, pointer mode); +Bool VidModeZoomViewport(int scrnIndex, int zoom); +Bool VidModeGetViewPort(int scrnIndex, int *x, int *y); +Bool VidModeSetViewPort(int scrnIndex, int x, int y); +Bool VidModeSwitchMode(int scrnIndex, pointer mode); +Bool VidModeLockZoom(int scrnIndex, Bool lock); +Bool VidModeGetMonitor(int scrnIndex, pointer *monitor); +int VidModeGetNumOfClocks(int scrnIndex, Bool *progClock); +Bool VidModeGetClocks(int scrnIndex, int *Clocks); +ModeStatus VidModeCheckModeForMonitor(int scrnIndex, pointer mode); +ModeStatus VidModeCheckModeForDriver(int scrnIndex, pointer mode); +void VidModeSetCrtcForMode(int scrnIndex, pointer mode); +Bool VidModeAddModeline(int scrnIndex, pointer mode); +int VidModeGetDotClock(int scrnIndex, int Clock); +int VidModeGetNumOfModes(int scrnIndex); +Bool VidModeSetGamma(int scrnIndex, float red, float green, float blue); +Bool VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue); +pointer VidModeCreateMode(void); +void VidModeCopyMode(pointer modefrom, pointer modeto); +int VidModeGetModeValue(pointer mode, int valtyp); +void VidModeSetModeValue(pointer mode, int valtyp, int val); +vidMonitorValue VidModeGetMonitorValue(pointer monitor, int valtyp, int indx); +Bool VidModeSetGammaRamp(int, int, CARD16 *, CARD16 *, CARD16 *); +Bool VidModeGetGammaRamp(int, int, CARD16 *, CARD16 *, CARD16 *); +int VidModeGetGammaRampSize(int scrnIndex); + +#endif + + diff --git a/nx-X11/programs/Xserver/Xext/xcmisc.c b/nx-X11/programs/Xserver/Xext/xcmisc.c new file mode 100644 index 000000000..c7bb72d9b --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xcmisc.c @@ -0,0 +1,253 @@ +/* $Xorg: xcmisc.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + +Copyright 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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/xcmisc.c,v 3.7 2003/10/28 23:08:43 tsi Exp $ */ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "swaprep.h" +#include <X11/extensions/xcmiscstr.h> +#include "modinit.h" + +#if HAVE_STDINT_H +#include <stdint.h> +#elif !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +#if 0 +static unsigned char XCMiscCode; +#endif + +static void XCMiscResetProc( + ExtensionEntry * /* extEntry */ +); + +static DISPATCH_PROC(ProcXCMiscDispatch); +static DISPATCH_PROC(ProcXCMiscGetVersion); +static DISPATCH_PROC(ProcXCMiscGetXIDList); +static DISPATCH_PROC(ProcXCMiscGetXIDRange); +static DISPATCH_PROC(SProcXCMiscDispatch); +static DISPATCH_PROC(SProcXCMiscGetVersion); +static DISPATCH_PROC(SProcXCMiscGetXIDList); +static DISPATCH_PROC(SProcXCMiscGetXIDRange); + +void +XCMiscExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XCMiscExtensionName, 0, 0, + ProcXCMiscDispatch, SProcXCMiscDispatch, + XCMiscResetProc, StandardMinorOpcode)) != 0) + XCMiscCode = (unsigned char)extEntry->base; +#else + (void) AddExtension(XCMiscExtensionName, 0, 0, + ProcXCMiscDispatch, SProcXCMiscDispatch, + XCMiscResetProc, StandardMinorOpcode); +#endif + + DeclareExtensionSecurity(XCMiscExtensionName, TRUE); +} + +/*ARGSUSED*/ +static void +XCMiscResetProc (extEntry) + ExtensionEntry *extEntry; +{ +} + +static int +ProcXCMiscGetVersion(client) + register ClientPtr client; +{ + xXCMiscGetVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XCMiscMajorVersion; + rep.minorVersion = XCMiscMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXCMiscGetVersionReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXCMiscGetXIDRange(client) + register ClientPtr client; +{ + xXCMiscGetXIDRangeReply rep; + register int n; + XID min_id, max_id; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq); + GetXIDRange(client->index, FALSE, &min_id, &max_id); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.start_id = min_id; + rep.count = max_id - min_id + 1; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.start_id, n); + swapl(&rep.count, n); + } + WriteToClient(client, sizeof(xXCMiscGetXIDRangeReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXCMiscGetXIDList(client) + register ClientPtr client; +{ + REQUEST(xXCMiscGetXIDListReq); + xXCMiscGetXIDListReply rep; + register int n; + XID *pids; + unsigned int count; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq); + + if (stuff->count > UINT32_MAX / sizeof(XID)) + return BadAlloc; + + pids = (XID *)Xalloc(stuff->count * sizeof(XID)); + if (!pids) + { + return BadAlloc; + } + count = GetXIDList(client, stuff->count, pids); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = count; + rep.count = count; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.count, n); + } + WriteToClient(client, sizeof(xXCMiscGetXIDListReply), (char *)&rep); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, count * sizeof(XID), pids); + } + Xfree(pids); + return(client->noClientException); +} + +static int +ProcXCMiscDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XCMiscGetVersion: + return ProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return ProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return ProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} + +static int +SProcXCMiscGetVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXCMiscGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return ProcXCMiscGetVersion(client); +} + +static int +SProcXCMiscGetXIDRange(client) + register ClientPtr client; +{ + register int n; + REQUEST(xReq); + + swaps(&stuff->length, n); + return ProcXCMiscGetXIDRange(client); +} + +static int +SProcXCMiscGetXIDList(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXCMiscGetXIDListReq); + + swaps(&stuff->length, n); + swapl(&stuff->count, n); + return ProcXCMiscGetXIDList(client); +} + +static int +SProcXCMiscDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XCMiscGetVersion: + return SProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return SProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return SProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} diff --git a/nx-X11/programs/Xserver/Xext/xevie.c b/nx-X11/programs/Xserver/Xext/xevie.c new file mode 100644 index 000000000..3ec6cc4f0 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xevie.c @@ -0,0 +1,719 @@ +/************************************************************ + +Copyright 2003-2005 Sun Microsystems, Inc. + +All rights reserved. + +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, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +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 +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +************************************************************/ +/* $XdotOrg: xc/programs/Xserver/Xext/xevie.c,v 1.11 2005/10/06 17:55:54 alanc Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XEVIE_SERVER_ +#include <X11/extensions/Xeviestr.h> +#include <X11/Xfuncproto.h> +#include "input.h" +#include "inputstr.h" +#include "windowstr.h" +#include "cursorstr.h" +#include <X11/extensions/XKBsrv.h> + +#include "../os/osdep.h" + +#define NoSuchEvent 0x80000000 + +extern Bool noXkbExtension; +extern int xeviegrabState; + +static int ProcDispatch (), SProcDispatch (); +static void ResetProc (); + +static unsigned char ReqCode = 0; +static int ErrorBase; + +int xevieFlag = 0; +int xevieClientIndex = 0; +DeviceIntPtr xeviekb = NULL; +DeviceIntPtr xeviemouse = NULL; +Mask xevieMask = 0; +int xevieEventSent = 0; +int xevieKBEventSent = 0; +static unsigned int xevieServerGeneration; +static int xevieDevicePrivateIndex; +static Bool xevieModifiersOn = FALSE; + +#define XEVIEINFO(dev) ((xevieDeviceInfoPtr)dev->devPrivates[xevieDevicePrivateIndex].ptr) + +Mask xevieFilters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask /* MotionNotify (initial state) */ +}; + +typedef struct { + ProcessInputProc processInputProc; + ProcessInputProc realInputProc; + DeviceUnwrapProc unwrapProc; +} xevieDeviceInfoRec, *xevieDeviceInfoPtr; + +typedef struct { + CARD32 time; + KeyClassPtr keyc; +} xevieKeycQueueRec, *xevieKeycQueuePtr; + +#define KEYC_QUEUE_SIZE 100 +xevieKeycQueueRec keycq[KEYC_QUEUE_SIZE] = {0, NULL}; +static int keycqHead = 0, keycqTail = 0; + +static int ProcDispatch (ClientPtr), SProcDispatch (ClientPtr); +static void ResetProc (ExtensionEntry*); + +static int ErrorBase; + +static Bool XevieStart(void); +static void XevieEnd(int clientIndex); +static void XevieClientStateCallback(CallbackListPtr *pcbl, pointer nulldata, + pointer calldata); +static void XevieServerGrabStateCallback(CallbackListPtr *pcbl, + pointer nulldata, + pointer calldata); + +static Bool XevieAdd(DeviceIntPtr device, pointer data); +static void XevieWrap(DeviceIntPtr device, ProcessInputProc proc); +static Bool XevieRemove(DeviceIntPtr device, pointer data); +static void doSendEvent(xEvent *xE, DeviceIntPtr device); +static void XeviePointerProcessInputProc(xEvent *xE, DeviceIntPtr dev, + int count); +static void XevieKbdProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count); + +void +XevieExtensionInit () +{ + ExtensionEntry* extEntry; + + if (serverGeneration != xevieServerGeneration) { + if ((xevieDevicePrivateIndex = AllocateDevicePrivateIndex()) == -1) + return; + xevieServerGeneration = serverGeneration; + } + + if (!AddCallback(&ServerGrabCallback,XevieServerGrabStateCallback,NULL)) + return; + + if ((extEntry = AddExtension (XEVIENAME, + 0, + XevieNumberErrors, + 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 (xXevieQueryVersionReq); + xXevieQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xXevieQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequence_number = client->sequence; + rep.server_major_version = XEVIE_MAJOR_VERSION; + rep.server_minor_version = XEVIE_MINOR_VERSION; + WriteToClient (client, sizeof (xXevieQueryVersionReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcStart (client) + register ClientPtr client; +{ + REQUEST (xXevieStartReq); + xXevieStartReply rep; + register int n; + + REQUEST_SIZE_MATCH (xXevieStartReq); + rep.pad1 = 0; + + if(!xevieFlag){ + if (AddCallback(&ClientStateCallback,XevieClientStateCallback,NULL)) { + xevieFlag = 1; + rep.pad1 = 1; + xevieClientIndex = client->index; + if(!keycq[0].time ) { + int i; + for(i=0; i<KEYC_QUEUE_SIZE; i++) { + keycq[i].keyc = xalloc(sizeof(KeyClassRec)); + keycq[i].keyc->xkbInfo = xalloc(sizeof(XkbSrvInfoRec)); + } + } + } else + return BadAlloc; + } else + return BadAccess; + if (!noXkbExtension) { + if (!XevieStart()) { + DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL); + return BadAlloc; + } + } + + xevieModifiersOn = FALSE; + + rep.type = X_Reply; + rep.sequence_number = client->sequence; + WriteToClient (client, sizeof (xXevieStartReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcEnd (client) + register ClientPtr client; +{ + xXevieEndReply rep; + + if (xevieFlag) { + if (client->index != xevieClientIndex) + return BadAccess; + + DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL); + XevieEnd(xevieClientIndex); + } + + rep.type = X_Reply; + rep.sequence_number = client->sequence; + WriteToClient (client, sizeof (xXevieEndReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcSend (client) + register ClientPtr client; +{ + REQUEST (xXevieSendReq); + xXevieSendReply rep; + xEvent *xE; + OsCommPtr oc; + static unsigned char lastDetail = 0, lastType = 0; + + if (client->index != xevieClientIndex) + return BadAccess; + + xE = (xEvent *)&stuff->event; + rep.type = X_Reply; + rep.sequence_number = client->sequence; + WriteToClient (client, sizeof (xXevieSendReply), (char *)&rep); + + switch(xE->u.u.type) { + case KeyPress: + case KeyRelease: + xevieKBEventSent = 1; + if(noXkbExtension) + CoreProcessKeyboardEvent (xE, xeviekb, 1); + else + doSendEvent(xE, inputInfo.keyboard); + break; + case ButtonPress: + case ButtonRelease: + case MotionNotify: + xevieEventSent = 1; + if(noXkbExtension) + CoreProcessPointerEvent(xE, xeviemouse, 1); + else + doSendEvent(xE, inputInfo.pointer); + break; + default: + break; + } + lastType = xE->u.u.type; + lastDetail = xE->u.u.detail; + return client->noClientException; +} + +static +int ProcSelectInput (client) + register ClientPtr client; +{ + REQUEST (xXevieSelectInputReq); + xXevieSelectInputReply rep; + + if (client->index != xevieClientIndex) + return BadAccess; + + xevieMask = (long)stuff->event_mask; + rep.type = X_Reply; + rep.sequence_number = client->sequence; + WriteToClient (client, sizeof (xXevieSelectInputReply), (char *)&rep); + return client->noClientException; +} + +static +int ProcDispatch (client) + register ClientPtr client; +{ + REQUEST (xReq); + switch (stuff->data) + { + case X_XevieQueryVersion: + return ProcQueryVersion (client); + case X_XevieStart: + return ProcStart (client); + case X_XevieEnd: + return ProcEnd (client); + case X_XevieSend: + return ProcSend (client); + case X_XevieSelectInput: + return ProcSelectInput(client); + default: + return BadRequest; + } +} + +static +int SProcQueryVersion (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xXevieQueryVersionReq); + swaps(&stuff->length, n); + return ProcQueryVersion(client); +} + +static +int SProcStart (client) + ClientPtr client; +{ + register int n; + + REQUEST (xXevieStartReq); + swaps (&stuff->length, n); + swapl (&stuff->screen, n); + REQUEST_AT_LEAST_SIZE (xXevieStartReq); + return ProcStart (client); +} + +static +int SProcEnd (client) + ClientPtr client; +{ + register int n; + int count; + xColorItem* pItem; + + REQUEST (xXevieEndReq); + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXevieEndReq); + swapl(&stuff->cmap, n); + return ProcEnd (client); +} + +static +int SProcSend (client) + ClientPtr client; +{ + register int n; + int count; + + REQUEST (xXevieSendReq); + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXevieSendReq); + swapl(&stuff->event, n); + return ProcSend (client); +} + +static +int SProcSelectInput (client) + ClientPtr client; +{ + register int n; + int count; + + REQUEST (xXevieSelectInputReq); + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xXevieSendReq); + swapl(&stuff->event_mask, n); + return ProcSelectInput (client); +} + + +static +int SProcDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XevieQueryVersion: + return SProcQueryVersion (client); + case X_XevieStart: + return SProcStart (client); + case X_XevieEnd: + return SProcEnd (client); + case X_XevieSend: + return SProcSend (client); + case X_XevieSelectInput: + return SProcSelectInput(client); + default: + return BadRequest; + } +} +/*======================================================*/ + +#define WRAP_INPUTPROC(dev,store,inputProc) \ + store->processInputProc = dev->public.processInputProc; \ + dev->public.processInputProc = inputProc; \ + store->realInputProc = dev->public.realInputProc; \ + dev->public.realInputProc = inputProc; + +#define COND_WRAP_INPUTPROC(dev,store,inputProc) \ + if (dev->public.processInputProc == dev->public.realInputProc) \ + dev->public.processInputProc = inputProc; \ + store->processInputProc = \ + store->realInputProc = dev->public.realInputProc; \ + dev->public.realInputProc = inputProc; + +#define UNWRAP_INPUTPROC(dev,restore) \ + dev->public.processInputProc = restore->processInputProc; \ + dev->public.realInputProc = restore->realInputProc; + +#define UNWRAP_INPUTPROC(dev,restore) \ + dev->public.processInputProc = restore->processInputProc; \ + dev->public.realInputProc = restore->realInputProc; + +#define XEVIE_EVENT(xE) \ + (xevieFlag \ + && !xeviegrabState \ + && clients[xevieClientIndex] \ + && (xevieMask & xevieFilters[xE->u.u.type])) + + +static void +sendEvent(ClientPtr pClient, xEvent *xE) +{ + if(pClient->swapped) { + xEvent eventTo; + + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[xE->u.u.type & 0177]) (xE, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } else { + (void)WriteToClient(pClient, sizeof(xEvent), (char *) xE); + } +} + +static void +XevieKbdProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count) +{ + int key, bit; + BYTE *kptr; + ProcessInputProc tmp; + KeyClassPtr keyc = dev->key; + xevieDeviceInfoPtr xeviep = XEVIEINFO(dev); + + if(XEVIE_EVENT(xE)) { + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + + if (dev->key->modifierMap[xE->u.u.detail]) + xevieModifiersOn = TRUE; + + xE->u.keyButtonPointer.event = xeviewin->drawable.id; + xE->u.keyButtonPointer.root = GetCurrentRootWindow()->drawable.id; + xE->u.keyButtonPointer.child = (xeviewin->firstChild) + ? xeviewin->firstChild->drawable.id:0; + xE->u.keyButtonPointer.rootX = xeviehot.x; + xE->u.keyButtonPointer.rootY = xeviehot.y; + xE->u.keyButtonPointer.state = keyc->state | inputInfo.pointer->button->state; + /* fix bug: sequence lost in Xlib */ + xE->u.u.sequenceNumber = clients[xevieClientIndex]->sequence; + /* fix for bug5092586 */ + if(!noXkbExtension) { + switch(xE->u.u.type) { + case KeyPress: *kptr |= bit; break; + case KeyRelease: *kptr &= ~bit; break; + } + } + keycq[keycqHead].time = xE->u.keyButtonPointer.time; + memcpy(keycq[keycqHead].keyc, keyc, sizeof(KeyClassRec) - sizeof(KeyClassPtr)); + memcpy(keycq[keycqHead].keyc->xkbInfo, keyc->xkbInfo, sizeof(XkbSrvInfoRec)); + if(++keycqHead >=KEYC_QUEUE_SIZE) + keycqHead = 0; + sendEvent(clients[xevieClientIndex], xE); + return; + } + + tmp = dev->public.realInputProc; + UNWRAP_INPUTPROC(dev,xeviep); + dev->public.processInputProc(xE,dev,count); + COND_WRAP_INPUTPROC(dev,xeviep,tmp); +} + +static void +XeviePointerProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count) +{ + xevieDeviceInfoPtr xeviep = XEVIEINFO(dev); + ProcessInputProc tmp; + + if (XEVIE_EVENT(xE)) { + /* fix bug: sequence lost in Xlib */ + xE->u.u.sequenceNumber = clients[xevieClientIndex]->sequence; + sendEvent(clients[xevieClientIndex], xE); + return; + } + + tmp = dev->public.realInputProc; + UNWRAP_INPUTPROC(dev,xeviep); + dev->public.processInputProc(xE,dev,count); + COND_WRAP_INPUTPROC(dev,xeviep,tmp); +} + +static Bool +XevieStart(void) +{ + ProcessInputProc prp; + prp = XevieKbdProcessInputProc; + if (!XevieAdd(inputInfo.keyboard,&prp)) + return FALSE; + prp = XeviePointerProcessInputProc; + if (!XevieAdd(inputInfo.pointer,&prp)) + return FALSE; + + return TRUE; +} + + +static void +XevieEnd(int clientIndex) +{ + if (!clientIndex || clientIndex == xevieClientIndex) { + + if(!noXkbExtension) { + + XevieRemove(inputInfo.keyboard,NULL); + + inputInfo.keyboard->public.processInputProc = CoreProcessKeyboardEvent; + inputInfo.keyboard->public.realInputProc = CoreProcessKeyboardEvent; + XkbSetExtension(inputInfo.keyboard,ProcessKeyboardEvent); + + + XevieRemove(inputInfo.pointer,NULL); + + inputInfo.pointer->public.processInputProc = CoreProcessPointerEvent; + inputInfo.pointer->public.realInputProc = CoreProcessPointerEvent; + XkbSetExtension(inputInfo.pointer,ProcessPointerEvent); + } + + xevieFlag = 0; + xevieClientIndex = 0; + DeleteCallback (&ClientStateCallback, XevieClientStateCallback, NULL); + } +} + +static void +XevieClientStateCallback(CallbackListPtr *pcbl, pointer nulldata, + pointer calldata) +{ + NewClientInfoRec *pci = (NewClientInfoRec *)calldata; + ClientPtr client = pci->client; + if (client->clientState == ClientStateGone + || client->clientState == ClientStateRetained) + XevieEnd(client->index); +} + +static void +XevieServerGrabStateCallback(CallbackListPtr *pcbl, pointer nulldata, + pointer calldata) +{ + ServerGrabInfoRec *grbinfo = (ServerGrabInfoRec *)calldata; + if (grbinfo->grabstate == SERVER_GRABBED) + xeviegrabState = TRUE; + else + xeviegrabState = FALSE; +} + +#define UNWRAP_UNWRAPPROC(device,proc_store) \ + device->unwrapProc = proc_store; + +#define WRAP_UNWRAPPROC(device,proc_store,proc) \ + proc_store = device->unwrapProc; \ + device->unwrapProc = proc; + +static void +xevieUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, pointer data) +{ + xevieDeviceInfoPtr xeviep = XEVIEINFO(device); + ProcessInputProc tmp = device->public.processInputProc; + + UNWRAP_INPUTPROC(device,xeviep); + UNWRAP_UNWRAPPROC(device,xeviep->unwrapProc); + proc(device,data); + WRAP_INPUTPROC(device,xeviep,tmp); + WRAP_UNWRAPPROC(device,xeviep->unwrapProc,xevieUnwrapProc); +} + +static Bool +XevieUnwrapAdd(DeviceIntPtr device, void* data) +{ + if (device->unwrapProc) + device->unwrapProc(device,XevieUnwrapAdd,data); + else { + ProcessInputProc *ptr = data; + XevieWrap(device,*ptr); + } + + return TRUE; +} + +static Bool +XevieAdd(DeviceIntPtr device, void* data) +{ + xevieDeviceInfoPtr xeviep; + + if (!AllocateDevicePrivate(device, xevieDevicePrivateIndex)) + return FALSE; + + xeviep = xalloc (sizeof (xevieDeviceInfoRec)); + if (!xeviep) + return FALSE; + + device->devPrivates[xevieDevicePrivateIndex].ptr = xeviep; + XevieUnwrapAdd(device, data); + + return TRUE; +} + +static Bool +XevieRemove(DeviceIntPtr device,pointer data) +{ + xevieDeviceInfoPtr xeviep = XEVIEINFO(device); + + if (!xeviep) return TRUE; + + UNWRAP_INPUTPROC(device,xeviep); + UNWRAP_UNWRAPPROC(device,xeviep->unwrapProc); + + xfree(xeviep); + device->devPrivates[xevieDevicePrivateIndex].ptr = NULL; + return TRUE; +} + +static void +XevieWrap(DeviceIntPtr device, ProcessInputProc proc) +{ + xevieDeviceInfoPtr xeviep = XEVIEINFO(device); + + WRAP_INPUTPROC(device,xeviep,proc); + WRAP_UNWRAPPROC(device,xeviep->unwrapProc,xevieUnwrapProc); +} + +static void +doSendEvent(xEvent *xE, DeviceIntPtr dev) +{ + xevieDeviceInfoPtr xeviep = XEVIEINFO(dev); + ProcessInputProc tmp = dev->public.realInputProc; + if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease)) + && !xevieModifiersOn) { + KeyClassPtr keyc = dev->key; + CARD8 realModes = dev->key->modifierMap[xE->u.u.detail]; + int notFound = 0; + /* if some events are consumed by client, move the queue tail pointer to the current + event which just comes back from Xevie client . + */ + if(keycq[keycqTail].time != xE->u.keyButtonPointer.time) { + while(keycq[keycqTail].time != xE->u.keyButtonPointer.time) { + if(++keycqTail >= KEYC_QUEUE_SIZE) + keycqTail = 0; + if(keycqTail == keycqHead) { + notFound = 1; + break; + } + } + } + if(!notFound) { + dev->key = keycq[keycqTail].keyc; + if(++keycqTail >= KEYC_QUEUE_SIZE) + keycqTail = 0; + } + dev->key->modifierMap[xE->u.u.detail] = 0; + + if(dev->key->xkbInfo->repeatKey != 0 && xE->u.u.type != KeyPress) + XkbLastRepeatEvent= (pointer)xE; + UNWRAP_INPUTPROC(dev,xeviep); + dev->public.processInputProc(xE,dev,1); + COND_WRAP_INPUTPROC(dev,xeviep,tmp); + XkbLastRepeatEvent= NULL; + + dev->key->modifierMap[xE->u.u.detail] = realModes; + dev->key = keyc; + if(notFound) { + DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL); + XevieEnd(xevieClientIndex); + ErrorF("Error: Xevie keyc queue size is not enough, disable Xevie\n"); + } + } else { + UNWRAP_INPUTPROC(dev,xeviep); + dev->public.processInputProc(xE,dev,1); + COND_WRAP_INPUTPROC(dev,xeviep,tmp); + } +} + diff --git a/nx-X11/programs/Xserver/Xext/xf86bigfont.c b/nx-X11/programs/Xserver/Xext/xf86bigfont.c new file mode 100644 index 000000000..36af17622 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xf86bigfont.c @@ -0,0 +1,790 @@ +/* $XFree86: xc/programs/Xserver/Xext/xf86bigfont.c,v 1.17 2003/10/28 23:08:43 tsi Exp $ */ +/* + * BIGFONT extension for sharing font metrics between clients (if possible) + * and for transmitting font metrics to clients in a compressed form. + * + * Copyright (c) 1999-2000 Bruno Haible + * Copyright (c) 1999-2000 The XFree86 Project, Inc. + */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +/* + * Big fonts suffer from the following: All clients that have opened a + * font can access the complete glyph metrics array (the XFontStruct member + * `per_char') directly, without going through a macro. Moreover these + * glyph metrics are ink metrics, i.e. are not redundant even for a + * fixed-width font. For a Unicode font, the size of this array is 768 KB. + * + * Problems: 1. It eats a lot of memory in each client. 2. All this glyph + * metrics data is piped through the socket when the font is opened. + * + * This extension addresses these two problems for local clients, by using + * shared memory. It also addresses the second problem for non-local clients, + * by compressing the data before transmit by a factor of nearly 6. + * + * If you use this extension, your OS ought to nicely support shared memory. + * This means: Shared memory should be swappable to the swap, and the limits + * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB, + * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls + * on segments that have already been marked "removed", because it permits + * these segments to be cleaned up by the OS if the X server is killed with + * signal SIGKILL. + * + * This extension is transparently exploited by Xlib (functions XQueryFont, + * XLoadQueryFont). + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <sys/types.h> +#ifdef HAS_SHM +#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2) +/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */ +/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers): + Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define + PAGE_SIZE. It is defined in <asm/page.h>. */ +#include <asm/page.h> +#endif +#ifdef SVR4 +#include <sys/sysmacros.h> +#endif +#if defined(ISC) || defined(__CYGWIN__) || defined(__SCO__) +#include <sys/param.h> +#include <sys/sysmacros.h> +#endif +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <errno.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "dixfontstr.h" +#include "extnsionst.h" + +#define _XF86BIGFONT_SERVER_ +#include <X11/extensions/xf86bigfstr.h> + +static void XF86BigfontResetProc( + ExtensionEntry * /* extEntry */ + ); + +static DISPATCH_PROC(ProcXF86BigfontDispatch); +static DISPATCH_PROC(ProcXF86BigfontQueryVersion); +static DISPATCH_PROC(ProcXF86BigfontQueryFont); +static DISPATCH_PROC(SProcXF86BigfontDispatch); +static DISPATCH_PROC(SProcXF86BigfontQueryVersion); +static DISPATCH_PROC(SProcXF86BigfontQueryFont); + +#if 0 +static unsigned char XF86BigfontReqCode; +#endif + +#ifdef HAS_SHM + +/* A random signature, transmitted to the clients so they can verify that the + shared memory segment they are attaching to was really established by the + X server they are talking to. */ +static CARD32 signature; + +/* Index for additional information stored in a FontRec's devPrivates array. */ +static int FontShmdescIndex; + +static unsigned int pagesize; + +static Bool badSysCall = FALSE; + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) + +#include <sys/signal.h> + +static void +SigSysHandler( + int signo) +{ + badSysCall = TRUE; +} + +static Bool +CheckForShmSyscall(void) +{ + void (*oldHandler)(int); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + if (shmid != -1) + { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + else + { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return (!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + +#endif + +void +XFree86BigfontExtensionInit() +{ +#if 0 + ExtensionEntry* extEntry; + + if ((extEntry = AddExtension(XF86BIGFONTNAME, + XF86BigfontNumberEvents, + XF86BigfontNumberErrors, + ProcXF86BigfontDispatch, + SProcXF86BigfontDispatch, + XF86BigfontResetProc, + StandardMinorOpcode))) { + XF86BigfontReqCode = (unsigned char) extEntry->base; +#else + if (AddExtension(XF86BIGFONTNAME, + XF86BigfontNumberEvents, + XF86BigfontNumberErrors, + ProcXF86BigfontDispatch, + SProcXF86BigfontDispatch, + XF86BigfontResetProc, + StandardMinorOpcode)) { +#endif +#ifdef HAS_SHM +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + /* + * Note: Local-clients will not be optimized without shared memory + * support. Remote-client optimization does not depend on shared + * memory support. Thus, the extension is still registered even + * when shared memory support is not functional. + */ + if (!CheckForShmSyscall()) { + ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n"); + return; + } +#endif + + srand((unsigned int) time(NULL)); + signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16) + + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand()); + /* fprintf(stderr, "signature = 0x%08X\n", signature); */ + + FontShmdescIndex = AllocateFontPrivateIndex(); + +#if !defined(CSRG_BASED) && !defined(__CYGWIN__) + pagesize = SHMLBA; +#else +# ifdef _SC_PAGESIZE + pagesize = sysconf(_SC_PAGESIZE); +# else + pagesize = getpagesize(); +# endif +#endif +#endif + } +} + + +/* ========== Management of shared memory segments ========== */ + +#ifdef HAS_SHM + +#ifdef __linux__ +/* On Linux, shared memory marked as "removed" can still be attached. + Nice feature, because the kernel will automatically free the associated + storage when the server and all clients are gone. */ +#define EARLY_REMOVE +#endif + +typedef struct _ShmDesc { + struct _ShmDesc *next; + struct _ShmDesc **prev; + int shmid; + char *attach_addr; +} ShmDescRec, *ShmDescPtr; + +static ShmDescPtr ShmList = (ShmDescPtr) NULL; + +static ShmDescPtr +shmalloc( + unsigned int size) +{ + ShmDescPtr pDesc; + int shmid; + char *addr; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (pagesize == 0) + return (ShmDescPtr) NULL; +#endif + + /* On some older Linux systems, the number of shared memory segments + system-wide is 127. In Linux 2.4, it is 4095. + Therefore there is a tradeoff to be made between allocating a + shared memory segment on one hand, and allocating memory and piping + the glyph metrics on the other hand. If the glyph metrics size is + small, we prefer the traditional way. */ + if (size < 3500) + return (ShmDescPtr) NULL; + + pDesc = (ShmDescRec *) xalloc(sizeof(ShmDescRec)); + if (!pDesc) + return (ShmDescPtr) NULL; + + size = (size + pagesize-1) & -pagesize; + shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + if (shmid == -1) { + ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, errno = %d\n", + size, errno); + xfree(pDesc); + return (ShmDescPtr) NULL; + } + + if ((addr = shmat(shmid, 0, 0)) == (char *)-1) { + ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, errno = %d\n", + size, errno); + shmctl(shmid, IPC_RMID, (void *) 0); + xfree(pDesc); + return (ShmDescPtr) NULL; + } + +#ifdef EARLY_REMOVE + shmctl(shmid, IPC_RMID, (void *) 0); +#endif + + pDesc->shmid = shmid; + pDesc->attach_addr = addr; + if (ShmList) ShmList->prev = &pDesc->next; + pDesc->next = ShmList; + pDesc->prev = &ShmList; + ShmList = pDesc; + + return pDesc; +} + +static void +shmdealloc( + ShmDescPtr pDesc) +{ +#ifndef EARLY_REMOVE + shmctl(pDesc->shmid, IPC_RMID, (void *) 0); +#endif + shmdt(pDesc->attach_addr); + + if (pDesc->next) pDesc->next->prev = pDesc->prev; + *pDesc->prev = pDesc->next; + xfree(pDesc); +} + +#endif + +/* Called when a font is closed. */ +void +XF86BigfontFreeFontShm( + FontPtr pFont) +{ +#ifdef HAS_SHM + ShmDescPtr pDesc; + + /* If during shutdown of the server, XF86BigfontCleanup() has already + * called shmdealloc() for all segments, we don't need to do it here. + */ + if (!ShmList) + return; + + pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); + if (pDesc) + shmdealloc(pDesc); +#endif +} + +/* Called upon fatal signal. */ +void +XF86BigfontCleanup() +{ +#ifdef HAS_SHM + while (ShmList) + shmdealloc(ShmList); +#endif +} + +/* Called when a server generation dies. */ +static void +XF86BigfontResetProc( + ExtensionEntry* extEntry) +{ + /* This function is normally called from CloseDownExtensions(), called + * from main(). It will be followed by a call to FreeAllResources(), + * which will call XF86BigfontFreeFontShm() for each font. Thus it + * appears that we do not need to do anything in this function. -- + * But I prefer to write robust code, and not keep shared memory lying + * around when it's not needed any more. (Someone might close down the + * extension without calling FreeAllResources()...) + */ + XF86BigfontCleanup(); +} + + +/* ========== Handling of extension specific requests ========== */ + +static int +ProcXF86BigfontQueryVersion( + ClientPtr client) +{ + xXF86BigfontQueryVersionReply reply; + + REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.majorVersion = XF86BIGFONT_MAJOR_VERSION; + reply.minorVersion = XF86BIGFONT_MINOR_VERSION; + reply.uid = geteuid(); + reply.gid = getegid(); +#ifdef HAS_SHM + reply.signature = signature; +#else + reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */ +#endif + reply.capabilities = +#ifdef HAS_SHM + (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) +#else + 0 +#endif + ; /* may add more bits here in future versions */ + if (client->swapped) { + char tmp; + swaps(&reply.sequenceNumber, tmp); + swapl(&reply.length, tmp); + swaps(&reply.majorVersion, tmp); + swaps(&reply.minorVersion, tmp); + swapl(&reply.uid, tmp); + swapl(&reply.gid, tmp); + swapl(&reply.signature, tmp); + } + WriteToClient(client, + sizeof(xXF86BigfontQueryVersionReply), (char *)&reply); + return client->noClientException; +} + +static void +swapCharInfo( + xCharInfo *pCI) +{ + char tmp; + + swaps(&pCI->leftSideBearing, tmp); + swaps(&pCI->rightSideBearing, tmp); + swaps(&pCI->characterWidth, tmp); + swaps(&pCI->ascent, tmp); + swaps(&pCI->descent, tmp); + swaps(&pCI->attributes, tmp); +} + +/* static CARD32 hashCI (xCharInfo *p); */ +#define hashCI(p) \ + (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \ + (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \ + (p->characterWidth << 16) + \ + (p->ascent << 11) + (p->descent << 6)) ^ p->attributes) + +static int +ProcXF86BigfontQueryFont( + ClientPtr client) +{ + FontPtr pFont; + REQUEST(xXF86BigfontQueryFontReq); + CARD32 stuff_flags; + xCharInfo* pmax; + xCharInfo* pmin; + int nCharInfos; + int shmid; +#ifdef HAS_SHM + ShmDescPtr pDesc; +#else +#define pDesc 0 +#endif + xCharInfo* pCI; + CARD16* pIndex2UniqIndex; + CARD16* pUniqIndex2Index; + CARD32 nUniqCharInfos; + +#if 0 + REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); +#else + switch (client->req_len) { + case 2: /* client with version 1.0 libX11 */ + stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); + break; + case 3: /* client with version 1.1 libX11 */ + stuff_flags = stuff->flags; + break; + default: + return BadLength; + } +#endif + client->errorValue = stuff->id; /* EITHER font or gc */ + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) { + /* can't use VERIFY_GC because it might return BadGC */ + GC *pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) { + client->errorValue = stuff->id; + return BadFont; /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + + pmax = FONTINKMAX(pFont); + pmin = FONTINKMIN(pFont); + nCharInfos = + (pmax->rightSideBearing == pmin->rightSideBearing + && pmax->leftSideBearing == pmin->leftSideBearing + && pmax->descent == pmin->descent + && pmax->ascent == pmin->ascent + && pmax->characterWidth == pmin->characterWidth) + ? 0 : N2dChars(pFont); + shmid = -1; + pCI = NULL; + pIndex2UniqIndex = NULL; + pUniqIndex2Index = NULL; + nUniqCharInfos = 0; + + if (nCharInfos > 0) { +#ifdef HAS_SHM + if (!badSysCall) + pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); + else + pDesc = NULL; + if (pDesc) { + pCI = (xCharInfo *) pDesc->attach_addr; + if (stuff_flags & XF86Bigfont_FLAGS_Shm) + shmid = pDesc->shmid; + } else { + if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall) + pDesc = shmalloc(nCharInfos * sizeof(xCharInfo) + + sizeof(CARD32)); + if (pDesc) { + pCI = (xCharInfo *) pDesc->attach_addr; + shmid = pDesc->shmid; + } else { +#endif + pCI = (xCharInfo *) + ALLOCATE_LOCAL(nCharInfos * sizeof(xCharInfo)); + if (!pCI) + return BadAlloc; +#ifdef HAS_SHM + } +#endif + /* Fill nCharInfos starting at pCI. */ + { + xCharInfo* prCI = pCI; + int ninfos = 0; + int ncols = pFont->info.lastCol - pFont->info.firstCol + 1; + int row; + for (row = pFont->info.firstRow; + row <= pFont->info.lastRow && ninfos < nCharInfos; + row++) { + unsigned char chars[512]; + xCharInfo* tmpCharInfos[256]; + unsigned long count; + int col; + unsigned long i; + i = 0; + for (col = pFont->info.firstCol; + col <= pFont->info.lastCol; + col++) { + chars[i++] = row; + chars[i++] = col; + } + (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit, + &count, tmpCharInfos); + for (i = 0; i < count && ninfos < nCharInfos; i++) { + *prCI++ = *tmpCharInfos[i]; + ninfos++; + } + } + } +#ifdef HAS_SHM + if (pDesc && !badSysCall) { + *(CARD32 *)(pCI + nCharInfos) = signature; + if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) { + shmdealloc(pDesc); + return BadAlloc; + } + } + } +#endif + if (shmid == -1) { + /* Cannot use shared memory, so remove-duplicates the xCharInfos + using a temporary hash table. */ + /* Note that CARD16 is suitable as index type, because + nCharInfos <= 0x10000. */ + CARD32 hashModulus; + CARD16* pHash2UniqIndex; + CARD16* pUniqIndex2NextUniqIndex; + CARD32 NextIndex; + CARD32 NextUniqIndex; + CARD16* tmp; + CARD32 i, j; + + hashModulus = 67; + if (hashModulus > nCharInfos+1) + hashModulus = nCharInfos+1; + + tmp = (CARD16*) + ALLOCATE_LOCAL((4*nCharInfos+1) * sizeof(CARD16)); + if (!tmp) { + if (!pDesc) DEALLOCATE_LOCAL(pCI); + return BadAlloc; + } + pIndex2UniqIndex = tmp; + /* nCharInfos elements */ + pUniqIndex2Index = tmp + nCharInfos; + /* max. nCharInfos elements */ + pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos; + /* max. nCharInfos elements */ + pHash2UniqIndex = tmp + 3*nCharInfos; + /* hashModulus (<= nCharInfos+1) elements */ + + /* Note that we can use 0xffff as end-of-list indicator, because + even if nCharInfos = 0x10000, 0xffff can not occur as valid + entry before the last element has been inserted. And once the + last element has been inserted, we don't need the hash table + any more. */ + for (j = 0; j < hashModulus; j++) + pHash2UniqIndex[j] = (CARD16)(-1); + + NextUniqIndex = 0; + for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) { + xCharInfo* p = &pCI[NextIndex]; + CARD32 hashCode = hashCI(p) % hashModulus; + for (i = pHash2UniqIndex[hashCode]; + i != (CARD16)(-1); + i = pUniqIndex2NextUniqIndex[i]) { + j = pUniqIndex2Index[i]; + if (pCI[j].leftSideBearing == p->leftSideBearing + && pCI[j].rightSideBearing == p->rightSideBearing + && pCI[j].characterWidth == p->characterWidth + && pCI[j].ascent == p->ascent + && pCI[j].descent == p->descent + && pCI[j].attributes == p->attributes) + break; + } + if (i != (CARD16)(-1)) { + /* Found *p at Index j, UniqIndex i */ + pIndex2UniqIndex[NextIndex] = i; + } else { + /* Allocate a new entry in the Uniq table */ + if (hashModulus <= 2*NextUniqIndex + && hashModulus < nCharInfos+1) { + /* Time to increate hash table size */ + hashModulus = 2*hashModulus+1; + if (hashModulus > nCharInfos+1) + hashModulus = nCharInfos+1; + for (j = 0; j < hashModulus; j++) + pHash2UniqIndex[j] = (CARD16)(-1); + for (i = 0; i < NextUniqIndex; i++) + pUniqIndex2NextUniqIndex[i] = (CARD16)(-1); + for (i = 0; i < NextUniqIndex; i++) { + j = pUniqIndex2Index[i]; + p = &pCI[j]; + hashCode = hashCI(p) % hashModulus; + pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; + pHash2UniqIndex[hashCode] = i; + } + p = &pCI[NextIndex]; + hashCode = hashCI(p) % hashModulus; + } + i = NextUniqIndex++; + pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; + pHash2UniqIndex[hashCode] = i; + pUniqIndex2Index[i] = NextIndex; + pIndex2UniqIndex[NextIndex] = i; + } + } + nUniqCharInfos = NextUniqIndex; + /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */ + } + } + + { + int nfontprops = pFont->info.nprops; + int rlength = + sizeof(xXF86BigfontQueryFontReply) + + nfontprops * sizeof(xFontProp) + + (nCharInfos > 0 && shmid == -1 + ? nUniqCharInfos * sizeof(xCharInfo) + + (nCharInfos+1)/2 * 2 * sizeof(CARD16) + : 0); + xXF86BigfontQueryFontReply* reply = + (xXF86BigfontQueryFontReply *) ALLOCATE_LOCAL(rlength); + char* p; + if (!reply) { + if (nCharInfos > 0) { + if (shmid == -1) DEALLOCATE_LOCAL(pIndex2UniqIndex); + if (!pDesc) DEALLOCATE_LOCAL(pCI); + } + return BadAlloc; + } + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + reply->minBounds = pFont->info.ink_minbounds; + reply->maxBounds = pFont->info.ink_maxbounds; + reply->minCharOrByte2 = pFont->info.firstCol; + reply->maxCharOrByte2 = pFont->info.lastCol; + reply->defaultChar = pFont->info.defaultCh; + reply->nFontProps = pFont->info.nprops; + reply->drawDirection = pFont->info.drawDirection; + reply->minByte1 = pFont->info.firstRow; + reply->maxByte1 = pFont->info.lastRow; + reply->allCharsExist = pFont->info.allExist; + reply->fontAscent = pFont->info.fontAscent; + reply->fontDescent = pFont->info.fontDescent; + reply->nCharInfos = nCharInfos; + reply->nUniqCharInfos = nUniqCharInfos; + reply->shmid = shmid; + reply->shmsegoffset = 0; + if (client->swapped) { + char tmp; + swaps(&reply->sequenceNumber, tmp); + swapl(&reply->length, tmp); + swapCharInfo(&reply->minBounds); + swapCharInfo(&reply->maxBounds); + swaps(&reply->minCharOrByte2, tmp); + swaps(&reply->maxCharOrByte2, tmp); + swaps(&reply->defaultChar, tmp); + swaps(&reply->nFontProps, tmp); + swaps(&reply->fontAscent, tmp); + swaps(&reply->fontDescent, tmp); + swapl(&reply->nCharInfos, tmp); + swapl(&reply->nUniqCharInfos, tmp); + swapl(&reply->shmid, tmp); + swapl(&reply->shmsegoffset, tmp); + } + p = (char*) &reply[1]; + { + FontPropPtr pFP; + xFontProp* prFP; + int i; + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p; + i < nfontprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + if (client->swapped) { + char tmp; + swapl(&prFP->name, tmp); + swapl(&prFP->value, tmp); + } + } + p = (char*) prFP; + } + if (nCharInfos > 0 && shmid == -1) { + xCharInfo* pci; + CARD16* ps; + int i, j; + pci = (xCharInfo*) p; + for (i = 0; i < nUniqCharInfos; i++, pci++) { + *pci = pCI[pUniqIndex2Index[i]]; + if (client->swapped) + swapCharInfo(pci); + } + ps = (CARD16*) pci; + for (j = 0; j < nCharInfos; j++, ps++) { + *ps = pIndex2UniqIndex[j]; + if (client->swapped) { + char tmp; + swaps(ps, tmp); + } + } + } + WriteToClient(client, rlength, (char *)reply); + DEALLOCATE_LOCAL(reply); + if (nCharInfos > 0) { + if (shmid == -1) DEALLOCATE_LOCAL(pIndex2UniqIndex); + if (!pDesc) DEALLOCATE_LOCAL(pCI); + } + return (client->noClientException); + } +} + +static int +ProcXF86BigfontDispatch( + ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_XF86BigfontQueryVersion: + return ProcXF86BigfontQueryVersion(client); + case X_XF86BigfontQueryFont: + return ProcXF86BigfontQueryFont(client); + default: + return BadRequest; + } +} + +static int +SProcXF86BigfontQueryVersion( + ClientPtr client) +{ + REQUEST(xXF86BigfontQueryVersionReq); + char tmp; + + swaps(&stuff->length, tmp); + return ProcXF86BigfontQueryVersion(client); +} + +static int +SProcXF86BigfontQueryFont( + ClientPtr client) +{ + REQUEST(xXF86BigfontQueryFontReq); + char tmp; + + swaps(&stuff->length, tmp); + REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); + swapl(&stuff->id, tmp); + return ProcXF86BigfontQueryFont(client); +} + +static int +SProcXF86BigfontDispatch( + ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_XF86BigfontQueryVersion: + return SProcXF86BigfontQueryVersion(client); + case X_XF86BigfontQueryFont: + return SProcXF86BigfontQueryFont(client); + default: + return BadRequest; + } +} diff --git a/nx-X11/programs/Xserver/Xext/xf86dga.c b/nx-X11/programs/Xserver/Xext/xf86dga.c new file mode 100644 index 000000000..9979bfb30 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xf86dga.c @@ -0,0 +1,307 @@ +/* $XFree86: xc/programs/Xserver/Xext/xf86dga.c,v 3.21 2000/06/30 19:06:54 keithp Exp $ */ + +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995, 1996, 1999 XFree86 Inc + +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XF86DGA_SERVER_ +#include <X11/extensions/xf86dga.h> +#include <X11/extensions/xf86dgastr.h> +#include "swaprep.h" +#include "dgaproc.h" + +#include "xf86dgaext.h" + + +static DISPATCH_PROC(ProcXF86DGADirectVideo); +static DISPATCH_PROC(ProcXF86DGAGetVidPage); +static DISPATCH_PROC(ProcXF86DGAGetVideoLL); +static DISPATCH_PROC(ProcXF86DGAGetViewPortSize); +static DISPATCH_PROC(ProcXF86DGASetVidPage); +static DISPATCH_PROC(ProcXF86DGASetViewPort); +static DISPATCH_PROC(ProcXF86DGAInstallColormap); +static DISPATCH_PROC(ProcXF86DGAQueryDirectVideo); +static DISPATCH_PROC(ProcXF86DGAViewPortChanged); + + +static int +ProcXF86DGAGetVideoLL(ClientPtr client) +{ + REQUEST(xXF86DGAGetVideoLLReq); + xXF86DGAGetVideoLLReply rep; + XDGAModeRec mode; + int num, offset, flags; + char *name; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetVideoLLReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if(!DGAAvailable(stuff->screen)) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + if(!(num = DGAGetOldDGAMode(stuff->screen))) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + /* get the parameters for the mode that best matches */ + DGAGetModeInfo(stuff->screen, &mode, num); + + if(!DGAOpenFramebuffer(stuff->screen, &name, + (unsigned char**)(&rep.offset), + (int*)(&rep.bank_size), &offset, &flags)) + return BadAlloc; + + rep.offset += mode.offset; + rep.width = mode.bytesPerScanline / (mode.bitsPerPixel >> 3); + rep.ram_size = rep.bank_size >> 10; + + WriteToClient(client, SIZEOF(xXF86DGAGetVideoLLReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DGADirectVideo(ClientPtr client) +{ + int num; + PixmapPtr pix; + XDGAModeRec mode; + REQUEST(xXF86DGADirectVideoReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGADirectVideoReq); + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (stuff->enable & XF86DGADirectGraphics) { + if(!(num = DGAGetOldDGAMode(stuff->screen))) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + } else + num = 0; + + if(Success != DGASetMode(stuff->screen, num, &mode, &pix)) + return (DGAErrorBase + XF86DGAScreenNotActive); + + DGASetInputMode (stuff->screen, + (stuff->enable & XF86DGADirectKeyb) != 0, + (stuff->enable & XF86DGADirectMouse) != 0); + + return (client->noClientException); +} + +static int +ProcXF86DGAGetViewPortSize(ClientPtr client) +{ + int num; + XDGAModeRec mode; + REQUEST(xXF86DGAGetViewPortSizeReq); + xXF86DGAGetViewPortSizeReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetViewPortSizeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + if(!(num = DGAGetOldDGAMode(stuff->screen))) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + DGAGetModeInfo(stuff->screen, &mode, num); + + rep.width = mode.viewportWidth; + rep.height = mode.viewportHeight; + + WriteToClient(client, SIZEOF(xXF86DGAGetViewPortSizeReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DGASetViewPort(ClientPtr client) +{ + REQUEST(xXF86DGASetViewPortReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGASetViewPortReq); + + if (!DGAActive(stuff->screen)) + { + int num; + PixmapPtr pix; + XDGAModeRec mode; + + if(!(num = DGAGetOldDGAMode(stuff->screen))) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + if(Success != DGASetMode(stuff->screen, num, &mode, &pix)) + return (DGAErrorBase + XF86DGAScreenNotActive); + } + + if (DGASetViewport(stuff->screen, stuff->x, stuff->y, DGA_FLIP_RETRACE) + != Success) + return DGAErrorBase + XF86DGADirectNotActivated; + + return (client->noClientException); +} + +static int +ProcXF86DGAGetVidPage(ClientPtr client) +{ + REQUEST(xXF86DGAGetVidPageReq); + xXF86DGAGetVidPageReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetVidPageReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.vpage = 0; /* silently fail */ + + WriteToClient(client, SIZEOF(xXF86DGAGetVidPageReply), (char *)&rep); + return (client->noClientException); +} + + +static int +ProcXF86DGASetVidPage(ClientPtr client) +{ + REQUEST(xXF86DGASetVidPageReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGASetVidPageReq); + + /* silently fail */ + + return (client->noClientException); +} + + +static int +ProcXF86DGAInstallColormap(ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xXF86DGAInstallColormapReq); + + REQUEST_SIZE_MATCH(xXF86DGAInstallColormapReq); + + if (!DGAActive(stuff->screen)) + return (DGAErrorBase + XF86DGADirectNotActivated); + + pcmp = (ColormapPtr )LookupIDByType(stuff->id, RT_COLORMAP); + if (pcmp) { + DGAInstallCmap(pcmp); + return (client->noClientException); + } else { + client->errorValue = stuff->id; + return (BadColor); + } +} + +static int +ProcXF86DGAQueryDirectVideo(ClientPtr client) +{ + REQUEST(xXF86DGAQueryDirectVideoReq); + xXF86DGAQueryDirectVideoReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAQueryDirectVideoReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.flags = 0; + + if (DGAAvailable(stuff->screen)) + rep.flags = XF86DGADirectPresent; + + WriteToClient(client, SIZEOF(xXF86DGAQueryDirectVideoReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DGAViewPortChanged(ClientPtr client) +{ + REQUEST(xXF86DGAViewPortChangedReq); + xXF86DGAViewPortChangedReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAViewPortChangedReq); + + if (!DGAActive(stuff->screen)) + return (DGAErrorBase + XF86DGADirectNotActivated); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.result = 1; + + WriteToClient(client, SIZEOF(xXF86DGAViewPortChangedReply), (char *)&rep); + return (client->noClientException); +} + +int +ProcXF86DGADispatch(register ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_XF86DGAGetVideoLL: + return ProcXF86DGAGetVideoLL(client); + case X_XF86DGADirectVideo: + return ProcXF86DGADirectVideo(client); + case X_XF86DGAGetViewPortSize: + return ProcXF86DGAGetViewPortSize(client); + case X_XF86DGASetViewPort: + return ProcXF86DGASetViewPort(client); + case X_XF86DGAGetVidPage: + return ProcXF86DGAGetVidPage(client); + case X_XF86DGASetVidPage: + return ProcXF86DGASetVidPage(client); + case X_XF86DGAInstallColormap: + return ProcXF86DGAInstallColormap(client); + case X_XF86DGAQueryDirectVideo: + return ProcXF86DGAQueryDirectVideo(client); + case X_XF86DGAViewPortChanged: + return ProcXF86DGAViewPortChanged(client); + default: + return BadRequest; + } +} + diff --git a/nx-X11/programs/Xserver/Xext/xf86dga2.c b/nx-X11/programs/Xserver/Xext/xf86dga2.c new file mode 100644 index 000000000..a5cab0f11 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xf86dga2.c @@ -0,0 +1,775 @@ +/* + Copyright (c) 1999 - The XFree86 Project Inc. + + Written by Mark Vojkovich +*/ +/* $XFree86: xc/programs/Xserver/Xext/xf86dga2.c,v 1.17 2001/10/28 03:32:51 tsi Exp $ */ + + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "dixevents.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XF86DGA_SERVER_ +#include <X11/extensions/xf86dga.h> +#include <X11/extensions/xf86dgastr.h> +#include "swaprep.h" +#include "dgaproc.h" +#include "xf86dgaext.h" + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#else +#include <string.h> +#endif + +#include "modinit.h" + +static DISPATCH_PROC(ProcXDGADispatch); +static DISPATCH_PROC(SProcXDGADispatch); +static DISPATCH_PROC(ProcXDGAQueryVersion); +static DISPATCH_PROC(ProcXDGAQueryModes); +static DISPATCH_PROC(ProcXDGASetMode); +static DISPATCH_PROC(ProcXDGAOpenFramebuffer); +static DISPATCH_PROC(ProcXDGACloseFramebuffer); +static DISPATCH_PROC(ProcXDGASetViewport); +static DISPATCH_PROC(ProcXDGAInstallColormap); +static DISPATCH_PROC(ProcXDGASelectInput); +static DISPATCH_PROC(ProcXDGAFillRectangle); +static DISPATCH_PROC(ProcXDGACopyArea); +static DISPATCH_PROC(ProcXDGACopyTransparentArea); +static DISPATCH_PROC(ProcXDGAGetViewportStatus); +static DISPATCH_PROC(ProcXDGASync); +static DISPATCH_PROC(ProcXDGASetClientVersion); +static DISPATCH_PROC(ProcXDGAChangePixmapMode); +static DISPATCH_PROC(ProcXDGACreateColormap); + +static void XDGAResetProc(ExtensionEntry *extEntry); + +static void DGAClientStateChange (CallbackListPtr*, pointer, pointer); + +static ClientPtr DGAClients[MAXSCREENS]; + +unsigned char DGAReqCode = 0; +int DGAErrorBase; +int DGAEventBase; + +static int DGAGeneration = 0; +static int DGAClientPrivateIndex; +static int DGACallbackRefCount = 0; + +/* This holds the client's version information */ +typedef struct { + int major; + int minor; +} DGAPrivRec, *DGAPrivPtr; + +#define DGAPRIV(c) ((c)->devPrivates[DGAClientPrivateIndex].ptr) + +void +XFree86DGAExtensionInit(INITARGS) +{ + ExtensionEntry* extEntry; + + if ((extEntry = AddExtension(XF86DGANAME, + XF86DGANumberEvents, + XF86DGANumberErrors, + ProcXDGADispatch, + SProcXDGADispatch, + XDGAResetProc, + StandardMinorOpcode))) { + int i; + + for(i = 0; i < MAXSCREENS; i++) + DGAClients[i] = NULL; + + DGAReqCode = (unsigned char)extEntry->base; + DGAErrorBase = extEntry->errorBase; + DGAEventBase = extEntry->eventBase; + for (i = KeyPress; i <= MotionNotify; i++) + SetCriticalEvent (DGAEventBase + i); + } + + /* + * Allocate a client private index to hold the client's version + * information. + */ + if (DGAGeneration != serverGeneration) { + DGAClientPrivateIndex = AllocateClientPrivateIndex(); + /* + * Allocate 0 length, and use the private to hold a pointer to + * our DGAPrivRec. + */ + if (!AllocateClientPrivate(DGAClientPrivateIndex, 0)) { + ErrorF("XFree86DGAExtensionInit: AllocateClientPrivate failed\n"); + return; + } + DGAGeneration = serverGeneration; + } +} + + + +static void +XDGAResetProc (ExtensionEntry *extEntry) +{ + DeleteCallback (&ClientStateCallback, DGAClientStateChange, NULL); + DGACallbackRefCount = 0; +} + + +static int +ProcXDGAQueryVersion(ClientPtr client) +{ + xXDGAQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xXDGAQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XDGA_MAJOR_VERSION; + rep.minorVersion = XDGA_MINOR_VERSION; + + WriteToClient(client, sizeof(xXDGAQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +static int +ProcXDGAOpenFramebuffer(ClientPtr client) +{ + REQUEST(xXDGAOpenFramebufferReq); + xXDGAOpenFramebufferReply rep; + char *deviceName; + int nameSize; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + REQUEST_SIZE_MATCH(xXDGAOpenFramebufferReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if(!DGAOpenFramebuffer(stuff->screen, &deviceName, + (unsigned char**)(&rep.mem1), + (int*)&rep.size, (int*)&rep.offset, (int*)&rep.extra)) + { + return BadAlloc; + } + + nameSize = deviceName ? (strlen(deviceName) + 1) : 0; + rep.length = (nameSize + 3) >> 2; + + WriteToClient(client, sizeof(xXDGAOpenFramebufferReply), (char *)&rep); + if(rep.length) + WriteToClient(client, nameSize, deviceName); + + return (client->noClientException); +} + + +static int +ProcXDGACloseFramebuffer(ClientPtr client) +{ + REQUEST(xXDGACloseFramebufferReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + REQUEST_SIZE_MATCH(xXDGACloseFramebufferReq); + + DGACloseFramebuffer(stuff->screen); + + return (client->noClientException); +} + +static int +ProcXDGAQueryModes(ClientPtr client) +{ + int i, num, size; + REQUEST(xXDGAQueryModesReq); + xXDGAQueryModesReply rep; + xXDGAModeInfo info; + XDGAModePtr mode; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXDGAQueryModesReq); + rep.type = X_Reply; + rep.length = 0; + rep.number = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) { + rep.number = 0; + rep.length = 0; + WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); + return (client->noClientException); + } + + if(!(num = DGAGetModes(stuff->screen))) { + WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); + return (client->noClientException); + } + + if(!(mode = (XDGAModePtr)xalloc(num * sizeof(XDGAModeRec)))) + return BadAlloc; + + for(i = 0; i < num; i++) + DGAGetModeInfo(stuff->screen, mode + i, i + 1); + + size = num * sz_xXDGAModeInfo; + for(i = 0; i < num; i++) + size += (strlen(mode[i].name) + 4) & ~3L; /* plus NULL */ + + rep.number = num; + rep.length = size >> 2; + + WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); + + for(i = 0; i < num; i++) { + size = strlen(mode[i].name) + 1; + + info.byte_order = mode[i].byteOrder; + info.depth = mode[i].depth; + info.num = mode[i].num; + info.bpp = mode[i].bitsPerPixel; + info.name_size = (size + 3) & ~3L; + info.vsync_num = mode[i].VSync_num; + info.vsync_den = mode[i].VSync_den; + info.flags = mode[i].flags; + info.image_width = mode[i].imageWidth; + info.image_height = mode[i].imageHeight; + info.pixmap_width = mode[i].pixmapWidth; + info.pixmap_height = mode[i].pixmapHeight; + info.bytes_per_scanline = mode[i].bytesPerScanline; + info.red_mask = mode[i].red_mask; + info.green_mask = mode[i].green_mask; + info.blue_mask = mode[i].blue_mask; + info.visual_class = mode[i].visualClass; + info.viewport_width = mode[i].viewportWidth; + info.viewport_height = mode[i].viewportHeight; + info.viewport_xstep = mode[i].xViewportStep; + info.viewport_ystep = mode[i].yViewportStep; + info.viewport_xmax = mode[i].maxViewportX; + info.viewport_ymax = mode[i].maxViewportY; + info.viewport_flags = mode[i].viewportFlags; + info.reserved1 = mode[i].reserved1; + info.reserved2 = mode[i].reserved2; + + WriteToClient(client, sz_xXDGAModeInfo, (char*)(&info)); + WriteToClient(client, size, mode[i].name); + } + + xfree(mode); + + return (client->noClientException); +} + + +static void +DGAClientStateChange ( + CallbackListPtr* pcbl, + pointer nulldata, + pointer calldata +){ + NewClientInfoRec* pci = (NewClientInfoRec*) calldata; + ClientPtr client = NULL; + int i; + + for(i = 0; i < screenInfo.numScreens; i++) { + if(DGAClients[i] == pci->client) { + client = pci->client; + break; + } + } + + if(client && + ((client->clientState == ClientStateGone) || + (client->clientState == ClientStateRetained))) { + XDGAModeRec mode; + PixmapPtr pPix; + + DGAClients[i] = NULL; + DGASelectInput(i, NULL, 0); + DGASetMode(i, 0, &mode, &pPix); + + if(--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } +} + +static int +ProcXDGASetMode(ClientPtr client) +{ + REQUEST(xXDGASetModeReq); + xXDGASetModeReply rep; + XDGAModeRec mode; + xXDGAModeInfo info; + PixmapPtr pPix; + int size; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXDGASetModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.offset = 0; + rep.flags = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if(DGAClients[stuff->screen] && + (DGAClients[stuff->screen] != client)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if(!stuff->mode) { + if(DGAClients[stuff->screen]) { + if(--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } + DGAClients[stuff->screen] = NULL; + DGASelectInput(stuff->screen, NULL, 0); + DGASetMode(stuff->screen, 0, &mode, &pPix); + WriteToClient(client, sz_xXDGASetModeReply, (char*)&rep); + return (client->noClientException); + } + + if(Success != DGASetMode(stuff->screen, stuff->mode, &mode, &pPix)) + return BadValue; + + if(!DGAClients[stuff->screen]) { + if(DGACallbackRefCount++ == 0) + AddCallback (&ClientStateCallback, DGAClientStateChange, NULL); + } + + DGAClients[stuff->screen] = client; + + if(pPix) { + if(AddResource(stuff->pid, RT_PIXMAP, (pointer)(pPix))) { + pPix->drawable.id = (int)stuff->pid; + rep.flags = DGA_PIXMAP_AVAILABLE; + } + } + + size = strlen(mode.name) + 1; + + info.byte_order = mode.byteOrder; + info.depth = mode.depth; + info.num = mode.num; + info.bpp = mode.bitsPerPixel; + info.name_size = (size + 3) & ~3L; + info.vsync_num = mode.VSync_num; + info.vsync_den = mode.VSync_den; + info.flags = mode.flags; + info.image_width = mode.imageWidth; + info.image_height = mode.imageHeight; + info.pixmap_width = mode.pixmapWidth; + info.pixmap_height = mode.pixmapHeight; + info.bytes_per_scanline = mode.bytesPerScanline; + info.red_mask = mode.red_mask; + info.green_mask = mode.green_mask; + info.blue_mask = mode.blue_mask; + info.visual_class = mode.visualClass; + info.viewport_width = mode.viewportWidth; + info.viewport_height = mode.viewportHeight; + info.viewport_xstep = mode.xViewportStep; + info.viewport_ystep = mode.yViewportStep; + info.viewport_xmax = mode.maxViewportX; + info.viewport_ymax = mode.maxViewportY; + info.viewport_flags = mode.viewportFlags; + info.reserved1 = mode.reserved1; + info.reserved2 = mode.reserved2; + + rep.length = (sz_xXDGAModeInfo + info.name_size) >> 2; + + WriteToClient(client, sz_xXDGASetModeReply, (char*)&rep); + WriteToClient(client, sz_xXDGAModeInfo, (char*)(&info)); + WriteToClient(client, size, mode.name); + + return (client->noClientException); +} + +static int +ProcXDGASetViewport(ClientPtr client) +{ + REQUEST(xXDGASetViewportReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASetViewportReq); + + DGASetViewport(stuff->screen, stuff->x, stuff->y, stuff->flags); + + return (client->noClientException); +} + +static int +ProcXDGAInstallColormap(ClientPtr client) +{ + ColormapPtr cmap; + REQUEST(xXDGAInstallColormapReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAInstallColormapReq); + + cmap = (ColormapPtr)LookupIDByType(stuff->cmap, RT_COLORMAP); + if (cmap) { + DGAInstallCmap(cmap); + return (client->noClientException); + } else { + client->errorValue = stuff->cmap; + return (BadColor); + } + + return (client->noClientException); +} + + +static int +ProcXDGASelectInput(ClientPtr client) +{ + REQUEST(xXDGASelectInputReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASelectInputReq); + + if(DGAClients[stuff->screen] == client) + DGASelectInput(stuff->screen, client, stuff->mask); + + return (client->noClientException); +} + + +static int +ProcXDGAFillRectangle(ClientPtr client) +{ + REQUEST(xXDGAFillRectangleReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAFillRectangleReq); + + if(Success != DGAFillRect(stuff->screen, stuff->x, stuff->y, + stuff->width, stuff->height, stuff->color)) + return BadMatch; + + return (client->noClientException); +} + +static int +ProcXDGACopyArea(ClientPtr client) +{ + REQUEST(xXDGACopyAreaReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACopyAreaReq); + + if(Success != DGABlitRect(stuff->screen, stuff->srcx, stuff->srcy, + stuff->width, stuff->height, stuff->dstx, stuff->dsty)) + return BadMatch; + + return (client->noClientException); +} + + +static int +ProcXDGACopyTransparentArea(ClientPtr client) +{ + REQUEST(xXDGACopyTransparentAreaReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACopyTransparentAreaReq); + + if(Success != DGABlitTransRect(stuff->screen, stuff->srcx, stuff->srcy, + stuff->width, stuff->height, stuff->dstx, stuff->dsty, stuff->key)) + return BadMatch; + + return (client->noClientException); +} + + +static int +ProcXDGAGetViewportStatus(ClientPtr client) +{ + REQUEST(xXDGAGetViewportStatusReq); + xXDGAGetViewportStatusReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAGetViewportStatusReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.status = DGAGetViewportStatus(stuff->screen); + + WriteToClient(client, sizeof(xXDGAGetViewportStatusReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXDGASync(ClientPtr client) +{ + REQUEST(xXDGASyncReq); + xXDGASyncReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASyncReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + DGASync(stuff->screen); + + WriteToClient(client, sizeof(xXDGASyncReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXDGASetClientVersion(ClientPtr client) +{ + REQUEST(xXDGASetClientVersionReq); + + DGAPrivPtr pPriv; + + REQUEST_SIZE_MATCH(xXDGASetClientVersionReq); + if ((pPriv = DGAPRIV(client)) == NULL) { + pPriv = xalloc(sizeof(DGAPrivRec)); + /* XXX Need to look into freeing this */ + if (!pPriv) + return BadAlloc; + DGAPRIV(client) = pPriv; + } + pPriv->major = stuff->major; + pPriv->minor = stuff->minor; + + return (client->noClientException); +} + +static int +ProcXDGAChangePixmapMode(ClientPtr client) +{ + REQUEST(xXDGAChangePixmapModeReq); + xXDGAChangePixmapModeReply rep; + int x, y; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAChangePixmapModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + x = stuff->x; + y = stuff->y; + + if(!DGAChangePixmapMode(stuff->screen, &x, &y, stuff->flags)) + return BadMatch; + + rep.x = x; + rep.y = y; + WriteToClient(client, sizeof(xXDGAChangePixmapModeReply), (char *)&rep); + + return (client->noClientException); +} + + +static int +ProcXDGACreateColormap(ClientPtr client) +{ + REQUEST(xXDGACreateColormapReq); + int result; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGAClients[stuff->screen] != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACreateColormapReq); + + if(!stuff->mode) + return BadValue; + + result = DGACreateColormap(stuff->screen, client, stuff->id, + stuff->mode, stuff->alloc); + if(result != Success) + return result; + + return (client->noClientException); +} + + +static int +SProcXDGADispatch (ClientPtr client) +{ + return DGAErrorBase + XF86DGAClientNotLocal; +} + +#if 0 +#define DGA_REQ_DEBUG +#endif + +#ifdef DGA_REQ_DEBUG +static char *dgaMinor[] = { + "QueryVersion", + "GetVideoLL", + "DirectVideo", + "GetViewPortSize", + "SetViewPort", + "GetVidPage", + "SetVidPage", + "InstallColormap", + "QueryDirectVideo", + "ViewPortChanged", + "10", + "11", + "QueryModes", + "SetMode", + "SetViewport", + "InstallColormap", + "SelectInput", + "FillRectangle", + "CopyArea", + "CopyTransparentArea", + "GetViewportStatus", + "Sync", + "OpenFramebuffer", + "CloseFramebuffer", + "SetClientVersion", + "ChangePixmapMode", + "CreateColormap", +}; +#endif + +static int +ProcXDGADispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (!LocalClient(client)) + return DGAErrorBase + XF86DGAClientNotLocal; + +#ifdef DGA_REQ_DEBUG + if (stuff->data <= X_XDGACreateColormap) + fprintf (stderr, " DGA %s\n", dgaMinor[stuff->data]); +#endif + + /* divert old protocol */ +#if 1 + if( (stuff->data <= X_XF86DGAViewPortChanged) && + (stuff->data >= X_XF86DGAGetVideoLL)) + return ProcXF86DGADispatch(client); +#endif + + switch (stuff->data){ + case X_XDGAQueryVersion: + return ProcXDGAQueryVersion(client); + case X_XDGAQueryModes: + return ProcXDGAQueryModes(client); + case X_XDGASetMode: + return ProcXDGASetMode(client); + case X_XDGAOpenFramebuffer: + return ProcXDGAOpenFramebuffer(client); + case X_XDGACloseFramebuffer: + return ProcXDGACloseFramebuffer(client); + case X_XDGASetViewport: + return ProcXDGASetViewport(client); + case X_XDGAInstallColormap: + return ProcXDGAInstallColormap(client); + case X_XDGASelectInput: + return ProcXDGASelectInput(client); + case X_XDGAFillRectangle: + return ProcXDGAFillRectangle(client); + case X_XDGACopyArea: + return ProcXDGACopyArea(client); + case X_XDGACopyTransparentArea: + return ProcXDGACopyTransparentArea(client); + case X_XDGAGetViewportStatus: + return ProcXDGAGetViewportStatus(client); + case X_XDGASync: + return ProcXDGASync(client); + case X_XDGASetClientVersion: + return ProcXDGASetClientVersion(client); + case X_XDGAChangePixmapMode: + return ProcXDGAChangePixmapMode(client); + case X_XDGACreateColormap: + return ProcXDGACreateColormap(client); + default: + return BadRequest; + } +} + +#ifdef EXTMODULE +void +XFree86DGARegister(INITARGS) +{ + XDGAEventBase = &DGAEventBase; +} +#endif diff --git a/nx-X11/programs/Xserver/Xext/xf86dgaext.h b/nx-X11/programs/Xserver/Xext/xf86dgaext.h new file mode 100644 index 000000000..16fc4c8b2 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xf86dgaext.h @@ -0,0 +1,12 @@ +/* $XFree86$ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _XF86DGAEXT_H_ +#define _XF86DGAEXT_H_ + +extern DISPATCH_PROC(ProcXF86DGADispatch); + +#endif /* _XF86DGAEXT_H_ */ diff --git a/nx-X11/programs/Xserver/Xext/xf86misc.c b/nx-X11/programs/Xserver/Xext/xf86misc.c new file mode 100644 index 000000000..a5dc2e212 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xf86misc.c @@ -0,0 +1,854 @@ +/* $XFree86: xc/programs/Xserver/Xext/xf86misc.c,v 3.41 2003/11/17 22:20:27 dawes Exp $ */ + +/* + * Copyright (c) 1995, 1996 The XFree86 Project, Inc + */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "inputstr.h" +#include "servermd.h" +#define _XF86MISC_SERVER_ +#undef _XF86MISC_SAVER_COMPAT_ +#include <X11/extensions/xf86mscstr.h> +#include "swaprep.h" +#include "xf86.h" +#include <X11/Xfuncproto.h> +#include "xf86miscproc.h" + +#if 0 +#include <X11/Xtrans/Xtrans.h> +#include "../os/osdep.h" +#include <X11/Xauth.h> +#ifndef USL +#ifndef Lynx +#include <sys/socket.h> +#else +#include <socket.h> +#endif +#endif /* USL */ +#endif + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +static int miscErrorBase; +static int MiscGeneration = 0; +static int MiscClientPrivateIndex; + +/* This holds the client's version information */ +typedef struct { + int major; + int minor; +} MiscPrivRec, *MiscPrivPtr; + +#define MPRIV(c) ((c)->devPrivates[MiscClientPrivateIndex].ptr) + +static void XF86MiscResetProc( + ExtensionEntry* /* extEntry */ +); + +static void +ClientVersion(ClientPtr client, int *major, int *minor) +{ + MiscPrivPtr pPriv; + + pPriv = MPRIV(client); + if (!pPriv) { + if (major) *major = 0; + if (minor) *minor = 0; + return; + } + + if (major) *major = pPriv->major; + if (minor) *minor = pPriv->minor; +} + +static DISPATCH_PROC(ProcXF86MiscDispatch); +static DISPATCH_PROC(ProcXF86MiscQueryVersion); +static DISPATCH_PROC(ProcXF86MiscGetKbdSettings); +static DISPATCH_PROC(ProcXF86MiscGetMouseSettings); +static DISPATCH_PROC(ProcXF86MiscSetKbdSettings); +static DISPATCH_PROC(ProcXF86MiscSetMouseSettings); +static DISPATCH_PROC(ProcXF86MiscSetGrabKeysState); +static DISPATCH_PROC(ProcXF86MiscSetClientVersion); +static DISPATCH_PROC(ProcXF86MiscGetFilePaths); +static DISPATCH_PROC(ProcXF86MiscPassMessage); +#ifdef _XF86MISC_SAVER_COMPAT_ +static DISPATCH_PROC(ProcXF86MiscGetSaver); +static DISPATCH_PROC(ProcXF86MiscSetSaver); +#endif +static DISPATCH_PROC(SProcXF86MiscDispatch); +static DISPATCH_PROC(SProcXF86MiscQueryVersion); +static DISPATCH_PROC(SProcXF86MiscGetKbdSettings); +static DISPATCH_PROC(SProcXF86MiscGetMouseSettings); +static DISPATCH_PROC(SProcXF86MiscSetKbdSettings); +static DISPATCH_PROC(SProcXF86MiscSetMouseSettings); +static DISPATCH_PROC(SProcXF86MiscSetGrabKeysState); +static DISPATCH_PROC(SProcXF86MiscSetClientVersion); +static DISPATCH_PROC(SProcXF86MiscGetFilePaths); +static DISPATCH_PROC(SProcXF86MiscPassMessage); +#ifdef _XF86MISC_SAVER_COMPAT_ +static DISPATCH_PROC(SProcXF86MiscGetSaver); +static DISPATCH_PROC(SProcXF86MiscSetSaver); +#endif + +#if 0 +static unsigned char XF86MiscReqCode = 0; +#endif + +#ifdef DEBUG +# define DEBUG_P(x) ErrorF(x"\n"); +#else +# define DEBUG_P(x) /**/ +#endif + +#define MISCERR(x) (miscErrorBase + x) + +void +XFree86MiscExtensionInit(void) +{ + ExtensionEntry* extEntry; + + DEBUG_P("XFree86MiscExtensionInit"); + + if (!xf86GetModInDevEnabled()) + return; + + /* + * Allocate a client private index to hold the client's version + * information. + */ + if (MiscGeneration != serverGeneration) { + MiscClientPrivateIndex = AllocateClientPrivateIndex(); + /* + * Allocate 0 length, and use the private to hold a pointer to our + * MiscPrivRec. + */ + if (!AllocateClientPrivate(MiscClientPrivateIndex, 0)) { + ErrorF("XFree86MiscExtensionInit: " + "AllocateClientPrivate failed\n"); + return; + } + MiscGeneration = serverGeneration; + } + + if ( + (extEntry = AddExtension(XF86MISCNAME, + XF86MiscNumberEvents, + XF86MiscNumberErrors, + ProcXF86MiscDispatch, + SProcXF86MiscDispatch, + XF86MiscResetProc, + StandardMinorOpcode))) { +#if 0 + XF86MiscReqCode = (unsigned char)extEntry->base; +#endif + miscErrorBase = extEntry->errorBase; + } +} + +/*ARGSUSED*/ +static void +XF86MiscResetProc (extEntry) + ExtensionEntry* extEntry; +{ +} + +static int +ProcXF86MiscQueryVersion(client) + register ClientPtr client; +{ + xXF86MiscQueryVersionReply rep; + register int n; + + DEBUG_P("XF86MiscQueryVersion"); + + REQUEST_SIZE_MATCH(xXF86MiscQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XF86MISC_MAJOR_VERSION; + rep.minorVersion = XF86MISC_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXF86MiscQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#ifdef _XF86MISC_SAVER_COMPAT_ +/* THESE HAVE NOT BEEN CONVERTED TO THE NEW DESIGN */ + +/* + * This will go away, but remains for now for compatibility with older + * clients. + */ +static int +ProcXF86MiscSetSaver(client) + register ClientPtr client; +{ + REQUEST(xXF86MiscSetSaverReq); + ScrnInfoPtr vptr; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + + REQUEST_SIZE_MATCH(xXF86MiscSetSaverReq); + + if (stuff->suspendTime < 0) + return BadValue; + if (stuff->offTime < 0) + return BadValue; + + return (client->noClientException); +} + +/* + * This will go away, but remains for now for compatibility with older + * clients. + */ +static int +ProcXF86MiscGetSaver(client) + register ClientPtr client; +{ + REQUEST(xXF86MiscGetSaverReq); + xXF86MiscGetSaverReply rep; + register int n; + ScrnInfoPtr vptr; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + vptr = (ScrnInfoPtr) screenInfo.screens[stuff->screen]->devPrivates[xf86ScreenIndex].ptr; + + REQUEST_SIZE_MATCH(xXF86MiscGetSaverReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.suspendTime = 0; + rep.offTime = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.suspendTime, n); + swapl(&rep.offTime, n); + } + WriteToClient(client, SIZEOF(xXF86MiscGetSaverReply), (char *)&rep); + return (client->noClientException); +} + +#endif /* _XF86MISC_SAVER_COMPAT_ */ + +static int +ProcXF86MiscGetMouseSettings(client) + register ClientPtr client; +{ + xXF86MiscGetMouseSettingsReply rep; + char *devname; + pointer mouse; + register int n; + + DEBUG_P("XF86MiscGetMouseSettings"); + + REQUEST_SIZE_MATCH(xXF86MiscGetMouseSettingsReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + + if (!MiscExtGetMouseSettings(&mouse, &devname)) + return BadValue; + + rep.mousetype = MiscExtGetMouseValue(mouse, MISC_MSE_PROTO); + rep.baudrate = MiscExtGetMouseValue(mouse, MISC_MSE_BAUDRATE); + rep.samplerate = MiscExtGetMouseValue(mouse, MISC_MSE_SAMPLERATE); + rep.resolution = MiscExtGetMouseValue(mouse, MISC_MSE_RESOLUTION); + rep.buttons = MiscExtGetMouseValue(mouse, MISC_MSE_BUTTONS); + rep.emulate3buttons = MiscExtGetMouseValue(mouse, MISC_MSE_EM3BUTTONS); + rep.emulate3timeout = MiscExtGetMouseValue(mouse, MISC_MSE_EM3TIMEOUT); + rep.chordmiddle = MiscExtGetMouseValue(mouse, MISC_MSE_CHORDMIDDLE); + rep.flags = MiscExtGetMouseValue(mouse, MISC_MSE_FLAGS); + rep.devnamelen = (devname? strlen(devname): 0); + rep.length = (sizeof(xXF86MiscGetMouseSettingsReply) - + sizeof(xGenericReply) + ((rep.devnamelen+3) & ~3)) >> 2; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.mousetype, n); + swapl(&rep.baudrate, n); + swapl(&rep.samplerate, n); + swapl(&rep.resolution, n); + swapl(&rep.buttons, n); + swapl(&rep.emulate3buttons, n); + swapl(&rep.emulate3timeout, n); + swapl(&rep.chordmiddle, n); + swapl(&rep.flags, n); + } + WriteToClient(client, SIZEOF(xXF86MiscGetMouseSettingsReply), (char *)&rep); + MiscExtDestroyStruct(mouse, MISC_POINTER); + + if (rep.devnamelen) + WriteToClient(client, rep.devnamelen, devname); + return (client->noClientException); +} + +static int +ProcXF86MiscGetKbdSettings(client) + register ClientPtr client; +{ + xXF86MiscGetKbdSettingsReply rep; + pointer kbd; + register int n; + + DEBUG_P("XF86MiscGetKbdSettings"); + + REQUEST_SIZE_MATCH(xXF86MiscGetKbdSettingsReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!MiscExtGetKbdSettings(&kbd)) + return BadValue; + + rep.kbdtype = MiscExtGetKbdValue(kbd, MISC_KBD_TYPE); + rep.rate = MiscExtGetKbdValue(kbd, MISC_KBD_RATE); + rep.delay = MiscExtGetKbdValue(kbd, MISC_KBD_DELAY); + rep.servnumlock = MiscExtGetKbdValue(kbd, MISC_KBD_SERVNUMLOCK); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.kbdtype, n); + swapl(&rep.rate, n); + swapl(&rep.delay, n); + } + WriteToClient(client, SIZEOF(xXF86MiscGetKbdSettingsReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86MiscSetMouseSettings(client) + register ClientPtr client; +{ + MiscExtReturn ret; + pointer mouse; + char *devname = NULL; + int major, minor; + + REQUEST(xXF86MiscSetMouseSettingsReq); + + DEBUG_P("XF86MiscSetMouseSettings"); + + REQUEST_AT_LEAST_SIZE(xXF86MiscSetMouseSettingsReq); + + ClientVersion(client, &major, &minor); + + if (xf86GetVerbosity() > 1) { + ErrorF("SetMouseSettings - type: %d brate: %d srate: %d chdmid: %d\n", + (int)stuff->mousetype, (int)stuff->baudrate, + (int)stuff->samplerate, stuff->chordmiddle); + ErrorF(" em3but: %d em3tim: %d res: %d flags: %ld\n", + stuff->emulate3buttons, (int)stuff->emulate3timeout, + (int)stuff->resolution, (unsigned long)stuff->flags); + } + + if ((mouse = MiscExtCreateStruct(MISC_POINTER)) == (pointer) 0) + return BadAlloc; + + MiscExtSetMouseValue(mouse, MISC_MSE_PROTO, stuff->mousetype); + MiscExtSetMouseValue(mouse, MISC_MSE_BAUDRATE, stuff->baudrate); + MiscExtSetMouseValue(mouse, MISC_MSE_SAMPLERATE, stuff->samplerate); + MiscExtSetMouseValue(mouse, MISC_MSE_RESOLUTION, stuff->resolution); + MiscExtSetMouseValue(mouse, MISC_MSE_BUTTONS, stuff->buttons); + MiscExtSetMouseValue(mouse, MISC_MSE_EM3BUTTONS, stuff->emulate3buttons); + MiscExtSetMouseValue(mouse, MISC_MSE_EM3TIMEOUT, stuff->emulate3timeout); + MiscExtSetMouseValue(mouse, MISC_MSE_CHORDMIDDLE, stuff->chordmiddle); + MiscExtSetMouseValue(mouse, MISC_MSE_FLAGS, stuff->flags); + + if ((major > 0 || minor > 5) && stuff->devnamelen) { + int size = sizeof(xXF86MiscSetMouseSettingsReq) + stuff->devnamelen; + size = (size + 3) >> 2; + if (client->req_len < size) + return BadLength; + if (stuff->devnamelen) { + if (!(devname = xalloc(stuff->devnamelen))) + return BadAlloc; + strncpy(devname,(char*)(&stuff[1]),stuff->devnamelen); + if (xf86GetVerbosity() > 1) + ErrorF("SetMouseSettings - device: %s\n",devname); + MiscExtSetMouseDevice(mouse, devname); + } + } + + ret = MiscExtApply(mouse, MISC_POINTER); + + if (devname) + xfree(devname); + + switch ((ret)) { + case MISC_RET_SUCCESS: break; + case MISC_RET_BADVAL: return BadValue; + case MISC_RET_BADMSEPROTO: return MISCERR(XF86MiscBadMouseProtocol); + case MISC_RET_BADBAUDRATE: return MISCERR(XF86MiscBadMouseBaudRate); + case MISC_RET_BADFLAGS: return MISCERR(XF86MiscBadMouseFlags); + case MISC_RET_BADCOMBO: return MISCERR(XF86MiscBadMouseCombo); + case MISC_RET_NOMODULE: return MISCERR(XF86MiscNoModule); + default: + ErrorF("Unexpected return from MiscExtApply(POINTER) = %d\n", ret); + return BadImplementation; + } + + if (xf86GetVerbosity() > 1) + ErrorF("SetMouseSettings - Succeeded\n"); + return (client->noClientException); +} + +static int +ProcXF86MiscSetKbdSettings(client) + register ClientPtr client; +{ + MiscExtReturn ret; + pointer kbd; + REQUEST(xXF86MiscSetKbdSettingsReq); + + DEBUG_P("XF86MiscSetKbdSettings"); + + REQUEST_SIZE_MATCH(xXF86MiscSetKbdSettingsReq); + + if (xf86GetVerbosity() > 1) + ErrorF("SetKbdSettings - type: %d rate: %d delay: %d snumlk: %d\n", + (int)stuff->kbdtype, (int)stuff->rate, + (int)stuff->delay, stuff->servnumlock); + + if ((kbd = MiscExtCreateStruct(MISC_KEYBOARD)) == (pointer) 0) + return BadAlloc; + + MiscExtSetKbdValue(kbd, MISC_KBD_TYPE, stuff->kbdtype); + MiscExtSetKbdValue(kbd, MISC_KBD_RATE, stuff->rate); + MiscExtSetKbdValue(kbd, MISC_KBD_DELAY, stuff->delay); + MiscExtSetKbdValue(kbd, MISC_KBD_SERVNUMLOCK, stuff->servnumlock); + + switch ((ret = MiscExtApply(kbd, MISC_KEYBOARD))) { + case MISC_RET_SUCCESS: break; + case MISC_RET_BADVAL: return BadValue; + case MISC_RET_BADKBDTYPE: return MISCERR(XF86MiscBadKbdType); + default: + ErrorF("Unexpected return from MiscExtApply(KEYBOARD) = %d\n", ret); + return BadImplementation; + } + + if (xf86GetVerbosity() > 1) + ErrorF("SetKbdSettings - Succeeded\n"); + return (client->noClientException); +} + +static int +ProcXF86MiscSetGrabKeysState(client) + register ClientPtr client; +{ + int n, status; + xXF86MiscSetGrabKeysStateReply rep; + REQUEST(xXF86MiscSetGrabKeysStateReq); + + DEBUG_P("XF86MiscSetGrabKeysState"); + + REQUEST_SIZE_MATCH(xXF86MiscSetGrabKeysStateReq); + + if ((status = MiscExtSetGrabKeysState(client, stuff->enable)) == 0) { + if (xf86GetVerbosity() > 1) + ErrorF("SetGrabKeysState - %s\n", + stuff->enable ? "enabled" : "disabled"); + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.status = status; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, SIZEOF(xXF86MiscSetGrabKeysStateReply), (char *)&rep); + + return (client->noClientException); +} + +static int +ProcXF86MiscSetClientVersion(ClientPtr client) +{ + REQUEST(xXF86MiscSetClientVersionReq); + + MiscPrivPtr pPriv; + + DEBUG_P("XF86MiscSetClientVersion"); + + REQUEST_SIZE_MATCH(xXF86MiscSetClientVersionReq); + + if ((pPriv = MPRIV(client)) == NULL) { + pPriv = xalloc(sizeof(MiscPrivRec)); + if (!pPriv) + return BadAlloc; + MPRIV(client) = pPriv; + } + ErrorF("SetClientVersion: %i %i\n",stuff->major,stuff->minor); + pPriv->major = stuff->major; + pPriv->minor = stuff->minor; + + return (client->noClientException); +} + +static int +ProcXF86MiscGetFilePaths(client) + register ClientPtr client; +{ + xXF86MiscGetFilePathsReply rep; + const char *configfile; + const char *modulepath; + const char *logfile; + register int n; + + DEBUG_P("XF86MiscGetFilePaths"); + + REQUEST_SIZE_MATCH(xXF86MiscGetFilePathsReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + + if (!MiscExtGetFilePaths(&configfile, &modulepath, &logfile)) + return BadValue; + + rep.configlen = (configfile? strlen(configfile): 0); + rep.modulelen = (modulepath? strlen(modulepath): 0); + rep.loglen = (logfile? strlen(logfile): 0); + rep.length = (SIZEOF(xXF86MiscGetFilePathsReply) - SIZEOF(xGenericReply) + + ((rep.configlen + 3) & ~3) + + ((rep.modulelen + 3) & ~3) + + ((rep.loglen + 3) & ~3) ) >> 2; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.configlen, n); + swaps(&rep.modulelen, n); + swaps(&rep.loglen, n); + } + WriteToClient(client, SIZEOF(xXF86MiscGetFilePathsReply), (char *)&rep); + + if (rep.configlen) + WriteToClient(client, rep.configlen, (char *)configfile); + if (rep.modulelen) + WriteToClient(client, rep.modulelen, (char *)modulepath); + if (rep.loglen) + WriteToClient(client, rep.loglen, (char *)logfile); + + return (client->noClientException); +} + +static int +ProcXF86MiscPassMessage(client) + register ClientPtr client; +{ + xXF86MiscPassMessageReply rep; + char *msgtype, *msgval, *retstr; + int retval, size; + register int n; + + REQUEST(xXF86MiscPassMessageReq); + + DEBUG_P("XF86MiscPassMessage"); + + REQUEST_AT_LEAST_SIZE(xXF86MiscPassMessageReq); + size = (sizeof(xXF86MiscPassMessageReq) + 3) >> 2; + size+= (stuff->typelen + 3) >> 2; + size+= (stuff->vallen + 3) >> 2; + if (client->req_len < size) + return BadLength; + if (stuff->typelen) { + if (!(msgtype = xalloc(stuff->typelen))) + return BadAlloc; + strncpy(msgtype,(char*)(&stuff[1]),stuff->typelen); + } else return BadValue; + if (stuff->vallen) { + if (!(msgval = xalloc(stuff->vallen))) { + xfree(msgtype); + return BadAlloc; + } + strncpy(msgval,(char*)((char*)&stuff[1] + ((stuff->typelen + 3) & ~3)), + stuff->vallen); + } else { + xfree(msgtype); + return BadValue; + } + + if ((retval = MiscExtPassMessage(stuff->screen,msgtype,msgval,&retstr)) != 0) { + xfree(msgtype); + xfree(msgval); + return retval; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mesglen = (retstr? strlen(retstr): 0); + rep.length = (SIZEOF(xXF86MiscPassMessageReply) - SIZEOF(xGenericReply) + + ((rep.mesglen + 3) & ~3)) >> 2; + rep.status = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.mesglen, n); + } + WriteToClient(client, SIZEOF(xXF86MiscPassMessageReply), (char *)&rep); + + if (rep.mesglen) + WriteToClient(client, rep.mesglen, (char *)retstr); + + xfree(msgtype); + xfree(msgval); + + return (client->noClientException); +} + +static int +ProcXF86MiscDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86MiscQueryVersion: + return ProcXF86MiscQueryVersion(client); +#ifdef _XF86MISC_SAVER_COMPAT_ + case X_XF86MiscGetSaver: + return ProcXF86MiscGetSaver(client); + case X_XF86MiscSetSaver: + return ProcXF86MiscSetSaver(client); +#endif + case X_XF86MiscGetMouseSettings: + return ProcXF86MiscGetMouseSettings(client); + case X_XF86MiscGetKbdSettings: + return ProcXF86MiscGetKbdSettings(client); + case X_XF86MiscSetClientVersion: + return ProcXF86MiscSetClientVersion(client); + case X_XF86MiscGetFilePaths: + return ProcXF86MiscGetFilePaths(client); + case X_XF86MiscPassMessage: + return ProcXF86MiscPassMessage(client); + default: + if (!xf86GetModInDevEnabled()) + return miscErrorBase + XF86MiscModInDevDisabled; + if (xf86GetModInDevAllowNonLocal() || LocalClient (client)) { + switch (stuff->data) { + case X_XF86MiscSetMouseSettings: + return ProcXF86MiscSetMouseSettings(client); + case X_XF86MiscSetKbdSettings: + return ProcXF86MiscSetKbdSettings(client); + case X_XF86MiscSetGrabKeysState: + return ProcXF86MiscSetGrabKeysState(client); + default: + return BadRequest; + } + } else + return miscErrorBase + XF86MiscModInDevClientNotLocal; + } +} + +static int +SProcXF86MiscQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86MiscQueryVersion(client); +} + +#ifdef _XF86MISC_SAVER_COMPAT_ +static int +SProcXF86MiscGetSaver(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscGetSaverReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscGetSaverReq); + swaps(&stuff->screen, n); + return ProcXF86MiscGetSaver(client); +} + +static int +SProcXF86MiscSetSaver(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscSetSaverReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscSetSaverReq); + swaps(&stuff->screen, n); + swapl(&stuff->suspendTime, n); + swapl(&stuff->offTime, n); + return ProcXF86MiscSetSaver(client); +} +#endif /* _XF86MISC_SAVER_COMPAT_ */ + +static int +SProcXF86MiscGetMouseSettings(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscGetMouseSettingsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscGetMouseSettingsReq); + return ProcXF86MiscGetMouseSettings(client); +} + +static int +SProcXF86MiscGetKbdSettings(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscGetKbdSettingsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscGetKbdSettingsReq); + return ProcXF86MiscGetKbdSettings(client); +} + +static int +SProcXF86MiscSetMouseSettings(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscSetMouseSettingsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscSetMouseSettingsReq); + swapl(&stuff->mousetype, n); + swapl(&stuff->baudrate, n); + swapl(&stuff->samplerate, n); + swapl(&stuff->resolution, n); + swapl(&stuff->buttons, n); + swapl(&stuff->emulate3timeout, n); + swapl(&stuff->flags, n); + return ProcXF86MiscSetMouseSettings(client); +} + +static int +SProcXF86MiscSetKbdSettings(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscSetKbdSettingsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscSetKbdSettingsReq); + swapl(&stuff->kbdtype, n); + swapl(&stuff->rate, n); + swapl(&stuff->delay, n); + return ProcXF86MiscSetKbdSettings(client); +} + +static int +SProcXF86MiscSetGrabKeysState(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscSetGrabKeysStateReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscSetGrabKeysStateReq); + swaps(&stuff->enable, n); + return ProcXF86MiscSetGrabKeysState(client); +} + +static int +SProcXF86MiscSetClientVersion(ClientPtr client) +{ + register int n; + REQUEST(xXF86MiscSetClientVersionReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscSetClientVersionReq); + swaps(&stuff->major, n); + swaps(&stuff->minor, n); + return ProcXF86MiscSetClientVersion(client); +} + +static int +SProcXF86MiscGetFilePaths(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscGetFilePathsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscGetFilePathsReq); + return ProcXF86MiscGetFilePaths(client); +} + +static int +SProcXF86MiscPassMessage(client) + ClientPtr client; +{ + register int n; + REQUEST(xXF86MiscPassMessageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86MiscPassMessageReq); + return ProcXF86MiscPassMessage(client); +} + +static int +SProcXF86MiscDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86MiscQueryVersion: + return SProcXF86MiscQueryVersion(client); +#ifdef _XF86MISC_SAVER_COMPAT_ + case X_XF86MiscGetSaver: + return SProcXF86MiscGetSaver(client); + case X_XF86MiscSetSaver: + return SProcXF86MiscSetSaver(client); +#endif + case X_XF86MiscGetMouseSettings: + return SProcXF86MiscGetMouseSettings(client); + case X_XF86MiscGetKbdSettings: + return SProcXF86MiscGetKbdSettings(client); + case X_XF86MiscSetClientVersion: + return SProcXF86MiscSetClientVersion(client); + case X_XF86MiscGetFilePaths: + return SProcXF86MiscGetFilePaths(client); + case X_XF86MiscPassMessage: + return SProcXF86MiscPassMessage(client); + default: + if (!xf86GetModInDevEnabled()) + return miscErrorBase + XF86MiscModInDevDisabled; + if (xf86GetModInDevAllowNonLocal() || LocalClient (client)) { + switch (stuff->data) { + case X_XF86MiscSetMouseSettings: + return SProcXF86MiscSetMouseSettings(client); + case X_XF86MiscSetKbdSettings: + return SProcXF86MiscSetKbdSettings(client); + case X_XF86MiscSetGrabKeysState: + return SProcXF86MiscSetGrabKeysState(client); + default: + return BadRequest; + } + } else + return miscErrorBase + XF86MiscModInDevClientNotLocal; + } +} + diff --git a/nx-X11/programs/Xserver/Xext/xf86miscproc.h b/nx-X11/programs/Xserver/Xext/xf86miscproc.h new file mode 100644 index 000000000..87a251767 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xf86miscproc.h @@ -0,0 +1,70 @@ +/* $XFree86: xc/programs/Xserver/Xext/xf86miscproc.h,v 1.5 2002/11/20 04:04:58 dawes Exp $ */ + +/* Prototypes for Pointer/Keyboard functions that the DDX must provide */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _XF86MISCPROC_H_ +#define _XF86MISCPROC_H_ + +typedef enum { + MISC_MSE_PROTO, + MISC_MSE_BAUDRATE, + MISC_MSE_SAMPLERATE, + MISC_MSE_RESOLUTION, + MISC_MSE_BUTTONS, + MISC_MSE_EM3BUTTONS, + MISC_MSE_EM3TIMEOUT, + MISC_MSE_CHORDMIDDLE, + MISC_MSE_FLAGS +} MiscExtMseValType; + +typedef enum { + MISC_KBD_TYPE, + MISC_KBD_RATE, + MISC_KBD_DELAY, + MISC_KBD_SERVNUMLOCK +} MiscExtKbdValType; + +typedef enum { + MISC_RET_SUCCESS, + MISC_RET_BADVAL, + MISC_RET_BADMSEPROTO, + MISC_RET_BADBAUDRATE, + MISC_RET_BADFLAGS, + MISC_RET_BADCOMBO, + MISC_RET_BADKBDTYPE, + MISC_RET_NOMODULE +} MiscExtReturn; + +typedef enum { + MISC_POINTER, + MISC_KEYBOARD +} MiscExtStructType; + +#define MISC_MSEFLAG_CLEARDTR 1 +#define MISC_MSEFLAG_CLEARRTS 2 +#define MISC_MSEFLAG_REOPEN 128 + +void XFree86MiscExtensionInit(void); + +Bool MiscExtGetMouseSettings(pointer *mouse, char **devname); +int MiscExtGetMouseValue(pointer mouse, MiscExtMseValType valtype); +Bool MiscExtSetMouseValue(pointer mouse, MiscExtMseValType valtype, int value); +Bool MiscExtGetKbdSettings(pointer *kbd); +int MiscExtGetKbdValue(pointer kbd, MiscExtKbdValType valtype); +Bool MiscExtSetKbdValue(pointer kbd, MiscExtKbdValType valtype, int value); +int MiscExtSetGrabKeysState(ClientPtr client, int enable); +pointer MiscExtCreateStruct(MiscExtStructType mse_or_kbd); +void MiscExtDestroyStruct(pointer structure, MiscExtStructType mse_or_kbd); +MiscExtReturn MiscExtApply(pointer structure, MiscExtStructType mse_or_kbd); +Bool MiscExtSetMouseDevice(pointer mouse, char* device); +Bool MiscExtGetFilePaths(const char **configfile, const char **modulepath, + const char **logfile); +int MiscExtPassMessage(int scrn, const char *msgtype, const char *msgval, + char **retstr); + +#endif + diff --git a/nx-X11/programs/Xserver/Xext/xf86vmode.c b/nx-X11/programs/Xserver/Xext/xf86vmode.c new file mode 100644 index 000000000..fa49fcd75 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xf86vmode.c @@ -0,0 +1,2206 @@ +/* $XFree86: xc/programs/Xserver/Xext/xf86vmode.c,v 3.58 2003/11/06 18:37:57 tsi Exp $ */ + +/* + +Copyright 1995 Kaleb S. KEITHLEY + +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, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +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 Kaleb S. KEITHLEY 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 Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ +/* $XdotOrg: xc/programs/Xserver/Xext/xf86vmode.c,v 1.8 2005/07/16 03:49:58 kem Exp $ */ +/* $Xorg: xf86vmode.c,v 1.3 2000/08/17 19:47:59 cpqbld Exp $ */ +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XF86VIDMODE_SERVER_ +#include <X11/extensions/xf86vmstr.h> +#include "swaprep.h" +#include "xf86.h" +#include "vidmodeproc.h" + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#define DEFAULT_XF86VIDMODE_VERBOSITY 3 + +static int VidModeErrorBase; +static int VidModeGeneration = 0; +static int VidModeClientPrivateIndex; + +/* This holds the client's version information */ +typedef struct { + int major; + int minor; +} VidModePrivRec, *VidModePrivPtr; + +#define VMPRIV(c) ((c)->devPrivates[VidModeClientPrivateIndex].ptr) + +static void XF86VidModeResetProc( + ExtensionEntry* /* extEntry */ +); + +static DISPATCH_PROC(ProcXF86VidModeDispatch); +static DISPATCH_PROC(ProcXF86VidModeGetAllModeLines); +static DISPATCH_PROC(ProcXF86VidModeGetModeLine); +static DISPATCH_PROC(ProcXF86VidModeGetMonitor); +static DISPATCH_PROC(ProcXF86VidModeLockModeSwitch); +static DISPATCH_PROC(ProcXF86VidModeAddModeLine); +static DISPATCH_PROC(ProcXF86VidModeDeleteModeLine); +static DISPATCH_PROC(ProcXF86VidModeModModeLine); +static DISPATCH_PROC(ProcXF86VidModeValidateModeLine); +static DISPATCH_PROC(ProcXF86VidModeQueryVersion); +static DISPATCH_PROC(ProcXF86VidModeSwitchMode); +static DISPATCH_PROC(ProcXF86VidModeSwitchToMode); +static DISPATCH_PROC(ProcXF86VidModeGetViewPort); +static DISPATCH_PROC(ProcXF86VidModeSetViewPort); +static DISPATCH_PROC(ProcXF86VidModeGetDotClocks); +static DISPATCH_PROC(ProcXF86VidModeSetGamma); +static DISPATCH_PROC(ProcXF86VidModeGetGamma); +static DISPATCH_PROC(ProcXF86VidModeSetClientVersion); +static DISPATCH_PROC(ProcXF86VidModeGetGammaRamp); +static DISPATCH_PROC(ProcXF86VidModeSetGammaRamp); +static DISPATCH_PROC(ProcXF86VidModeGetGammaRampSize); +static DISPATCH_PROC(SProcXF86VidModeDispatch); +static DISPATCH_PROC(SProcXF86VidModeGetAllModeLines); +static DISPATCH_PROC(SProcXF86VidModeGetModeLine); +static DISPATCH_PROC(SProcXF86VidModeGetMonitor); +static DISPATCH_PROC(SProcXF86VidModeLockModeSwitch); +static DISPATCH_PROC(SProcXF86VidModeAddModeLine); +static DISPATCH_PROC(SProcXF86VidModeDeleteModeLine); +static DISPATCH_PROC(SProcXF86VidModeModModeLine); +static DISPATCH_PROC(SProcXF86VidModeValidateModeLine); +static DISPATCH_PROC(SProcXF86VidModeQueryVersion); +static DISPATCH_PROC(SProcXF86VidModeSwitchMode); +static DISPATCH_PROC(SProcXF86VidModeSwitchToMode); +static DISPATCH_PROC(SProcXF86VidModeGetViewPort); +static DISPATCH_PROC(SProcXF86VidModeSetViewPort); +static DISPATCH_PROC(SProcXF86VidModeGetDotClocks); +static DISPATCH_PROC(SProcXF86VidModeSetGamma); +static DISPATCH_PROC(SProcXF86VidModeGetGamma); +static DISPATCH_PROC(SProcXF86VidModeSetClientVersion); +static DISPATCH_PROC(SProcXF86VidModeGetGammaRamp); +static DISPATCH_PROC(SProcXF86VidModeSetGammaRamp); +static DISPATCH_PROC(SProcXF86VidModeGetGammaRampSize); + +#if 0 +static unsigned char XF86VidModeReqCode = 0; +#endif + +/* The XF86VIDMODE_EVENTS code is far from complete */ + +#ifdef XF86VIDMODE_EVENTS +static int XF86VidModeEventBase = 0; + +static void SXF86VidModeNotifyEvent(); + xXF86VidModeNotifyEvent * /* from */, + xXF86VidModeNotifyEvent * /* to */ +); + +extern WindowPtr *WindowTable; + +static RESTYPE EventType; /* resource type for event masks */ + +typedef struct _XF86VidModeEvent *XF86VidModeEventPtr; + +typedef struct _XF86VidModeEvent { + XF86VidModeEventPtr next; + ClientPtr client; + ScreenPtr screen; + XID resource; + CARD32 mask; +} XF86VidModeEventRec; + +static int XF86VidModeFreeEvents(); + +typedef struct _XF86VidModeScreenPrivate { + XF86VidModeEventPtr events; + Bool hasWindow; +} XF86VidModeScreenPrivateRec, *XF86VidModeScreenPrivatePtr; + +static int ScreenPrivateIndex; + +#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr)(s)->devPrivates[ScreenPrivateIndex].ptr) +#define SetScreenPrivate(s,v) ((s)->devPrivates[ScreenPrivateIndex].ptr = (pointer) v); +#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = GetScreenPrivate(s) + +#define New(t) (xalloc (sizeof (t))) +#endif + +#ifdef DEBUG +# define DEBUG_P(x) ErrorF(x"\n"); +#else +# define DEBUG_P(x) /**/ +#endif + +void +XFree86VidModeExtensionInit(void) +{ + ExtensionEntry* extEntry; + ScreenPtr pScreen; + int i; + Bool enabled = FALSE; + + DEBUG_P("XFree86VidModeExtensionInit"); + +#ifdef XF86VIDMODE_EVENTS + EventType = CreateNewResourceType(XF86VidModeFreeEvents); + ScreenPrivateIndex = AllocateScreenPrivateIndex (); +#endif + + for(i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if (VidModeExtensionInit(pScreen)) + enabled = TRUE; +#ifdef XF86VIDMODE_EVENTS + SetScreenPrivate (pScreen, NULL); +#endif + } + /* This means that the DDX doesn't want the vidmode extension enabled */ + if (!enabled) + return; + + /* + * Allocate a client private index to hold the client's version + * information. + */ + if (VidModeGeneration != serverGeneration) { + VidModeClientPrivateIndex = AllocateClientPrivateIndex(); + /* + * Allocate 0 length, and use the private to hold a pointer to our + * VidModePrivRec. + */ + if (!AllocateClientPrivate(VidModeClientPrivateIndex, 0)) { + ErrorF("XFree86VidModeExtensionInit: " + "AllocateClientPrivate failed\n"); + return; + } + VidModeGeneration = serverGeneration; + } + + if ( +#ifdef XF86VIDMODE_EVENTS + EventType && ScreenPrivateIndex != -1 && +#endif + (extEntry = AddExtension(XF86VIDMODENAME, + XF86VidModeNumberEvents, + XF86VidModeNumberErrors, + ProcXF86VidModeDispatch, + SProcXF86VidModeDispatch, + XF86VidModeResetProc, + StandardMinorOpcode))) { +#if 0 + XF86VidModeReqCode = (unsigned char)extEntry->base; +#endif + VidModeErrorBase = extEntry->errorBase; +#ifdef XF86VIDMODE_EVENTS + XF86VidModeEventBase = extEntry->eventBase; + EventSwapVector[XF86VidModeEventBase] = (EventSwapPtr)SXF86VidModeNotifyEvent; +#endif + } +} + +/*ARGSUSED*/ +static void +XF86VidModeResetProc (extEntry) + ExtensionEntry* extEntry; +{ +} + +static int +ClientMajorVersion(ClientPtr client) +{ + VidModePrivPtr pPriv; + + pPriv = VMPRIV(client); + if (!pPriv) + return 0; + else + return pPriv->major; +} + +#ifdef XF86VIDMODE_EVENTS +static void +CheckScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (!pPriv) + return; + if (!pPriv->events && !pPriv->hasWindow) { + xfree (pPriv); + SetScreenPrivate (pScreen, NULL); + } +} + +static XF86VidModeScreenPrivatePtr +MakeScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (pPriv) + return pPriv; + pPriv = New (XF86VidModeScreenPrivateRec); + if (!pPriv) + return 0; + pPriv->events = 0; + pPriv->hasWindow = FALSE; + SetScreenPrivate (pScreen, pPriv); + return pPriv; +} + +static unsigned long +getEventMask (ScreenPtr pScreen, ClientPtr client) +{ + SetupScreen(pScreen); + XF86VidModeEventPtr pEv; + + if (!pPriv) + return 0; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + if (pEv->client == client) + return pEv->mask; + return 0; +} + +static Bool +setEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask) +{ + SetupScreen(pScreen); + XF86VidModeEventPtr pEv, *pPrev; + + if (getEventMask (pScreen, client) == mask) + return TRUE; + if (!pPriv) { + pPriv = MakeScreenPrivate (pScreen); + if (!pPriv) + return FALSE; + } + for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) + if (pEv->client == client) + break; + if (mask == 0) { + *pPrev = pEv->next; + xfree (pEv); + CheckScreenPrivate (pScreen); + } else { + if (!pEv) { + pEv = New (ScreenSaverEventRec); + if (!pEv) { + CheckScreenPrivate (pScreen); + return FALSE; + } + *pPrev = pEv; + pEv->next = NULL; + pEv->client = client; + pEv->screen = pScreen; + pEv->resource = FakeClientID (client->index); + } + pEv->mask = mask; + } + return TRUE; +} + +static int +XF86VidModeFreeEvents(pointer value, XID id) +{ + XF86VidModeEventPtr pOld = (XF86VidModeEventPtr)value; + ScreenPtr pScreen = pOld->screen; + SetupScreen (pScreen); + XF86VidModeEventPtr pEv, *pPrev; + + if (!pPriv) + return TRUE; + for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) + if (pEv == pOld) + break; + if (!pEv) + return TRUE; + *pPrev = pEv->next; + xfree (pEv); + CheckScreenPrivate (pScreen); + return TRUE; +} + +static void +SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced) +{ + XF86VidModeScreenPrivatePtr pPriv; + XF86VidModeEventPtr pEv; + unsigned long mask; + xXF86VidModeNotifyEvent ev; + ClientPtr client; + int kind; + + UpdateCurrentTimeIf (); + mask = XF86VidModeNotifyMask; + pScreen = screenInfo.screens[pScreen->myNum]; + pPriv = GetScreenPrivate(pScreen); + if (!pPriv) + return; + kind = XF86VidModeModeChange; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + { + client = pEv->client; + if (client->clientGone) + continue; + if (!(pEv->mask & mask)) + continue; + ev.type = XF86VidModeNotify + XF86VidModeEventBase; + ev.state = state; + ev.sequenceNumber = client->sequence; + ev.timestamp = currentTime.milliseconds; + ev.root = WindowTable[pScreen->myNum]->drawable.id; + ev.kind = kind; + ev.forced = forced; + WriteEventsToClient (client, 1, (xEvent *) &ev); + } +} + +static void +SXF86VidModeNotifyEvent(xXF86VidModeNotifyEvent *from, + xXF86VidModeNotifyEvent *to) +{ + to->type = from->type; + to->state = from->state; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->timestamp, to->timestamp); + cpswapl (from->root, to->root); + to->kind = from->kind; + to->forced = from->forced; +} +#endif + +static int +ProcXF86VidModeQueryVersion(ClientPtr client) +{ + xXF86VidModeQueryVersionReply rep; + register int n; + + DEBUG_P("XF86VidModeQueryVersion"); + + REQUEST_SIZE_MATCH(xXF86VidModeQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XF86VIDMODE_MAJOR_VERSION; + rep.minorVersion = XF86VIDMODE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXF86VidModeQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86VidModeGetModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeGetModeLineReq); + xXF86VidModeGetModeLineReply rep; + xXF86OldVidModeGetModeLineReply oldrep; + pointer mode; + register int n; + int dotClock; + int ver; + + DEBUG_P("XF86VidModeGetModeline"); + + ver = ClientMajorVersion(client); + REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); + rep.type = X_Reply; + if (ver < 2) { + rep.length = (SIZEOF(xXF86OldVidModeGetModeLineReply) - + SIZEOF(xGenericReply)) >> 2; + } else { + rep.length = (SIZEOF(xXF86VidModeGetModeLineReply) - + SIZEOF(xGenericReply)) >> 2; + } + rep.sequenceNumber = client->sequence; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + rep.dotclock = dotClock; + rep.hdisplay = VidModeGetModeValue(mode, VIDMODE_H_DISPLAY); + rep.hsyncstart = VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART); + rep.hsyncend = VidModeGetModeValue(mode, VIDMODE_H_SYNCEND); + rep.htotal = VidModeGetModeValue(mode, VIDMODE_H_TOTAL); + rep.hskew = VidModeGetModeValue(mode, VIDMODE_H_SKEW); + rep.vdisplay = VidModeGetModeValue(mode, VIDMODE_V_DISPLAY); + rep.vsyncstart = VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART); + rep.vsyncend = VidModeGetModeValue(mode, VIDMODE_V_SYNCEND); + rep.vtotal = VidModeGetModeValue(mode, VIDMODE_V_TOTAL); + rep.flags = VidModeGetModeValue(mode, VIDMODE_FLAGS); + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("GetModeLine - scrn: %d clock: %ld\n", + stuff->screen, (unsigned long)rep.dotclock); + ErrorF("GetModeLine - hdsp: %d hbeg: %d hend: %d httl: %d\n", + rep.hdisplay, rep.hsyncstart, + rep.hsyncend, rep.htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + rep.vdisplay, rep.vsyncstart, rep.vsyncend, + rep.vtotal, (unsigned long)rep.flags); + } + + /* + * Older servers sometimes had server privates that the VidMode + * extention made available. So to be compatiable pretend that + * there are no server privates to pass to the client + */ + rep.privsize = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.dotclock, n); + swaps(&rep.hdisplay, n); + swaps(&rep.hsyncstart, n); + swaps(&rep.hsyncend, n); + swaps(&rep.htotal, n); + swaps(&rep.hskew, n); + swaps(&rep.vdisplay, n); + swaps(&rep.vsyncstart, n); + swaps(&rep.vsyncend, n); + swaps(&rep.vtotal, n); + swapl(&rep.flags, n); + swapl(&rep.privsize, n); + } + if (ver < 2) { + oldrep.type = rep.type; + oldrep.sequenceNumber = rep.sequenceNumber; + oldrep.length = rep.length; + oldrep.dotclock = rep.dotclock; + oldrep.hdisplay = rep.hdisplay; + oldrep.hsyncstart = rep.hsyncstart; + oldrep.hsyncend = rep.hsyncend; + oldrep.htotal = rep.htotal; + oldrep.vdisplay = rep.vdisplay; + oldrep.vsyncstart = rep.vsyncstart; + oldrep.vsyncend = rep.vsyncend; + oldrep.vtotal = rep.vtotal; + oldrep.flags = rep.flags; + oldrep.privsize = rep.privsize; + WriteToClient(client, sizeof(xXF86OldVidModeGetModeLineReply), + (char *)&oldrep); + } else { + WriteToClient(client, sizeof(xXF86VidModeGetModeLineReply), + (char *)&rep); + } + return (client->noClientException); +} + +static int +ProcXF86VidModeGetAllModeLines(ClientPtr client) +{ + REQUEST(xXF86VidModeGetAllModeLinesReq); + xXF86VidModeGetAllModeLinesReply rep; + xXF86VidModeModeInfo mdinf; + xXF86OldVidModeModeInfo oldmdinf; + pointer mode; + int modecount, dotClock; + register int n; + int ver; + + DEBUG_P("XF86VidModeGetAllModelines"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + ver = ClientMajorVersion(client); + + modecount = VidModeGetNumOfModes(stuff->screen); + if (modecount < 1) + return (VidModeErrorBase + XF86VidModeExtensionDisabled); + + if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + rep.type = X_Reply; + rep.length = SIZEOF(xXF86VidModeGetAllModeLinesReply) - + SIZEOF(xGenericReply); + if (ver < 2) + rep.length += modecount * sizeof(xXF86OldVidModeModeInfo); + else + rep.length += modecount * sizeof(xXF86VidModeModeInfo); + rep.length >>= 2; + rep.sequenceNumber = client->sequence; + rep.modecount = modecount; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.modecount, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetAllModeLinesReply), (char *)&rep); + + do { + mdinf.dotclock = dotClock; + mdinf.hdisplay = VidModeGetModeValue(mode, VIDMODE_H_DISPLAY); + mdinf.hsyncstart = VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART); + mdinf.hsyncend = VidModeGetModeValue(mode, VIDMODE_H_SYNCEND); + mdinf.htotal = VidModeGetModeValue(mode, VIDMODE_H_TOTAL); + mdinf.hskew = VidModeGetModeValue(mode, VIDMODE_H_SKEW); + mdinf.vdisplay = VidModeGetModeValue(mode, VIDMODE_V_DISPLAY); + mdinf.vsyncstart = VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART); + mdinf.vsyncend = VidModeGetModeValue(mode, VIDMODE_V_SYNCEND); + mdinf.vtotal = VidModeGetModeValue(mode, VIDMODE_V_TOTAL); + mdinf.flags = VidModeGetModeValue(mode, VIDMODE_FLAGS); + mdinf.privsize = 0; + if (client->swapped) { + swapl(&mdinf.dotclock, n); + swaps(&mdinf.hdisplay, n); + swaps(&mdinf.hsyncstart, n); + swaps(&mdinf.hsyncend, n); + swaps(&mdinf.htotal, n); + swaps(&mdinf.hskew, n); + swaps(&mdinf.vdisplay, n); + swaps(&mdinf.vsyncstart, n); + swaps(&mdinf.vsyncend, n); + swaps(&mdinf.vtotal, n); + swapl(&mdinf.flags, n); + swapl(&mdinf.privsize, n); + } + if (ver < 2) { + oldmdinf.dotclock = mdinf.dotclock; + oldmdinf.hdisplay = mdinf.hdisplay; + oldmdinf.hsyncstart = mdinf.hsyncstart; + oldmdinf.hsyncend = mdinf.hsyncend; + oldmdinf.htotal = mdinf.htotal; + oldmdinf.vdisplay = mdinf.vdisplay; + oldmdinf.vsyncstart = mdinf.vsyncstart; + oldmdinf.vsyncend = mdinf.vsyncend; + oldmdinf.vtotal = mdinf.vtotal; + oldmdinf.flags = mdinf.flags; + oldmdinf.privsize = mdinf.privsize; + WriteToClient(client, sizeof(xXF86OldVidModeModeInfo), + (char *)&oldmdinf); + } else { + WriteToClient(client, sizeof(xXF86VidModeModeInfo), (char *)&mdinf); + } + + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + + return (client->noClientException); +} + +#define MODEMATCH(mode,stuff) \ + (VidModeGetModeValue(mode, VIDMODE_H_DISPLAY) == stuff->hdisplay \ + && VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART) == stuff->hsyncstart \ + && VidModeGetModeValue(mode, VIDMODE_H_SYNCEND) == stuff->hsyncend \ + && VidModeGetModeValue(mode, VIDMODE_H_TOTAL) == stuff->htotal \ + && VidModeGetModeValue(mode, VIDMODE_V_DISPLAY) == stuff->vdisplay \ + && VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART) == stuff->vsyncstart \ + && VidModeGetModeValue(mode, VIDMODE_V_SYNCEND) == stuff->vsyncend \ + && VidModeGetModeValue(mode, VIDMODE_V_TOTAL) == stuff->vtotal \ + && VidModeGetModeValue(mode, VIDMODE_FLAGS) == stuff->flags ) + +static int +ProcXF86VidModeAddModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeAddModeLineReq); + xXF86OldVidModeAddModeLineReq *oldstuff = + (xXF86OldVidModeAddModeLineReq *)client->requestBuffer; + xXF86VidModeAddModeLineReq newstuff; + pointer mode; + int len; + int dotClock; + int ver; + + DEBUG_P("XF86VidModeAddModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + stuff->after_dotclock = oldstuff->after_dotclock; + stuff->after_hdisplay = oldstuff->after_hdisplay; + stuff->after_hsyncstart = oldstuff->after_hsyncstart; + stuff->after_hsyncend = oldstuff->after_hsyncend; + stuff->after_htotal = oldstuff->after_htotal; + stuff->after_hskew = 0; + stuff->after_vdisplay = oldstuff->after_vdisplay; + stuff->after_vsyncstart = oldstuff->after_vsyncstart; + stuff->after_vsyncend = oldstuff->after_vsyncend; + stuff->after_vtotal = oldstuff->after_vtotal; + stuff->after_flags = oldstuff->after_flags; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("AddModeLine - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF("AddModeLine - hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + ErrorF(" after - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->after_dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->after_hdisplay, stuff->after_hsyncstart, + stuff->after_hsyncend, stuff->after_htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->after_vdisplay, stuff->after_vsyncstart, + stuff->after_vsyncend, stuff->after_vtotal, + (unsigned long)stuff->after_flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeAddModeLineReq); + len = client->req_len - (sizeof(xXF86OldVidModeAddModeLineReq) >> 2); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeAddModeLineReq) >> 2); + } + if (len != stuff->privsize) + return BadLength; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + return BadValue; + + if (stuff->after_hsyncstart < stuff->after_hdisplay || + stuff->after_hsyncend < stuff->after_hsyncstart || + stuff->after_htotal < stuff->after_hsyncend || + stuff->after_vsyncstart < stuff->after_vdisplay || + stuff->after_vsyncend < stuff->after_vsyncstart || + stuff->after_vtotal < stuff->after_vsyncend) + return BadValue; + + if (stuff->after_htotal != 0 || stuff->after_vtotal != 0) { + Bool found = FALSE; + if (VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) { + do { + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) + == dotClock) && MODEMATCH(mode, stuff)) { + found = TRUE; + break; + } + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + } + if (!found) + return BadValue; + } + + + mode = VidModeCreateMode(); + if (mode == NULL) + return BadValue; + + VidModeSetModeValue(mode, VIDMODE_CLOCK, stuff->dotclock); + VidModeSetModeValue(mode, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(mode, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(mode, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(mode, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(mode, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(mode, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(mode, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(mode, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(mode, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(mode, VIDMODE_FLAGS, stuff->flags); + + if (stuff->privsize) + ErrorF("AddModeLine - Privates in request have been ignored\n"); + + /* Check that the mode is consistent with the monitor specs */ + switch (VidModeCheckModeForMonitor(stuff->screen, mode)) { + case MODE_OK: + break; + case MODE_HSYNC: + case MODE_H_ILLEGAL: + xfree(mode); + return VidModeErrorBase + XF86VidModeBadHTimings; + case MODE_VSYNC: + case MODE_V_ILLEGAL: + xfree(mode); + return VidModeErrorBase + XF86VidModeBadVTimings; + default: + xfree(mode); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + + /* Check that the driver is happy with the mode */ + if (VidModeCheckModeForDriver(stuff->screen, mode) != MODE_OK) { + xfree(mode); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + + VidModeSetCrtcForMode(stuff->screen, mode); + + VidModeAddModeline(stuff->screen, mode); + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("AddModeLine - Succeeded\n"); + return client->noClientException; +} + +static int +ProcXF86VidModeDeleteModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeDeleteModeLineReq); + xXF86OldVidModeDeleteModeLineReq *oldstuff = + (xXF86OldVidModeDeleteModeLineReq *)client->requestBuffer; + xXF86VidModeDeleteModeLineReq newstuff; + pointer mode; + int len, dotClock; + int ver; + + DEBUG_P("XF86VidModeDeleteModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("DeleteModeLine - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeDeleteModeLineReq); + len = client->req_len - (sizeof(xXF86OldVidModeDeleteModeLineReq) >> 2); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeDeleteModeLineReq) >> 2); + } + if (len != stuff->privsize) { + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("req_len = %ld, sizeof(Req) = %d, privsize = %ld, " + "len = %d, length = %d\n", + (unsigned long)client->req_len, + (int)sizeof(xXF86VidModeDeleteModeLineReq)>>2, + (unsigned long)stuff->privsize, len, stuff->length); + } + return BadLength; + } + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("Checking against clock: %d (%d)\n", + VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_V_TOTAL), + VidModeGetModeValue(mode, VIDMODE_FLAGS)); + } + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && + MODEMATCH(mode, stuff)) + return BadValue; + + if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + do { + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("Checking against clock: %d (%d)\n", + VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_V_TOTAL), + VidModeGetModeValue(mode, VIDMODE_FLAGS)); + } + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && + MODEMATCH(mode, stuff)) { + VidModeDeleteModeline(stuff->screen, mode); + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("DeleteModeLine - Succeeded\n"); + return(client->noClientException); + } + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + + return BadValue; +} + +static int +ProcXF86VidModeModModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeModModeLineReq); + xXF86OldVidModeModModeLineReq *oldstuff = + (xXF86OldVidModeModModeLineReq *)client->requestBuffer; + xXF86VidModeModModeLineReq newstuff; + pointer mode, modetmp; + int len, dotClock; + int ver; + + DEBUG_P("XF86VidModeModModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2 ) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("ModModeLine - scrn: %d hdsp: %d hbeg: %d hend: %d httl: %d\n", + (int)stuff->screen, stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeModModeLineReq); + len = client->req_len - (sizeof(xXF86OldVidModeModModeLineReq) >> 2); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeModModeLineReq) >> 2); + } + if (len != stuff->privsize) + return BadLength; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + return BadValue; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + modetmp = VidModeCreateMode(); + VidModeCopyMode(mode, modetmp); + + VidModeSetModeValue(modetmp, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(modetmp, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(modetmp, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(modetmp, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(modetmp, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(modetmp, VIDMODE_FLAGS, stuff->flags); + + if (stuff->privsize) + ErrorF("ModModeLine - Privates in request have been ignored\n"); + + /* Check that the mode is consistent with the monitor specs */ + switch (VidModeCheckModeForMonitor(stuff->screen, modetmp)) { + case MODE_OK: + break; + case MODE_HSYNC: + case MODE_H_ILLEGAL: + xfree(modetmp); + return VidModeErrorBase + XF86VidModeBadHTimings; + case MODE_VSYNC: + case MODE_V_ILLEGAL: + xfree(modetmp); + return VidModeErrorBase + XF86VidModeBadVTimings; + default: + xfree(modetmp); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + + /* Check that the driver is happy with the mode */ + if (VidModeCheckModeForDriver(stuff->screen, modetmp) != MODE_OK) { + xfree(modetmp); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + xfree(modetmp); + + VidModeSetModeValue(mode, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(mode, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(mode, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(mode, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(mode, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(mode, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(mode, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(mode, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(mode, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(mode, VIDMODE_FLAGS, stuff->flags); + + VidModeSetCrtcForMode(stuff->screen, mode); + VidModeSwitchMode(stuff->screen, mode); + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("ModModeLine - Succeeded\n"); + return(client->noClientException); +} + +static int +ProcXF86VidModeValidateModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeValidateModeLineReq); + xXF86OldVidModeValidateModeLineReq *oldstuff = + (xXF86OldVidModeValidateModeLineReq *)client->requestBuffer; + xXF86VidModeValidateModeLineReq newstuff; + xXF86VidModeValidateModeLineReply rep; + pointer mode, modetmp = NULL; + int len, status, dotClock; + int ver; + + DEBUG_P("XF86VidModeValidateModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("ValidateModeLine - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeValidateModeLineReq); + len = client->req_len - + (sizeof(xXF86OldVidModeValidateModeLineReq) >> 2); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); + len = client->req_len - (sizeof(xXF86VidModeValidateModeLineReq) >> 2); + } + if (len != stuff->privsize) + return BadLength; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + status = MODE_OK; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + { + status = MODE_BAD; + goto status_reply; + } + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + modetmp = VidModeCreateMode(); + VidModeCopyMode(mode, modetmp); + + VidModeSetModeValue(modetmp, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(modetmp, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(modetmp, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(modetmp, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(modetmp, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(modetmp, VIDMODE_FLAGS, stuff->flags); + if (stuff->privsize) + ErrorF("ValidateModeLine - Privates in request have been ignored\n"); + + /* Check that the mode is consistent with the monitor specs */ + if ((status = VidModeCheckModeForMonitor(stuff->screen, modetmp)) != MODE_OK) + goto status_reply; + + /* Check that the driver is happy with the mode */ + status = VidModeCheckModeForDriver(stuff->screen, modetmp); + +status_reply: + if(modetmp) + xfree(modetmp); + + rep.type = X_Reply; + rep.length = (SIZEOF(xXF86VidModeValidateModeLineReply) + - SIZEOF(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.status = status; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xXF86VidModeValidateModeLineReply), (char *)&rep); + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("ValidateModeLine - Succeeded (status = %d)\n", status); + return(client->noClientException); +} + +static int +ProcXF86VidModeSwitchMode(ClientPtr client) +{ + REQUEST(xXF86VidModeSwitchModeReq); + + DEBUG_P("XF86VidModeSwitchMode"); + + REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + VidModeZoomViewport(stuff->screen, (short)stuff->zoom); + + return (client->noClientException); +} + +static int +ProcXF86VidModeSwitchToMode(ClientPtr client) +{ + REQUEST(xXF86VidModeSwitchToModeReq); + xXF86OldVidModeSwitchToModeReq *oldstuff = + (xXF86OldVidModeSwitchToModeReq *)client->requestBuffer; + xXF86VidModeSwitchToModeReq newstuff; + pointer mode; + int len, dotClock; + int ver; + + DEBUG_P("XF86VidModeSwitchToMode"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("SwitchToMode - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeSwitchToModeReq); + len = client->req_len - (sizeof(xXF86OldVidModeSwitchToModeReq) >> 2); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeSwitchToModeReq); + len = client->req_len - (sizeof(xXF86VidModeSwitchToModeReq) >> 2); + } + if (len != stuff->privsize) + return BadLength; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) + && MODEMATCH(mode, stuff)) + return (client->noClientException); + + if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + do { + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("Checking against clock: %d (%d)\n", + VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_V_TOTAL), + VidModeGetModeValue(mode, VIDMODE_FLAGS)); + } + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && + MODEMATCH(mode, stuff)) { + + if (!VidModeSwitchMode(stuff->screen, mode)) + return BadValue; + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("SwitchToMode - Succeeded\n"); + return(client->noClientException); + } + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + + return BadValue; +} + +static int +ProcXF86VidModeLockModeSwitch(ClientPtr client) +{ + REQUEST(xXF86VidModeLockModeSwitchReq); + + REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); + + DEBUG_P("XF86VidModeLockModeSwitch"); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeLockZoom(stuff->screen, (short)stuff->lock)) + return VidModeErrorBase + XF86VidModeZoomLocked; + + return (client->noClientException); +} + +static int +ProcXF86VidModeGetMonitor(ClientPtr client) +{ + REQUEST(xXF86VidModeGetMonitorReq); + xXF86VidModeGetMonitorReply rep; + register int n; + CARD32 *hsyncdata, *vsyncdata; + int i, nHsync, nVrefresh; + pointer monitor; + + DEBUG_P("XF86VidModeGetMonitor"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetMonitor(stuff->screen, &monitor)) + return BadValue; + + nHsync = VidModeGetMonitorValue(monitor, VIDMODE_MON_NHSYNC, 0).i; + nVrefresh = VidModeGetMonitorValue(monitor, VIDMODE_MON_NVREFRESH, 0).i; + + rep.type = X_Reply; + if ((char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_VENDOR, 0)).ptr) + rep.vendorLength = strlen((char *)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_VENDOR, 0)).ptr); + else + rep.vendorLength = 0; + if ((char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_MODEL, 0)).ptr) + rep.modelLength = strlen((char *)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_MODEL, 0)).ptr); + else + rep.modelLength = 0; + rep.length = (SIZEOF(xXF86VidModeGetMonitorReply) - SIZEOF(xGenericReply) + + (nHsync + nVrefresh) * sizeof(CARD32) + + ((rep.vendorLength + 3) & ~3) + + ((rep.modelLength + 3) & ~3)) >> 2; + rep.sequenceNumber = client->sequence; + rep.nhsync = nHsync; + rep.nvsync = nVrefresh; + hsyncdata = ALLOCATE_LOCAL(nHsync * sizeof(CARD32)); + if (!hsyncdata) { + return BadAlloc; + } + + vsyncdata = ALLOCATE_LOCAL(nVrefresh * sizeof(CARD32)); + if (!vsyncdata) { + DEALLOCATE_LOCAL(hsyncdata); + return BadAlloc; + } + + for (i = 0; i < nHsync; i++) { + hsyncdata[i] = (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_HSYNC_LO, i)).f | + (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_HSYNC_HI, i)).f << 16; + } + for (i = 0; i < nVrefresh; i++) { + vsyncdata[i] = (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_VREFRESH_LO, i)).f | + (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_VREFRESH_HI, i)).f << 16; + } + + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, SIZEOF(xXF86VidModeGetMonitorReply), (char *)&rep); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nHsync * sizeof(CARD32), + hsyncdata); + WriteSwappedDataToClient(client, nVrefresh * sizeof(CARD32), + vsyncdata); + if (rep.vendorLength) + WriteToClient(client, rep.vendorLength, (char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_VENDOR, 0)).ptr); + if (rep.modelLength) + WriteToClient(client, rep.modelLength, (char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_MODEL, 0)).ptr); + + DEALLOCATE_LOCAL(hsyncdata); + DEALLOCATE_LOCAL(vsyncdata); + + return (client->noClientException); +} + +static int +ProcXF86VidModeGetViewPort(ClientPtr client) +{ + REQUEST(xXF86VidModeGetViewPortReq); + xXF86VidModeGetViewPortReply rep; + int x, y, n; + + DEBUG_P("XF86VidModeGetViewPort"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + VidModeGetViewPort(stuff->screen, &x, &y); + rep.x = x; + rep.y = y; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.x, n); + swapl(&rep.y, n); + } + WriteToClient(client, SIZEOF(xXF86VidModeGetViewPortReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86VidModeSetViewPort(ClientPtr client) +{ + REQUEST(xXF86VidModeSetViewPortReq); + + DEBUG_P("XF86VidModeSetViewPort"); + + REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeSetViewPort(stuff->screen, stuff->x, stuff->y)) + return BadValue; + + return (client->noClientException); +} + +static int +ProcXF86VidModeGetDotClocks(ClientPtr client) +{ + REQUEST(xXF86VidModeGetDotClocksReq); + xXF86VidModeGetDotClocksReply rep; + register int n; + int numClocks; + CARD32 dotclock; + int *Clocks = NULL; + Bool ClockProg; + + DEBUG_P("XF86VidModeGetDotClocks"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetDotClocksReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + numClocks = VidModeGetNumOfClocks(stuff->screen, &ClockProg); + + rep.type = X_Reply; + rep.length = (SIZEOF(xXF86VidModeGetDotClocksReply) + - SIZEOF(xGenericReply) + numClocks) >> 2; + rep.sequenceNumber = client->sequence; + rep.clocks = numClocks; + rep.maxclocks = MAXCLOCKS; + rep.flags = 0; + + if (!ClockProg) { + Clocks = ALLOCATE_LOCAL(numClocks * sizeof(int)); + if (!Clocks) + return BadValue; + if (!VidModeGetClocks(stuff->screen, Clocks)) { + DEALLOCATE_LOCAL(Clocks); + return BadValue; + } + } + + if (ClockProg) { + rep.flags |= CLKFLAG_PROGRAMABLE; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.clocks, n); + swapl(&rep.maxclocks, n); + swapl(&rep.flags, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetDotClocksReply), (char *)&rep); + if (!ClockProg) { + for (n = 0; n < numClocks; n++) { + dotclock = *Clocks++; + if (client->swapped) { + WriteSwappedDataToClient(client, 4, (char *)&dotclock); + } else { + WriteToClient(client, 4, (char *)&dotclock); + } + } + } + + DEALLOCATE_LOCAL(Clocks); + return (client->noClientException); +} + +static int +ProcXF86VidModeSetGamma(ClientPtr client) +{ + REQUEST(xXF86VidModeSetGammaReq); + + DEBUG_P("XF86VidModeSetGamma"); + + REQUEST_SIZE_MATCH(xXF86VidModeSetGammaReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeSetGamma(stuff->screen, ((float)stuff->red)/10000., + ((float)stuff->green)/10000., ((float)stuff->blue)/10000.)) + return BadValue; + + return (client->noClientException); +} + +static int +ProcXF86VidModeGetGamma(ClientPtr client) +{ + REQUEST(xXF86VidModeGetGammaReq); + xXF86VidModeGetGammaReply rep; + register int n; + float red, green, blue; + + DEBUG_P("XF86VidModeGetGamma"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!VidModeGetGamma(stuff->screen, &red, &green, &blue)) + return BadValue; + rep.red = (CARD32)(red * 10000.); + rep.green = (CARD32)(green * 10000.); + rep.blue = (CARD32)(blue * 10000.); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.red, n); + swapl(&rep.green, n); + swapl(&rep.blue, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetGammaReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86VidModeSetGammaRamp(ClientPtr client) +{ + CARD16 *r, *g, *b; + int length; + REQUEST(xXF86VidModeSetGammaRampReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if(stuff->size != VidModeGetGammaRampSize(stuff->screen)) + return BadValue; + + length = (stuff->size + 1) & ~1; + + REQUEST_FIXED_SIZE(xXF86VidModeSetGammaRampReq, length * 6); + + r = (CARD16*)&stuff[1]; + g = r + length; + b = g + length; + + if (!VidModeSetGammaRamp(stuff->screen, stuff->size, r, g, b)) + return BadValue; + + return (client->noClientException); +} + +static int +ProcXF86VidModeGetGammaRamp(ClientPtr client) +{ + CARD16 *ramp = NULL; + int n, length, i; + xXF86VidModeGetGammaRampReply rep; + REQUEST(xXF86VidModeGetGammaRampReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if(stuff->size != VidModeGetGammaRampSize(stuff->screen)) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampReq); + + length = (stuff->size + 1) & ~1; + + if(stuff->size) { + if(!(ramp = xalloc(length * 3 * sizeof(CARD16)))) + return BadAlloc; + + if (!VidModeGetGammaRamp(stuff->screen, stuff->size, + ramp, ramp + length, ramp + (length * 2))) + return BadValue; + } + + rep.type = X_Reply; + rep.length = (length >> 1) * 3; + rep.sequenceNumber = client->sequence; + rep.size = stuff->size; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.size, n); + for(i = 0; i < length * 3; i++) + swaps(&ramp[i],n); + } + WriteToClient(client, sizeof(xXF86VidModeGetGammaRampReply), (char *)&rep); + + if(stuff->size) { + WriteToClient(client, rep.length << 2, (char*)ramp); + xfree(ramp); + } + + return (client->noClientException); +} + + +static int +ProcXF86VidModeGetGammaRampSize(ClientPtr client) +{ + xXF86VidModeGetGammaRampSizeReply rep; + int n; + REQUEST(xXF86VidModeGetGammaRampSizeReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampSizeReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.size = VidModeGetGammaRampSize(stuff->screen); + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.size, n); + } + WriteToClient(client,sizeof(xXF86VidModeGetGammaRampSizeReply),(char*)&rep); + + return (client->noClientException); +} + +static int +ProcXF86VidModeGetPermissions(ClientPtr client) +{ + xXF86VidModeGetPermissionsReply rep; + int n; + REQUEST(xXF86VidModeGetPermissionsReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86VidModeGetPermissionsReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.permissions = XF86VM_READ_PERMISSION; + if (xf86GetVidModeEnabled() && + (xf86GetVidModeAllowNonLocal() || LocalClient (client))) { + rep.permissions |= XF86VM_WRITE_PERMISSION; + } + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.permissions, n); + } + WriteToClient(client,sizeof(xXF86VidModeGetPermissionsReply),(char*)&rep); + + return (client->noClientException); +} + + +static int +ProcXF86VidModeSetClientVersion(ClientPtr client) +{ + REQUEST(xXF86VidModeSetClientVersionReq); + + VidModePrivPtr pPriv; + + DEBUG_P("XF86VidModeSetClientVersion"); + + REQUEST_SIZE_MATCH(xXF86VidModeSetClientVersionReq); + + if ((pPriv = VMPRIV(client)) == NULL) { + pPriv = xalloc(sizeof(VidModePrivRec)); + if (!pPriv) + return BadAlloc; + VMPRIV(client) = pPriv; + } + pPriv->major = stuff->major; + pPriv->minor = stuff->minor; + + return (client->noClientException); +} + +static int +ProcXF86VidModeDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86VidModeQueryVersion: + return ProcXF86VidModeQueryVersion(client); + case X_XF86VidModeGetModeLine: + return ProcXF86VidModeGetModeLine(client); + case X_XF86VidModeGetMonitor: + return ProcXF86VidModeGetMonitor(client); + case X_XF86VidModeGetAllModeLines: + return ProcXF86VidModeGetAllModeLines(client); + case X_XF86VidModeValidateModeLine: + return ProcXF86VidModeValidateModeLine(client); + case X_XF86VidModeGetViewPort: + return ProcXF86VidModeGetViewPort(client); + case X_XF86VidModeGetDotClocks: + return ProcXF86VidModeGetDotClocks(client); + case X_XF86VidModeSetClientVersion: + return ProcXF86VidModeSetClientVersion(client); + case X_XF86VidModeGetGamma: + return ProcXF86VidModeGetGamma(client); + case X_XF86VidModeGetGammaRamp: + return ProcXF86VidModeGetGammaRamp(client); + case X_XF86VidModeGetGammaRampSize: + return ProcXF86VidModeGetGammaRampSize(client); + case X_XF86VidModeGetPermissions: + return ProcXF86VidModeGetPermissions(client); + default: + if (!xf86GetVidModeEnabled()) + return VidModeErrorBase + XF86VidModeExtensionDisabled; + if (xf86GetVidModeAllowNonLocal() || LocalClient (client)) { + switch (stuff->data) { + case X_XF86VidModeAddModeLine: + return ProcXF86VidModeAddModeLine(client); + case X_XF86VidModeDeleteModeLine: + return ProcXF86VidModeDeleteModeLine(client); + case X_XF86VidModeModModeLine: + return ProcXF86VidModeModModeLine(client); + case X_XF86VidModeSwitchMode: + return ProcXF86VidModeSwitchMode(client); + case X_XF86VidModeSwitchToMode: + return ProcXF86VidModeSwitchToMode(client); + case X_XF86VidModeLockModeSwitch: + return ProcXF86VidModeLockModeSwitch(client); + case X_XF86VidModeSetViewPort: + return ProcXF86VidModeSetViewPort(client); + case X_XF86VidModeSetGamma: + return ProcXF86VidModeSetGamma(client); + case X_XF86VidModeSetGammaRamp: + return ProcXF86VidModeSetGammaRamp(client); + default: + return BadRequest; + } + } else + return VidModeErrorBase + XF86VidModeClientNotLocal; + } +} + +static int +SProcXF86VidModeQueryVersion(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86VidModeQueryVersion(client); +} + +static int +SProcXF86VidModeGetModeLine(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetModeLineReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetModeLine(client); +} + +static int +SProcXF86VidModeGetAllModeLines(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetAllModeLinesReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetAllModeLines(client); +} + +static int +SProcXF86VidModeAddModeLine(ClientPtr client) +{ + xXF86OldVidModeAddModeLineReq *oldstuff = + (xXF86OldVidModeAddModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeAddModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeAddModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeAddModeLine(client); +} + +static int +SProcXF86VidModeDeleteModeLine(ClientPtr client) +{ + xXF86OldVidModeDeleteModeLineReq *oldstuff = + (xXF86OldVidModeDeleteModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeDeleteModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeDeleteModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeDeleteModeLine(client); +} + +static int +SProcXF86VidModeModModeLine(ClientPtr client) +{ + xXF86OldVidModeModModeLineReq *oldstuff = + (xXF86OldVidModeModModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeModModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeModModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeModModeLine(client); +} + +static int +SProcXF86VidModeValidateModeLine(ClientPtr client) +{ + xXF86OldVidModeValidateModeLineReq *oldstuff = + (xXF86OldVidModeValidateModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeValidateModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeValidateModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeValidateModeLine(client); +} + +static int +SProcXF86VidModeSwitchMode(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSwitchModeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); + swaps(&stuff->screen, n); + swaps(&stuff->zoom, n); + return ProcXF86VidModeSwitchMode(client); +} + +static int +SProcXF86VidModeSwitchToMode(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSwitchToModeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSwitchToModeReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeSwitchToMode(client); +} + +static int +SProcXF86VidModeLockModeSwitch(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeLockModeSwitchReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); + swaps(&stuff->screen, n); + swaps(&stuff->lock, n); + return ProcXF86VidModeLockModeSwitch(client); +} + +static int +SProcXF86VidModeGetMonitor(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetMonitorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetMonitor(client); +} + +static int +SProcXF86VidModeGetViewPort(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetViewPortReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetViewPort(client); +} + +static int +SProcXF86VidModeSetViewPort(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSetViewPortReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); + swaps(&stuff->screen, n); + swapl(&stuff->x, n); + swapl(&stuff->y, n); + return ProcXF86VidModeSetViewPort(client); +} + +static int +SProcXF86VidModeGetDotClocks(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetDotClocksReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetDotClocksReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetDotClocks(client); +} + +static int +SProcXF86VidModeSetClientVersion(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSetClientVersionReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSetClientVersionReq); + swaps(&stuff->major, n); + swaps(&stuff->minor, n); + return ProcXF86VidModeSetClientVersion(client); +} + +static int +SProcXF86VidModeSetGamma(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSetGammaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSetGammaReq); + swaps(&stuff->screen, n); + swapl(&stuff->red, n); + swapl(&stuff->green, n); + swapl(&stuff->blue, n); + return ProcXF86VidModeSetGamma(client); +} + +static int +SProcXF86VidModeGetGamma(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetGammaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetGamma(client); +} + +static int +SProcXF86VidModeSetGammaRamp(ClientPtr client) +{ + CARD16 *ramp; + int length, n; + REQUEST(xXF86VidModeSetGammaRampReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeSetGammaRampReq); + swaps(&stuff->size, n); + swaps(&stuff->screen, n); + length = ((stuff->size + 1) & ~1) * 6; + REQUEST_FIXED_SIZE(xXF86VidModeSetGammaRampReq, length); + ramp = (CARD16*)&stuff[1]; + while(length--) { + swaps(ramp, n); + ramp++; + } + return ProcXF86VidModeSetGammaRamp(client); +} + +static int +SProcXF86VidModeGetGammaRamp(ClientPtr client) +{ + int n; + REQUEST(xXF86VidModeGetGammaRampReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampReq); + swaps(&stuff->size, n); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetGammaRamp(client); +} + +static int +SProcXF86VidModeGetGammaRampSize(ClientPtr client) +{ + int n; + REQUEST(xXF86VidModeGetGammaRampSizeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampSizeReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetGammaRampSize(client); +} + +static int +SProcXF86VidModeGetPermissions(ClientPtr client) +{ + int n; + REQUEST(xXF86VidModeGetPermissionsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetPermissionsReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetPermissions(client); +} + + +static int +SProcXF86VidModeDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86VidModeQueryVersion: + return SProcXF86VidModeQueryVersion(client); + case X_XF86VidModeGetModeLine: + return SProcXF86VidModeGetModeLine(client); + case X_XF86VidModeGetMonitor: + return SProcXF86VidModeGetMonitor(client); + case X_XF86VidModeGetAllModeLines: + return SProcXF86VidModeGetAllModeLines(client); + case X_XF86VidModeGetViewPort: + return SProcXF86VidModeGetViewPort(client); + case X_XF86VidModeValidateModeLine: + return SProcXF86VidModeValidateModeLine(client); + case X_XF86VidModeGetDotClocks: + return SProcXF86VidModeGetDotClocks(client); + case X_XF86VidModeSetClientVersion: + return SProcXF86VidModeSetClientVersion(client); + case X_XF86VidModeGetGamma: + return SProcXF86VidModeGetGamma(client); + case X_XF86VidModeGetGammaRamp: + return SProcXF86VidModeGetGammaRamp(client); + case X_XF86VidModeGetGammaRampSize: + return SProcXF86VidModeGetGammaRampSize(client); + case X_XF86VidModeGetPermissions: + return SProcXF86VidModeGetPermissions(client); + default: + if (!xf86GetVidModeEnabled()) + return VidModeErrorBase + XF86VidModeExtensionDisabled; + if (xf86GetVidModeAllowNonLocal() || LocalClient(client)) { + switch (stuff->data) { + case X_XF86VidModeAddModeLine: + return SProcXF86VidModeAddModeLine(client); + case X_XF86VidModeDeleteModeLine: + return SProcXF86VidModeDeleteModeLine(client); + case X_XF86VidModeModModeLine: + return SProcXF86VidModeModModeLine(client); + case X_XF86VidModeSwitchMode: + return SProcXF86VidModeSwitchMode(client); + case X_XF86VidModeSwitchToMode: + return SProcXF86VidModeSwitchToMode(client); + case X_XF86VidModeLockModeSwitch: + return SProcXF86VidModeLockModeSwitch(client); + case X_XF86VidModeSetViewPort: + return SProcXF86VidModeSetViewPort(client); + case X_XF86VidModeSetGamma: + return SProcXF86VidModeSetGamma(client); + case X_XF86VidModeSetGammaRamp: + return SProcXF86VidModeSetGammaRamp(client); + default: + return BadRequest; + } + } else + return VidModeErrorBase + XF86VidModeClientNotLocal; + } +} diff --git a/nx-X11/programs/Xserver/Xext/xprint.c b/nx-X11/programs/Xserver/Xext/xprint.c new file mode 100644 index 000000000..60512d372 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xprint.c @@ -0,0 +1,2760 @@ +/* $Xorg: xprint.c,v 1.5 2001/03/05 20:42:26 pookie Exp $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +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, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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 +COPYRIGHT HOLDERS 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 names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: xprint.c +** * +** * Copyright: Copyright 1993, 1995 Hewlett-Packard Company +** * +** * Copyright 1989 by The Massachusetts Institute of Technology +** * +** * 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 MIT not be used in +** * advertising or publicity pertaining to distribution of the +** * software without specific prior written permission. +** * M.I.T. makes no representation about the suitability of +** * this software for any purpose. It is provided "as is" +** * without any express or implied warranty. +** * +** * MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +** * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +** * NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE LI- +** * ABLE 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. +** * +** ********************************************************* +** +********************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xprint.c,v 1.14tsi Exp $ */ + +#define _XP_PRINT_SERVER_ +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xos.h> +#define NEED_EVENTS +#include <X11/Xproto.h> +#undef NEED_EVENTS +#include "misc.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include <X11/Xatom.h> +#include <X11/extensions/Print.h> +#include <X11/extensions/Printstr.h> +#include "../Xprint/DiPrint.h" +#include "../Xprint/attributes.h" +#include "modinit.h" + +static void XpResetProc(ExtensionEntry *); + +static int ProcXpDispatch(ClientPtr); +static int ProcXpSwappedDispatch(ClientPtr); + +static int ProcXpQueryVersion(ClientPtr); +static int ProcXpGetPrinterList(ClientPtr); +static int ProcXpCreateContext(ClientPtr); +static int ProcXpSetContext(ClientPtr); +static int ProcXpGetContext(ClientPtr); +static int ProcXpDestroyContext(ClientPtr); +static int ProcXpGetContextScreen(ClientPtr); +static int ProcXpStartJob(ClientPtr); +static int ProcXpEndJob(ClientPtr); +static int ProcXpStartDoc(ClientPtr); +static int ProcXpEndDoc(ClientPtr); +static int ProcXpStartPage(ClientPtr); +static int ProcXpEndPage(ClientPtr); +static int ProcXpSelectInput(ClientPtr); +static int ProcXpInputSelected(ClientPtr); +static int ProcXpPutDocumentData(ClientPtr); +static int ProcXpGetDocumentData(ClientPtr); +static int ProcXpGetAttributes(ClientPtr); +static int ProcXpGetOneAttribute(ClientPtr); +static int ProcXpSetAttributes(ClientPtr); +static int ProcXpRehashPrinterList(ClientPtr); +static int ProcXpQueryScreens(ClientPtr); +static int ProcXpGetPageDimensions(ClientPtr); +static int ProcXpSetImageResolution(ClientPtr); +static int ProcXpGetImageResolution(ClientPtr); + +static void SwapXpNotifyEvent(xPrintPrintEvent *, xPrintPrintEvent *); +static void SwapXpAttributeEvent(xPrintAttributeEvent *, xPrintAttributeEvent *); + +static int SProcXpGetPrinterList(ClientPtr); +static int SProcXpCreateContext(ClientPtr); +static int SProcXpSetContext(ClientPtr); +static int SProcXpGetContext(ClientPtr); +static int SProcXpDestroyContext(ClientPtr); +static int SProcXpGetContextScreen(ClientPtr); +static int SProcXpStartJob(ClientPtr); +static int SProcXpEndJob(ClientPtr); +static int SProcXpStartDoc(ClientPtr); +static int SProcXpEndDoc(ClientPtr); +static int SProcXpStartPage(ClientPtr); +static int SProcXpEndPage(ClientPtr); +static int SProcXpSelectInput(ClientPtr); +static int SProcXpInputSelected(ClientPtr); +static int SProcXpPutDocumentData(ClientPtr); +static int SProcXpGetDocumentData(ClientPtr); +static int SProcXpGetAttributes(ClientPtr); +static int SProcXpGetOneAttribute(ClientPtr); +static int SProcXpSetAttributes(ClientPtr); +static int SProcXpRehashPrinterList(ClientPtr); +static int SProcXpGetPageDimensions(ClientPtr); +static int SProcXpSetImageResolution(ClientPtr); +static int SProcXpGetImageResolution(ClientPtr); + +static void SendXpNotify(XpContextPtr, int, int); +static void SendAttributeNotify(XpContextPtr, int); +static int XpFreeClient(pointer, XID); +static int XpFreeContext(pointer, XID); +static int XpFreePage(pointer, XID); +static Bool XpCloseScreen(int, ScreenPtr); +static CARD32 GetAllEventMasks(XpContextPtr); +static struct _XpClient *CreateXpClient(ClientPtr); +static void InitContextPrivates(XpContextPtr); +static void ResetContextPrivates(void); +static struct _XpClient *FindClient(XpContextPtr, ClientPtr); +static struct _XpClient *AcquireClient(XpContextPtr, ClientPtr); + +typedef struct _driver { + struct _driver *next; + char *name; + int (* CreateContext)(XpContextPtr); +} XpDriverRec, *XpDriverPtr; + +typedef struct _xpScreen { + Bool (* CloseScreen)(int, ScreenPtr); + struct _driver *drivers; +} XpScreenRec, *XpScreenPtr; + +/* + * Each context has a list of XpClients indicating which clients have + * associated this context with their connection. + * Each such client has a RTclient resource allocated for it, + * and this per-client + * resource is used to delete the XpClientRec if/when the client closes + * its connection. + * The list of XpClients is also walked if/when the context is destroyed + * so that the ContextPtr can be removed from the client's devPrivates. + */ +typedef struct _XpClient { + struct _XpClient *pNext; + ClientPtr client; + XpContextPtr context; + CARD32 eventMask; + XID contextClientID; /* unneeded sanity check? */ +} XpClientRec, *XpClientPtr; + +static void FreeXpClient(XpClientPtr, Bool); + +/* + * Each StartPage request specifies a window which forms the top level + * window of the page. One of the following structs is created as a + * RTpage resource with the same ID as the window itself. This enables + * us to clean up when/if the window is destroyed, and to prevent the + * same window from being simultaneously referenced in multiple contexts. + * The page resource is created at the first StartPage on a given window, + * and is only destroyed when/if the window is destroyed. When the + * EndPage is recieved (or an EndDoc or EndJob) the context field is + * set to NULL, but the resource remains alive. + */ +typedef struct _XpPage { + XpContextPtr context; +} XpPageRec, *XpPagePtr; + +typedef struct _XpStPageRec { + XpContextPtr pContext; + Bool slept; + XpPagePtr pPage; + WindowPtr pWin; +} XpStPageRec, *XpStPagePtr; + +typedef struct _XpStDocRec { + XpContextPtr pContext; + Bool slept; + CARD8 type; +} XpStDocRec, *XpStDocPtr; + +#define QUADPAD(x) ((((x)+3)>>2)<<2) + +/* + * Possible bit-mask values in the "state" field of a XpContextRec. + */ +#define JOB_STARTED (1 << 0) +#define DOC_RAW_STARTED (1 << 1) +#define DOC_COOKED_STARTED (1 << 2) +#define PAGE_STARTED (1 << 3) +#define GET_DOC_DATA_STARTED (1 << 4) +#define JOB_GET_DATA (1 << 5) + +static XpScreenPtr XpScreens[MAXSCREENS]; +static unsigned char XpReqCode; +static int XpEventBase; +static int XpErrorBase; +static unsigned long XpGeneration = 0; +static int XpClientPrivateIndex; + +/* Variables for the context private machinery. + * These must be initialized at compile time because + * main() calls InitOutput before InitExtensions, and the + * output drivers are likely to call AllocateContextPrivate. + * These variables are reset at CloseScreen time. CloseScreen + * is used because it occurs after FreeAllResources, and before + * the next InitOutput cycle. + */ +static int contextPrivateCount = 0; +static int contextPrivateLen = 0; +static unsigned *contextPrivateSizes = (unsigned *)NULL; +static unsigned totalContextSize = sizeof(XpContextRec); + +/* + * There are three types of resources involved. One is the resource associated + * with the context itself, with an ID specified by a printing client. The + * next is a resource created by us on the client's behalf (and unknown to + * the client) when a client inits or sets a context which allows us to + * track each client's interest in events + * on a particular context, and also allows us to clean up this interest + * record when/if the client's connection is closed. Finally, there is + * a resource created for each window that's specified in a StartPage. This + * resource carries the same ID as the window itself, and enables us to + * easily prevent the same window being referenced in multiple contexts + * simultaneously, and enables us to clean up if the window is destroyed + * before the EndPage. + */ +static RESTYPE RTclient, RTcontext, RTpage; + +/* + * allEvents is the OR of all the legal event mask bits. + */ +static CARD32 allEvents = XPPrintMask | XPAttributeMask; + + +/******************************************************************************* + * + * ExtensionInit, Driver Init functions, QueryVersion, and Dispatch procs + * + ******************************************************************************/ + +/* + * XpExtensionInit + * + * Called from InitExtensions in main() usually through miinitextension + * + */ + +void +XpExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + + RTclient = CreateNewResourceType(XpFreeClient); + RTcontext = CreateNewResourceType(XpFreeContext); + RTpage = CreateNewResourceType(XpFreePage); + if (RTclient && RTcontext && RTpage && + (extEntry = AddExtension(XP_PRINTNAME, XP_EVENTS, XP_ERRORS, + ProcXpDispatch, ProcXpSwappedDispatch, + XpResetProc, StandardMinorOpcode))) + { + XpReqCode = (unsigned char)extEntry->base; + XpEventBase = extEntry->eventBase; + XpErrorBase = extEntry->errorBase; + EventSwapVector[XpEventBase] = (EventSwapPtr) SwapXpNotifyEvent; + EventSwapVector[XpEventBase+1] = (EventSwapPtr) SwapXpAttributeEvent; + } + + if(XpGeneration != serverGeneration) + { + XpClientPrivateIndex = AllocateClientPrivateIndex(); + /* + * We allocate 0 length & simply stuff a pointer to the + * ContextRec in the DevUnion. + */ + if(AllocateClientPrivate(XpClientPrivateIndex, 0) != TRUE) + { + /* we can't alloc a client private, should we bail??? XXX */ + } + XpGeneration = serverGeneration; + } + + for(i = 0; i < MAXSCREENS; i++) + { + /* + * If a screen has registered with our extension, then we + * wrap the screen's CloseScreen function to allow us to + * reset our ContextPrivate stuff. Note that this + * requires a printing DDX to call XpRegisterInitFunc + * _before_ this extension is initialized - i.e. at screen init + * time, _not_ at root window creation time. + */ + if(XpScreens[i] != (XpScreenPtr)NULL) + { + XpScreens[i]->CloseScreen = screenInfo.screens[i]->CloseScreen; + screenInfo.screens[i]->CloseScreen = XpCloseScreen; + } + } + DeclareExtensionSecurity(XP_PRINTNAME, TRUE); +} + +static void +XpResetProc(ExtensionEntry *extEntry) +{ + /* + * We can't free up the XpScreens recs here, because extensions are + * closed before screens, and our CloseScreen function uses the XpScreens + * recs. + + int i; + + for(i = 0; i < MAXSCREENS; i++) + { + if(XpScreens[i] != (XpScreenPtr)NULL) + Xfree(XpScreens[i]); + XpScreens[i] = (XpScreenPtr)NULL; + } + */ +} + +static Bool +XpCloseScreen(int index, ScreenPtr pScreen) +{ + Bool (* CloseScreen)(int, ScreenPtr); + + CloseScreen = XpScreens[index]->CloseScreen; + if(XpScreens[index] != (XpScreenPtr)NULL) + { + XpDriverPtr pDriv, nextDriv; + + pDriv = XpScreens[index]->drivers; + while(pDriv != (XpDriverPtr)NULL) + { + nextDriv = pDriv->next; + Xfree(pDriv); + pDriv = nextDriv; + } + Xfree(XpScreens[index]); + } + XpScreens[index] = (XpScreenPtr)NULL; + + /* + * It's wasteful to call ResetContextPrivates() at every CloseScreen, + * but it's the best we know how to do for now. We do this because we + * have to wait until after all resources have been freed (so we know + * how to free the ContextRecs), and before the next InitOutput cycle. + * See dix/main.c for the order of initialization and reset. + */ + ResetContextPrivates(); + return (*CloseScreen)(index, pScreen); +} + +#if 0 /* NOT USED */ +static void +FreeScreenEntry(XpScreenPtr pScreenEntry) +{ + XpDriverPtr pDriver; + + pDriver = pScreenEntry->drivers; + while(pDriver != (XpDriverPtr)NULL) + { + XpDriverPtr tmp; + + tmp = pDriver->next; + xfree(pDriver); + pDriver = tmp; + } + xfree(pScreenEntry); +} +#endif + +/* + * XpRegisterInitFunc tells the print extension which screens + * are printers as opposed to displays, and what drivers are + * supported on each screen. This eliminates the need of + * allocating print-related private structures on windows on _all_ screens. + * It also hands the extension a pointer to the routine to be called + * whenever a context gets created for a particular driver on this screen. + */ +void +XpRegisterInitFunc(ScreenPtr pScreen, char *driverName, int (*initContext)(struct _XpContext *)) +{ + XpDriverPtr pDriver; + + if(XpScreens[pScreen->myNum] == 0) + { + if((XpScreens[pScreen->myNum] = + (XpScreenPtr) Xalloc(sizeof(XpScreenRec))) == 0) + return; + XpScreens[pScreen->myNum]->CloseScreen = 0; + XpScreens[pScreen->myNum]->drivers = 0; + } + + if((pDriver = (XpDriverPtr)Xalloc(sizeof(XpDriverRec))) == 0) + return; + pDriver->next = XpScreens[pScreen->myNum]->drivers; + pDriver->name = driverName; + pDriver->CreateContext = initContext; + XpScreens[pScreen->myNum]->drivers = pDriver; +} + +static int +ProcXpDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch(stuff->data) + { + case X_PrintQueryVersion: + return ProcXpQueryVersion(client); + case X_PrintGetPrinterList: + return ProcXpGetPrinterList(client); + case X_PrintCreateContext: + return ProcXpCreateContext(client); + case X_PrintSetContext: + return ProcXpSetContext(client); + case X_PrintGetContext: + return ProcXpGetContext(client); + case X_PrintDestroyContext: + return ProcXpDestroyContext(client); + case X_PrintGetContextScreen: + return ProcXpGetContextScreen(client); + case X_PrintStartJob: + return ProcXpStartJob(client); + case X_PrintEndJob: + return ProcXpEndJob(client); + case X_PrintStartDoc: + return ProcXpStartDoc(client); + case X_PrintEndDoc: + return ProcXpEndDoc(client); + case X_PrintStartPage: + return ProcXpStartPage(client); + case X_PrintEndPage: + return ProcXpEndPage(client); + case X_PrintSelectInput: + return ProcXpSelectInput(client); + case X_PrintInputSelected: + return ProcXpInputSelected(client); + case X_PrintPutDocumentData: + return ProcXpPutDocumentData(client); + case X_PrintGetDocumentData: + return ProcXpGetDocumentData(client); + case X_PrintSetAttributes: + return ProcXpSetAttributes(client); + case X_PrintGetAttributes: + return ProcXpGetAttributes(client); + case X_PrintGetOneAttribute: + return ProcXpGetOneAttribute(client); + case X_PrintRehashPrinterList: + return ProcXpRehashPrinterList(client); + case X_PrintQueryScreens: + return ProcXpQueryScreens(client); + case X_PrintGetPageDimensions: + return ProcXpGetPageDimensions(client); + case X_PrintSetImageResolution: + return ProcXpSetImageResolution(client); + case X_PrintGetImageResolution: + return ProcXpGetImageResolution(client); + default: + return BadRequest; + } +} + +static int +ProcXpSwappedDispatch(ClientPtr client) +{ + int temp; + REQUEST(xReq); + + switch(stuff->data) + { + case X_PrintQueryVersion: + swaps(&stuff->length, temp); + return ProcXpQueryVersion(client); + case X_PrintGetPrinterList: + return SProcXpGetPrinterList(client); + case X_PrintCreateContext: + return SProcXpCreateContext(client); + case X_PrintSetContext: + return SProcXpSetContext(client); + case X_PrintGetContext: + return SProcXpGetContext(client); + case X_PrintDestroyContext: + return SProcXpDestroyContext(client); + case X_PrintGetContextScreen: + return SProcXpGetContextScreen(client); + case X_PrintStartJob: + return SProcXpStartJob(client); + case X_PrintEndJob: + return SProcXpEndJob(client); + case X_PrintStartDoc: + return SProcXpStartDoc(client); + case X_PrintEndDoc: + return SProcXpEndDoc(client); + case X_PrintStartPage: + return SProcXpStartPage(client); + case X_PrintEndPage: + return SProcXpEndPage(client); + case X_PrintSelectInput: + return SProcXpSelectInput(client); + case X_PrintInputSelected: + return SProcXpInputSelected(client); + case X_PrintPutDocumentData: + return SProcXpPutDocumentData(client); + case X_PrintGetDocumentData: + return SProcXpGetDocumentData(client); + case X_PrintSetAttributes: + return SProcXpSetAttributes(client); + case X_PrintGetAttributes: + return SProcXpGetAttributes(client); + case X_PrintGetOneAttribute: + return SProcXpGetOneAttribute(client); + case X_PrintRehashPrinterList: + return SProcXpRehashPrinterList(client); + case X_PrintQueryScreens: + swaps(&stuff->length, temp); + return ProcXpQueryScreens(client); + case X_PrintGetPageDimensions: + return SProcXpGetPageDimensions(client); + case X_PrintSetImageResolution: + return SProcXpSetImageResolution(client); + case X_PrintGetImageResolution: + return SProcXpGetImageResolution(client); + default: + return BadRequest; + } +} + +static int +ProcXpQueryVersion(ClientPtr client) +{ + /* REQUEST(xPrintQueryVersionReq); */ + xPrintQueryVersionReply rep; + register int n; + long l; + + REQUEST_SIZE_MATCH(xPrintQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XP_MAJOR_VERSION; + rep.minorVersion = XP_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sz_xPrintQueryVersionReply, (char *)&rep); + return client->noClientException; +} + +/******************************************************************************* + * + * GetPrinterList : Return a list of all printers associated with this + * server. Calls XpDiGetPrinterList, which is defined in + * the device-independent code in Xserver/Xprint. + * + ******************************************************************************/ + +static int +ProcXpGetPrinterList(ClientPtr client) +{ + REQUEST(xPrintGetPrinterListReq); + int totalSize; + int numEntries; + XpDiListEntry **pList; + xPrintGetPrinterListReply *rep; + int n, i, totalBytes; + long l; + char *curByte; + + REQUEST_AT_LEAST_SIZE(xPrintGetPrinterListReq); + + totalSize = ((sz_xPrintGetPrinterListReq) >> 2) + + ((stuff->printerNameLen + 3) >> 2) + + ((stuff->localeLen + 3) >> 2); + if(totalSize != client->req_len) + return BadLength; + + pList = XpDiGetPrinterList(stuff->printerNameLen, (char *)(stuff + 1), + stuff->localeLen, (char *)((stuff + 1) + + QUADPAD(stuff->printerNameLen))); + + for(numEntries = 0, totalBytes = sz_xPrintGetPrinterListReply; + pList[numEntries] != (XpDiListEntry *)NULL; + numEntries++) + { + totalBytes += 2 * sizeof(CARD32); + totalBytes += QUADPAD(strlen(pList[numEntries]->name)); + totalBytes += QUADPAD(strlen(pList[numEntries]->description)); + } + + if((rep = (xPrintGetPrinterListReply *)xalloc(totalBytes)) == + (xPrintGetPrinterListReply *)NULL) + return BadAlloc; + + rep->type = X_Reply; + rep->length = (totalBytes - sz_xPrintGetPrinterListReply) >> 2; + rep->sequenceNumber = client->sequence; + rep->listCount = numEntries; + if (client->swapped) { + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, l); + swapl(&rep->listCount, l); + } + + for(i = 0, curByte = (char *)(rep + 1); i < numEntries; i++) + { + CARD32 *pCrd; + int len; + + pCrd = (CARD32 *)curByte; + len = strlen(pList[i]->name); + *pCrd = len; + if (client->swapped) + swapl((long *)curByte, l); + curByte += sizeof(CARD32); + strncpy(curByte, pList[i]->name, len); + curByte += QUADPAD(len); + + pCrd = (CARD32 *)curByte; + len = strlen(pList[i]->description); + *pCrd = len; + if (client->swapped) + swapl((long *)curByte, l); + curByte += sizeof(CARD32); + strncpy(curByte, pList[i]->description, len); + curByte += QUADPAD(len); + } + + XpDiFreePrinterList(pList); + + WriteToClient(client, totalBytes, (char *)rep); + xfree(rep); + return client->noClientException; +} + +/******************************************************************************* + * + * QueryScreens: Returns the list of screens which are associated with + * print drivers. + * + ******************************************************************************/ + +static int +ProcXpQueryScreens(ClientPtr client) +{ + /* REQUEST(xPrintQueryScreensReq); */ + int i, numPrintScreens, totalSize; + WINDOW *pWinId; + xPrintQueryScreensReply *rep; + long l; + + REQUEST_SIZE_MATCH(xPrintQueryScreensReq); + + rep = (xPrintQueryScreensReply *)xalloc(sz_xPrintQueryScreensReply); + pWinId = (WINDOW *)(rep + 1); + + for(i = 0, numPrintScreens = 0, totalSize = sz_xPrintQueryScreensReply; + i < MAXSCREENS; i++) + { + /* + * If a screen has registered with our extension, then it's + * a printer screen. + */ + if(XpScreens[i] != (XpScreenPtr)NULL) + { + numPrintScreens++; + totalSize += sizeof(WINDOW); + rep = (xPrintQueryScreensReply *)xrealloc(rep, totalSize); + /* fix of bug: pWinId should be set again after reallocate rep */ + pWinId = (WINDOW *)(rep + 1); + *pWinId = WindowTable[i]->drawable.id; + if (client->swapped) + swapl((long *)pWinId, l); + } + } + + rep->type = X_Reply; + rep->sequenceNumber = client->sequence; + rep->length = (totalSize - sz_xPrintQueryScreensReply) >> 2; + rep->listCount = numPrintScreens; + if (client->swapped) + { + int n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, l); + swapl(&rep->listCount, l); + } + + WriteToClient(client, totalSize, (char *)rep); + xfree(rep); + return client->noClientException; +} + +static int +ProcXpGetPageDimensions(ClientPtr client) +{ + REQUEST(xPrintGetPageDimensionsReq); + CARD16 width, height; + xRectangle rect; + xPrintGetPageDimensionsReply rep; + XpContextPtr pContext; + int result; + + REQUEST_SIZE_MATCH(xPrintGetPageDimensionsReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if((pContext->funcs.GetMediumDimensions == 0) || + (pContext->funcs.GetReproducibleArea == 0)) + return BadImplementation; + + result = pContext->funcs.GetMediumDimensions(pContext, &width, &height); + if(result != Success) + return result; + + result = pContext->funcs.GetReproducibleArea(pContext, &rect); + if(result != Success) + return result; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.width = width; + rep.height = height; + rep.rx = rect.x; + rep.ry = rect.y; + rep.rwidth = rect.width; + rep.rheight = rect.height; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.width, n); + swaps(&rep.height, n); + swaps(&rep.rx, n); + swaps(&rep.ry, n); + swaps(&rep.rwidth, n); + swaps(&rep.rheight, n); + } + + WriteToClient(client, sz_xPrintGetPageDimensionsReply, (char *)&rep); + return client->noClientException; +} + +static int +ProcXpSetImageResolution(ClientPtr client) +{ + REQUEST(xPrintSetImageResolutionReq); + xPrintSetImageResolutionReply rep; + XpContextPtr pContext; + Bool status; + int result; + + REQUEST_SIZE_MATCH(xPrintSetImageResolutionReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + rep.prevRes = pContext->imageRes; + if(pContext->funcs.SetImageResolution != 0) { + result = pContext->funcs.SetImageResolution(pContext, + (int)stuff->imageRes, + &status); + if(result != Success) + status = FALSE; + } else + status = FALSE; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.prevRes, n); + } + + WriteToClient(client, sz_xPrintSetImageResolutionReply, (char *)&rep); + return client->noClientException; +} + +static int +ProcXpGetImageResolution(ClientPtr client) +{ + REQUEST(xPrintGetImageResolutionReq); + xPrintGetImageResolutionReply rep; + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintGetImageResolutionReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.imageRes = pContext->imageRes; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.imageRes, n); + } + + WriteToClient(client, sz_xPrintGetImageResolutionReply, (char *)&rep); + return client->noClientException; +} + +/******************************************************************************* + * + * RehashPrinterList : Cause the server's list of printers to be rebuilt. + * This allows new printers to be added, or old ones + * deleted without needing to restart the server. + * + ******************************************************************************/ + +static int +ProcXpRehashPrinterList(ClientPtr client) +{ + /* REQUEST(xPrintRehashPrinterListReq); */ + + REQUEST_SIZE_MATCH(xPrintRehashPrinterListReq); + + return XpRehashPrinterList(); +} + +/****************************************************************************** + * + * Context functions: Init, Set, Destroy, FreeContext + * AllocateContextPrivateIndex, AllocateContextPrivate + * and supporting functions. + * + * Init creates a context, creates a XpClientRec for the calling + * client, and stores the contextPtr in the client's devPrivates. + * + * Set creates a XpClientRec for the calling client, and stores the + * contextPtr in the client's devPrivates unless the context is None. + * If the context is None, then the client's connection association + * with any context is removed. + * + * Destroy frees any and all XpClientRecs associated with the context, + * frees the context itself, and removes the contextPtr from any + * relevant client devPrivates. + * + * FreeContext is called by FreeResource to free up a context. + * + ******************************************************************************/ + +/* + * CreateContext creates and initializes the memory for the context itself. + * The driver's CreateContext function + * is then called. + */ +static int +ProcXpCreateContext(ClientPtr client) +{ + REQUEST(xPrintCreateContextReq); + XpScreenPtr pPrintScreen; + WindowPtr pRoot; + char *driverName; + XpContextPtr pContext; + int result = Success; + XpDriverPtr pDriver; + + REQUEST_AT_LEAST_SIZE(xPrintCreateContextReq); + + LEGAL_NEW_RESOURCE(stuff->contextID, client); + + /* + * Check to see if the printer name is valid. + */ + if((pRoot = XpDiValidatePrinter((char *)(stuff + 1), stuff->printerNameLen)) == + (WindowPtr)NULL) + return BadMatch; + + pPrintScreen = XpScreens[pRoot->drawable.pScreen->myNum]; + + /* + * Allocate and add the context resource. + */ + if((pContext = (XpContextPtr) xalloc(totalContextSize)) == + (XpContextPtr) NULL) + return BadAlloc; + + InitContextPrivates(pContext); + + if(AddResource(stuff->contextID, RTcontext, (pointer) pContext) + != TRUE) + { + xfree(pContext); + return BadAlloc; + } + + pContext->contextID = stuff->contextID; + pContext->clientHead = (XpClientPtr)NULL; + pContext->screenNum = pRoot->drawable.pScreen->myNum; + pContext->state = 0; + pContext->clientSlept = (ClientPtr)NULL; + pContext->imageRes = 0; + + pContext->funcs.DestroyContext = 0; + pContext->funcs.StartJob = 0; + pContext->funcs.EndJob = 0; + pContext->funcs.StartDoc = 0; + pContext->funcs.EndDoc = 0; + pContext->funcs.StartPage = 0; + pContext->funcs.EndPage = 0; + pContext->funcs.PutDocumentData = 0; + pContext->funcs.GetDocumentData = 0; + pContext->funcs.GetAttributes = 0; + pContext->funcs.GetOneAttribute = 0; + pContext->funcs.SetAttributes = 0; + pContext->funcs.AugmentAttributes = 0; + pContext->funcs.GetMediumDimensions = 0; + pContext->funcs.GetReproducibleArea = 0; + pContext->funcs.SetImageResolution = 0; + + if((pContext->printerName = (char *)xalloc(stuff->printerNameLen + 1)) == + (char *)NULL) + { + /* Freeing the context also causes the XpClients to be freed. */ + FreeResource(stuff->contextID, RT_NONE); + return BadAlloc; + } + strncpy(pContext->printerName, (char *)(stuff + 1), stuff->printerNameLen); + pContext->printerName[stuff->printerNameLen] = (char)'\0'; + + driverName = XpDiGetDriverName(pRoot->drawable.pScreen->myNum, + pContext->printerName); + + for(pDriver = pPrintScreen->drivers; + pDriver != (XpDriverPtr)NULL; + pDriver = pDriver->next) + { + if(!strcmp(driverName, pDriver->name)) + { + if(pDriver->CreateContext != 0) + pDriver->CreateContext(pContext); + else + return BadImplementation; + break; + } + } + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +/* + * SetContext creates the calling client's contextClient resource, + * and stashes the contextID in the client's devPrivate. + */ +static int +ProcXpSetContext(ClientPtr client) +{ + REQUEST(xPrintSetContextReq); + + XpContextPtr pContext; + XpClientPtr pPrintClient; + int result = Success; + + REQUEST_AT_LEAST_SIZE(xPrintSetContextReq); + + if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) != + (pointer)NULL) + { + /* + * Erase this client's knowledge of its old context, if any. + */ + if((pPrintClient = FindClient(pContext, client)) != (XpClientPtr)NULL) + { + XpUnsetFontResFunc(client); + + if(pPrintClient->eventMask == 0) + FreeXpClient(pPrintClient, TRUE); + } + + client->devPrivates[XpClientPrivateIndex].ptr = (pointer)NULL; + } + if(stuff->printContext == None) + return Success; + + /* + * Check to see that the supplied XID is really a valid print context + * in this server. + */ + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL) + return BadAlloc; + + client->devPrivates[XpClientPrivateIndex].ptr = pContext; + + XpSetFontResFunc(client); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +XpContextPtr +XpGetPrintContext(ClientPtr client) +{ + return (client->devPrivates[XpClientPrivateIndex].ptr); +} + +static int +ProcXpGetContext(ClientPtr client) +{ + /* REQUEST(xPrintGetContextReq); */ + xPrintGetContextReply rep; + + XpContextPtr pContext; + register int n; + register long l; + + REQUEST_SIZE_MATCH(xPrintGetContextReq); + + if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) == + (pointer)NULL) + rep.printContext = None; + else + rep.printContext = pContext->contextID; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.printContext, l); + } + WriteToClient(client, sz_xPrintGetContextReply, (char *)&rep); + return client->noClientException; +} + + +/* + * DestroyContext frees the context associated with the calling client. + * It operates by freeing the context resource ID, thus causing XpFreeContext + * to be called. + */ +static int +ProcXpDestroyContext(ClientPtr client) +{ + REQUEST(xPrintDestroyContextReq); + + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintDestroyContextReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityDestroyAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + XpUnsetFontResFunc(client); + + FreeResource(pContext->contextID, RT_NONE); + + return Success; +} + +static int +ProcXpGetContextScreen(ClientPtr client) +{ + REQUEST(xPrintGetContextScreenReq); + xPrintGetContextScreenReply rep; + XpContextPtr pContext; + int n; + long l; + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadContext; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.rootWindow = WindowTable[pContext->screenNum]->drawable.id; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.rootWindow, l); + } + + WriteToClient(client, sz_xPrintGetContextScreenReply, (char *)&rep); + return client->noClientException; +} + +/* + * XpFreeContext is the routine called by dix:FreeResource when a context + * resource ID is freed. + * It checks to see if there's a partial job pending on the context, and + * if so it calls the appropriate End procs with the cancel flag set. + * It calls the driver's DestroyContext routine to allow the driver to clean + * up any context-related memory or state. + * It calls FreeXpClient to free all the + * associated XpClientRecs and to set all the client->devPrivates to NULL. + * It frees the printer name string, and frees the context + * itself. + */ +static int +XpFreeContext(pointer data, XID id) +{ + XpContextPtr pContext = (XpContextPtr)data; + + /* Clean up any pending job on this context */ + if(pContext->state != 0) + { + if(pContext->state & PAGE_STARTED) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + pContext->funcs.EndPage(pContext, pWin); + SendXpNotify(pContext, XPEndPageNotify, TRUE); + pContext->state &= ~PAGE_STARTED; + if(pPage) + pPage->context = (XpContextPtr)NULL; + } + if((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) + { + pContext->funcs.EndDoc(pContext, TRUE); + SendXpNotify(pContext, XPEndDocNotify, TRUE); + pContext->state &= ~DOC_RAW_STARTED; + pContext->state &= ~DOC_COOKED_STARTED; + } + if(pContext->funcs.EndJob != 0) + { + pContext->funcs.EndJob(pContext, TRUE); + SendXpNotify(pContext, XPEndJobNotify, TRUE); + pContext->state &= ~JOB_STARTED; + pContext->state &= ~GET_DOC_DATA_STARTED; + } + } + + /* + * Tell the driver we're destroying the context + * This allows the driver to free and ContextPrivate data + */ + if(pContext->funcs.DestroyContext != 0) + pContext->funcs.DestroyContext(pContext); + + /* Free up all the XpClientRecs */ + while(pContext->clientHead != (XpClientPtr)NULL) + { + FreeXpClient(pContext->clientHead, TRUE); + } + + xfree(pContext->printerName); + xfree(pContext); + return Success; /* ??? */ +} + +/* + * XpFreeClient is the routine called by dix:FreeResource when a RTclient + * is freed. It simply calls the FreeXpClient routine to do the work. + */ +static int +XpFreeClient(pointer data, XID id) +{ + FreeXpClient((XpClientPtr)data, TRUE); + return Success; +} + +/* + * FreeXpClient + * frees the ClientRec passed in, and sets the client->devPrivates to NULL + * if the client->devPrivates points to the same context as the XpClient. + * Called from XpFreeContext(from FreeResource), and + * XpFreeClient. The boolean freeResource specifies whether or not to call + * FreeResource for the XpClientRec's XID. We should free it except if we're + * called from XpFreeClient (which is itself called from FreeResource for the + * XpClientRec's XID). + */ +static void +FreeXpClient(XpClientPtr pXpClient, Bool freeResource) +{ + XpClientPtr pCurrent, pPrev; + XpContextPtr pContext = pXpClient->context; + + /* + * If we're freeing the clientRec associated with the context tied + * to the client's devPrivates, then we need to clear the devPrivates. + */ + if(pXpClient->client->devPrivates[XpClientPrivateIndex].ptr == + pXpClient->context) + { + pXpClient->client->devPrivates[XpClientPrivateIndex].ptr = + (pointer)NULL; + } + + for(pPrev = (XpClientPtr)NULL, pCurrent = pContext->clientHead; + pCurrent != (XpClientPtr)NULL; + pCurrent = pCurrent->pNext) + { + if(pCurrent == pXpClient) + { + if(freeResource == TRUE) + FreeResource (pCurrent->contextClientID, RTclient); + + if (pPrev != (XpClientPtr)NULL) + pPrev->pNext = pCurrent->pNext; + else + pContext->clientHead = pCurrent->pNext; + + xfree (pCurrent); + break; + } + pPrev = pCurrent; + } +} + +/* + * CreateXpClient takes a ClientPtr and returns a pointer to a + * XpClientRec which it allocates. It also initializes the Rec, + * including adding a resource on behalf of the client to enable the + * freeing of the Rec when the client's connection is closed. + */ +static XpClientPtr +CreateXpClient(ClientPtr client) +{ + XpClientPtr pNewPrintClient; + XID clientResource; + + if((pNewPrintClient = (XpClientPtr)xalloc(sizeof(XpClientRec))) == + (XpClientPtr)NULL) + return (XpClientPtr)NULL; + + clientResource = FakeClientID(client->index); + if(!AddResource(clientResource, RTclient, (pointer)pNewPrintClient)) + { + xfree (pNewPrintClient); + return (XpClientPtr)NULL; + } + + pNewPrintClient->pNext = (XpClientPtr)NULL; + pNewPrintClient->client = client; + pNewPrintClient->context = (XpContextPtr)NULL; + pNewPrintClient->eventMask = 0; + pNewPrintClient->contextClientID = clientResource; + + return pNewPrintClient; +} + +/* + * XpFreePage is the routine called by dix:FreeResource to free the page + * resource built with the same ID as a page window. It checks to see + * if we're in the middle of a page, and if so calls the driver's EndPage + * function with 'cancel' set TRUE. It frees the memory associated with + * the page resource. + */ +static int +XpFreePage(pointer data, XID id) +{ + XpPagePtr page = (XpPagePtr)data; + int result = Success; + WindowPtr pWin = (WindowPtr )LookupIDByType(id, RT_WINDOW); + + /* Check to see if the window's being deleted in the middle of a page */ + if(page->context != (XpContextPtr)NULL && + page->context->state & PAGE_STARTED) + { + if(page->context->funcs.EndPage != 0) + result = page->context->funcs.EndPage(page->context, pWin); + SendXpNotify(page->context, XPEndPageNotify, (int)TRUE); + page->context->pageWin = 0; /* None, NULL??? XXX */ + } + + xfree(page); + return result; +} + +/* + * ContextPrivate machinery. + * Context privates are intended for use by the drivers, allowing the + * drivers to maintain context-specific data. The driver should free + * the associated data at DestroyContext time. + */ + +static void +InitContextPrivates(XpContextPtr context) +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalContextSize == sizeof(XpContextRec)) + ppriv = (DevUnion *)NULL; + else + ppriv = (DevUnion *)(context + 1); + + context->devPrivates = ppriv; + sizes = contextPrivateSizes; + ptr = (char *)(ppriv + contextPrivateLen); + for (i = contextPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } +} + +static void +ResetContextPrivates(void) +{ + contextPrivateCount = 0; + contextPrivateLen = 0; + xfree(contextPrivateSizes); + contextPrivateSizes = (unsigned *)NULL; + totalContextSize = sizeof(XpContextRec); + +} + +int +XpAllocateContextPrivateIndex(void) +{ + return contextPrivateCount++; +} + +Bool +XpAllocateContextPrivate(int index, unsigned amount) +{ + unsigned oldamount; + + if (index >= contextPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(contextPrivateSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (contextPrivateLen <= index) + { + nsizes[contextPrivateLen++] = 0; + totalContextSize += sizeof(DevUnion); + } + contextPrivateSizes = nsizes; + } + oldamount = contextPrivateSizes[index]; + if (amount > oldamount) + { + contextPrivateSizes[index] = amount; + totalContextSize += (amount - oldamount); + } + return TRUE; +} + +static XpClientPtr +AcquireClient(XpContextPtr pContext, ClientPtr client) +{ + XpClientPtr pXpClient; + + if((pXpClient = FindClient(pContext, client)) != (XpClientPtr)NULL) + return pXpClient; + + if((pXpClient = CreateXpClient(client)) == (XpClientPtr)NULL) + return (XpClientPtr)NULL; + + pXpClient->context = pContext; + pXpClient->pNext = pContext->clientHead; + pContext->clientHead = pXpClient; + + return pXpClient; +} + +static XpClientPtr +FindClient(XpContextPtr pContext, ClientPtr client) +{ + XpClientPtr pXpClient; + + for(pXpClient = pContext->clientHead; pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + if(pXpClient->client == client) return pXpClient; + } + return (XpClientPtr)NULL; +} + + +/****************************************************************************** + * + * Start/End Functions: StartJob, EndJob, StartDoc, EndDoc, StartPage, EndPage + * + ******************************************************************************/ + +static int +ProcXpStartJob(ClientPtr client) +{ + REQUEST(xPrintStartJobReq); + XpContextPtr pContext; + int result = Success; + + REQUEST_SIZE_MATCH(xPrintStartJobReq); + + /* Check to see that a context has been established by this client. */ + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadContext; + + if(pContext->state != 0) + return XpErrorBase+XPBadSequence; + + if(stuff->saveData != XPSpool && stuff->saveData != XPGetData) + { + client->errorValue = stuff->saveData; + return BadValue; + } + + if(pContext->funcs.StartJob != 0) + result = pContext->funcs.StartJob(pContext, + (stuff->saveData == XPGetData)? TRUE:FALSE, + client); + else + return BadImplementation; + + pContext->state = JOB_STARTED; + if(stuff->saveData == XPGetData) + pContext->state |= JOB_GET_DATA; + + SendXpNotify(pContext, XPStartJobNotify, FALSE); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndJob(ClientPtr client) +{ + REQUEST(xPrintEndJobReq); + int result = Success; + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintEndJobReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & JOB_STARTED)) + return XpErrorBase+XPBadSequence; + + /* Check for missing EndDoc */ + if((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) + { + if(pContext->state & PAGE_STARTED) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + if(stuff->cancel != TRUE) + return XpErrorBase+XPBadSequence; + + if(pContext->funcs.EndPage != 0) + result = pContext->funcs.EndPage(pContext, pWin); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndPageNotify, TRUE); + + pContext->state &= ~PAGE_STARTED; + + if(pPage) + pPage->context = (XpContextPtr)NULL; + + if(result != Success) return result; + } + + if(pContext->funcs.EndDoc != 0) + result = pContext->funcs.EndDoc(pContext, stuff->cancel); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndDocNotify, stuff->cancel); + } + + if(pContext->funcs.EndJob != 0) + result = pContext->funcs.EndJob(pContext, stuff->cancel); + else + return BadImplementation; + + pContext->state = 0; + + SendXpNotify(pContext, XPEndJobNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static Bool +DoStartDoc(ClientPtr client, XpStDocPtr c) +{ + XpContextPtr pContext = c->pContext; + + if(c->pContext->state & JOB_GET_DATA && + !(c->pContext->state & GET_DOC_DATA_STARTED)) + { + if(!c->slept) + { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)DoStartDoc, (pointer) c); + c->pContext->clientSlept = client; + } + return TRUE; + } + + if(pContext->funcs.StartDoc != 0) + (void) pContext->funcs.StartDoc(pContext, c->type); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + if(c->type == XPDocNormal) + pContext->state |= DOC_COOKED_STARTED; + else + pContext->state |= DOC_RAW_STARTED; + + SendXpNotify(pContext, XPStartDocNotify, (int)FALSE); + + xfree(c); + return TRUE; +} + +static int +ProcXpStartDoc(ClientPtr client) +{ + REQUEST(xPrintStartDocReq); + int result = Success; + XpContextPtr pContext; + XpStDocPtr c; + + REQUEST_SIZE_MATCH(xPrintStartDocReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & JOB_STARTED) || + pContext->state & DOC_RAW_STARTED || + pContext->state & DOC_COOKED_STARTED) + return XpErrorBase+XPBadSequence; + + if(stuff->type != XPDocNormal && stuff->type != XPDocRaw) + { + client->errorValue = stuff->type; + return BadValue; + } + + c = (XpStDocPtr)xalloc(sizeof(XpStDocRec)); + c->pContext = pContext; + c->type = stuff->type; + c->slept = FALSE; + (void)DoStartDoc(client, c); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndDoc(ClientPtr client) +{ + REQUEST(xPrintEndDocReq); + XpContextPtr pContext; + int result = Success; + + REQUEST_SIZE_MATCH(xPrintEndDocReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & DOC_RAW_STARTED) && + !(pContext->state & DOC_COOKED_STARTED)) + return XpErrorBase+XPBadSequence; + + if(pContext->state & PAGE_STARTED) + { + if(stuff->cancel == TRUE) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + if(pContext->funcs.EndPage != 0) + result = pContext->funcs.EndPage(pContext, pWin); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndPageNotify, TRUE); + + if(pPage) + pPage->context = (XpContextPtr)NULL; + } + else + return XpErrorBase+XPBadSequence; + if(result != Success) + return result; + } + + if(pContext->funcs.EndDoc != 0) + result = pContext->funcs.EndDoc(pContext, stuff->cancel); + else + return BadImplementation; + + pContext->state &= ~DOC_RAW_STARTED; + pContext->state &= ~DOC_COOKED_STARTED; + + SendXpNotify(pContext, XPEndDocNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static Bool +DoStartPage( + ClientPtr client, + XpStPagePtr c) +{ + WindowPtr pWin = c->pWin; + int result = Success; + XpContextPtr pContext = c->pContext; + XpPagePtr pPage; + + if(c->pContext->state & JOB_GET_DATA && + !(c->pContext->state & GET_DOC_DATA_STARTED)) + { + if(!c->slept) + { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)DoStartPage, (pointer) c); + c->pContext->clientSlept = client; + } + return TRUE; + } + + if(!(pContext->state & DOC_COOKED_STARTED)) + { + /* Implied StartDoc if it was omitted */ + if(pContext->funcs.StartDoc != 0) + result = pContext->funcs.StartDoc(pContext, XPDocNormal); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + if(result != Success) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, result); + return TRUE; + } + + pContext->state |= DOC_COOKED_STARTED; + SendXpNotify(pContext, XPStartDocNotify, (int)FALSE); + } + + /* ensure the window's not already being used as a page */ + if((pPage = (XpPagePtr)LookupIDByType(c->pWin->drawable.id, RTpage)) != + (XpPagePtr)NULL) + { + if(pPage->context != (XpContextPtr)NULL) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadWindow); + return TRUE; + } + } + else + { + if((pPage = (XpPagePtr)xalloc(sizeof(XpPageRec))) == (XpPagePtr)NULL) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadAlloc); + return TRUE; + } + if(AddResource(c->pWin->drawable.id, RTpage, pPage) == FALSE) + { + xfree(pPage); + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadAlloc); + return TRUE; + } + } + + pPage->context = pContext; + pContext->pageWin = c->pWin->drawable.id; + + if(pContext->funcs.StartPage != 0) + result = pContext->funcs.StartPage(pContext, pWin); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + pContext->state |= PAGE_STARTED; + + (void)MapWindow(pWin, client); + + SendXpNotify(pContext, XPStartPageNotify, (int)FALSE); + + return TRUE; +} + +static int +ProcXpStartPage(ClientPtr client) +{ + REQUEST(xPrintStartPageReq); + WindowPtr pWin; + int result = Success; + XpContextPtr pContext; + XpStPagePtr c; + + REQUEST_SIZE_MATCH(xPrintStartPageReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & JOB_STARTED)) + return XpErrorBase+XPBadSequence; + + /* can't have pages in a raw documented */ + if(pContext->state & DOC_RAW_STARTED) + return XpErrorBase+XPBadSequence; + + if(pContext->state & PAGE_STARTED) + return XpErrorBase+XPBadSequence; + + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin || pWin->drawable.pScreen->myNum != pContext->screenNum) + return BadWindow; + + if((c = (XpStPagePtr)xalloc(sizeof(XpStPageRec))) == (XpStPagePtr)NULL) + return BadAlloc; + c->pContext = pContext; + c->slept = FALSE; + c->pWin = pWin; + + (void)DoStartPage(client, c); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndPage(ClientPtr client) +{ + REQUEST(xPrintEndPageReq); + int result = Success; + XpContextPtr pContext; + XpPagePtr page; + WindowPtr pWin; + + REQUEST_SIZE_MATCH(xPrintEndPageReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & PAGE_STARTED)) + return XpErrorBase+XPBadSequence; + + pWin = (WindowPtr )LookupIDByType(pContext->pageWin, RT_WINDOW); + + /* Call the ddx's EndPage proc. */ + if(pContext->funcs.EndPage != 0) + result = pContext->funcs.EndPage(pContext, pWin); + else + return BadImplementation; + + if((page = (XpPagePtr)LookupIDByType(pContext->pageWin, RTpage)) != + (XpPagePtr)NULL) + page->context = (XpContextPtr)NULL; + + pContext->state &= ~PAGE_STARTED; + pContext->pageWin = 0; /* None, NULL??? XXX */ + + (void)UnmapWindow(pWin, FALSE); + + SendXpNotify(pContext, XPEndPageNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +/******************************************************************************* + * + * Document Data Functions: PutDocumentData, GetDocumentData + * + ******************************************************************************/ + +static int +ProcXpPutDocumentData(ClientPtr client) +{ + REQUEST(xPrintPutDocumentDataReq); + XpContextPtr pContext; + DrawablePtr pDraw; + int result = Success; + unsigned totalSize; + char *pData, *pDoc_fmt, *pOptions; + + REQUEST_AT_LEAST_SIZE(xPrintPutDocumentDataReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & DOC_RAW_STARTED) && + !(pContext->state & DOC_COOKED_STARTED)) + return XpErrorBase+XPBadSequence; + + if (stuff->drawable) { + if (pContext->state & DOC_RAW_STARTED) + return BadDrawable; + pDraw = (DrawablePtr)LookupDrawable(stuff->drawable, client); + if (!pDraw || pDraw->pScreen->myNum != pContext->screenNum) + return BadDrawable; + } else { + if (pContext->state & DOC_COOKED_STARTED) + return BadDrawable; + pDraw = NULL; + } + + pData = (char *)(&stuff[1]); + + totalSize = (stuff->len_data + 3) >> 2; + pDoc_fmt = pData + (totalSize << 2); + + totalSize += (stuff->len_fmt + 3) >> 2; + pOptions = pData + (totalSize << 2); + + totalSize += (stuff->len_options + 3) >> 2; + if((totalSize + (sz_xPrintPutDocumentDataReq >> 2)) != client->req_len) + return BadLength; + + if(pContext->funcs.PutDocumentData != 0) + { + result = (*pContext->funcs.PutDocumentData)(pContext, pDraw, + pData, stuff->len_data, + pDoc_fmt, stuff->len_fmt, + pOptions, stuff->len_options, + client); + } + else + return BadImplementation; + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpGetDocumentData(ClientPtr client) +{ + REQUEST(xPrintGetDocumentDataReq); + xPrintGetDocumentDataReply rep; + XpContextPtr pContext; + int result = Success; + + REQUEST_SIZE_MATCH(xPrintGetDocumentDataReq); + + if((pContext = (XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetDocumentData == 0) + return BadImplementation; + + if(!(pContext->state & JOB_GET_DATA) || + pContext->state & GET_DOC_DATA_STARTED) + return XpErrorBase+XPBadSequence; + + if(stuff->maxBufferSize <= 0) + { + client->errorValue = stuff->maxBufferSize; + return BadValue; /* gotta have a positive buffer size */ + } + + result = (*pContext->funcs.GetDocumentData)(pContext, client, + stuff->maxBufferSize); + if(result != Success) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.dataLen = 0; + rep.statusCode = 1; + rep.finishedFlag = TRUE; + if (client->swapped) { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.statusCode, l); /* XXX Why are these longs??? */ + swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */ + } + (void)WriteToClient(client,sz_xPrintGetDocumentDataReply,(char *)&rep); + } + else + pContext->state |= GET_DOC_DATA_STARTED; + + if(pContext->clientSlept != (ClientPtr)NULL) + { + ClientSignal(pContext->clientSlept); + ClientWakeup(pContext->clientSlept); + pContext->clientSlept = (ClientPtr)NULL; + } + + return result; +} + +/******************************************************************************* + * + * Attribute requests: GetAttributes, SetAttributes, GetOneAttribute + * + ******************************************************************************/ + +static int +ProcXpGetAttributes(ClientPtr client) +{ + REQUEST(xPrintGetAttributesReq); + XpContextPtr pContext; + char *attrs; + xPrintGetAttributesReply *pRep; + int totalSize, n; + unsigned long l; + + REQUEST_SIZE_MATCH(xPrintGetAttributesReq); + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + if(stuff->type != XPServerAttr) + { + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetAttributes == 0) + return BadImplementation; + if((attrs = (*pContext->funcs.GetAttributes)(pContext, stuff->type)) == + (char *)NULL) + return BadAlloc; + } + else + { + if((attrs = XpGetAttributes((XpContextPtr)NULL, XPServerAttr)) == + (char *)NULL) + return BadAlloc; + } + + totalSize = sz_xPrintGetAttributesReply + QUADPAD(strlen(attrs)); + if((pRep = (xPrintGetAttributesReply *)malloc(totalSize)) == + (xPrintGetAttributesReply *)NULL) + return BadAlloc; + + pRep->type = X_Reply; + pRep->length = (totalSize - sz_xPrintGetAttributesReply) >> 2; + pRep->sequenceNumber = client->sequence; + pRep->stringLen = strlen(attrs); + + if (client->swapped) { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, l); + swapl(&pRep->stringLen, l); + } + + strncpy((char*)(pRep + 1), attrs, strlen(attrs)); + xfree(attrs); + + WriteToClient(client, totalSize, (char *)pRep); + + xfree(pRep); + + return client->noClientException; +} + +static int +ProcXpSetAttributes(ClientPtr client) +{ + REQUEST(xPrintSetAttributesReq); + int result = Success; + XpContextPtr pContext; + char *attr; + + REQUEST_AT_LEAST_SIZE(xPrintSetAttributesReq); + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + /* + * Disallow changing of read-only attribute pools + */ + if(stuff->type == XPPrinterAttr || stuff->type == XPServerAttr) + return BadMatch; + + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.SetAttributes == 0) + return BadImplementation; + + /* + * Check for attributes being set after their relevant phase + * has already begun (e.g. Job attributes set after StartJob). + */ + if((pContext->state & JOB_STARTED) && stuff->type == XPJobAttr) + return XpErrorBase+XPBadSequence; + if(((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) && stuff->type == XPDocAttr) + return XpErrorBase+XPBadSequence; + if((pContext->state & PAGE_STARTED) && stuff->type == XPPageAttr) + return XpErrorBase+XPBadSequence; + + if((attr = (char *)malloc(stuff->stringLen + 1)) == (char *)NULL) + return BadAlloc; + + strncpy(attr, (char *)(stuff + 1), stuff->stringLen); + attr[stuff->stringLen] = (char)'\0'; + + if(stuff->rule == XPAttrReplace) + (*pContext->funcs.SetAttributes)(pContext, stuff->type, attr); + else if(stuff->rule == XPAttrMerge) + (*pContext->funcs.AugmentAttributes)(pContext, stuff->type, attr); + else + { + client->errorValue = stuff->rule; + result = BadValue; + } + + xfree(attr); + + SendAttributeNotify(pContext, stuff->type); + + return result; +} + +static int +ProcXpGetOneAttribute(ClientPtr client) +{ + REQUEST(xPrintGetOneAttributeReq); + XpContextPtr pContext; + char *value, *attrName; + xPrintGetOneAttributeReply *pRep; + int totalSize; + int n; + unsigned long l; + + REQUEST_AT_LEAST_SIZE(xPrintGetOneAttributeReq); + + totalSize = ((sz_xPrintGetOneAttributeReq) >> 2) + + ((stuff->nameLen + 3) >> 2); + if(totalSize != client->req_len) + return BadLength; + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + if((attrName = (char *)malloc(stuff->nameLen + 1)) == (char *)NULL) + return BadAlloc; + strncpy(attrName, (char *)(stuff+1), stuff->nameLen); + attrName[stuff->nameLen] = (char)'\0'; + + if(stuff->type != XPServerAttr) + { + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetOneAttribute == 0) + return BadImplementation; + if((value = (*pContext->funcs.GetOneAttribute)(pContext, stuff->type, + attrName)) == (char *)NULL) + return BadAlloc; + } + else + { + if((value = XpGetOneAttribute((XpContextPtr)NULL, XPServerAttr, + attrName)) == (char *)NULL) + return BadAlloc; + } + + free(attrName); + + totalSize = sz_xPrintGetOneAttributeReply + QUADPAD(strlen(value)); + if((pRep = (xPrintGetOneAttributeReply *)malloc(totalSize)) == + (xPrintGetOneAttributeReply *)NULL) + return BadAlloc; + + pRep->type = X_Reply; + pRep->length = (totalSize - sz_xPrintGetOneAttributeReply) >> 2; + pRep->sequenceNumber = client->sequence; + pRep->valueLen = strlen(value); + + if (client->swapped) { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, l); + swapl(&pRep->valueLen, l); + } + + strncpy((char*)(pRep + 1), value, strlen(value)); + + WriteToClient(client, totalSize, (char *)pRep); + + xfree(pRep); + + return client->noClientException; +} + +/******************************************************************************* + * + * Print Event requests: SelectInput InputSelected, SendXpNotify + * + ******************************************************************************/ + + +static int +ProcXpSelectInput(ClientPtr client) +{ + REQUEST(xPrintSelectInputReq); + int result = Success; + XpContextPtr pContext; + XpClientPtr pPrintClient; + + REQUEST_SIZE_MATCH(xPrintSelectInputReq); + + /* + * Check to see that the supplied XID is really a valid print context + * in this server. + */ + if((pContext=(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(stuff->eventMask & ~allEvents) + { + client->errorValue = stuff->eventMask; + return BadValue; /* bogus event mask bits */ + } + + if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL) + return BadAlloc; + + pPrintClient->eventMask = stuff->eventMask; + + return result; +} + +static int +ProcXpInputSelected(ClientPtr client) +{ + REQUEST(xPrintInputSelectedReq); + xPrintInputSelectedReply rep; + register int n; + long l; + XpClientPtr pXpClient; + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintInputSelectedReq); + + if((pContext=(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + pXpClient = FindClient(pContext, client); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.eventMask = (pXpClient != (XpClientPtr)NULL)? pXpClient->eventMask : 0; + rep.allEventsMask = GetAllEventMasks(pContext); + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.eventMask, l); + swapl(&rep.allEventsMask, l); + } + + WriteToClient(client, sz_xPrintInputSelectedReply, (char *)&rep); + return client->noClientException; +} + +static void +SendAttributeNotify(XpContextPtr pContext, int which) +{ + XpClientPtr pXpClient; + xPrintAttributeEvent ae; + ClientPtr client; + + pXpClient = pContext->clientHead; + if(pXpClient == (XpClientPtr)NULL) + return; /* Nobody's interested in the events (or this context). */ + + for (pXpClient = pContext->clientHead; + pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + client = pXpClient->client; + if (client == serverClient || client->clientGone || + !(pXpClient->eventMask & XPAttributeMask)) + continue; + ae.type = XPAttributeNotify + XpEventBase; + ae.detail = which; + ae.printContext = pContext->contextID; + ae.sequenceNumber = client->sequence; + WriteEventsToClient (client, 1, (xEvent *) &ae); + } +} + +static void +SendXpNotify(XpContextPtr pContext, int which, int val) +{ + XpClientPtr pXpClient; + xPrintPrintEvent pe; + ClientPtr client; + + pXpClient = pContext->clientHead; + if(pXpClient == (XpClientPtr)NULL) + return; /* Nobody's interested in the events (or this context). */ + + for (pXpClient = pContext->clientHead; + pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + client = pXpClient->client; + if (client == serverClient || client->clientGone || + !(pXpClient->eventMask & XPPrintMask)) + continue; + pe.type = XPPrintNotify + XpEventBase; + pe.detail = which; + pe.printContext = pContext->contextID; + pe.cancel = (Bool)val; + pe.sequenceNumber = client->sequence; + WriteEventsToClient (client, 1, (xEvent *) &pe); + } +} + +static CARD32 +GetAllEventMasks(XpContextPtr pContext) +{ + XpClientPtr pPrintClient; + CARD32 totalMask = (CARD32)0; + + for (pPrintClient = pContext->clientHead; + pPrintClient != (XpClientPtr)NULL; + pPrintClient = pPrintClient->pNext) + { + totalMask |= pPrintClient->eventMask; + } + return totalMask; +} + +/* + * XpContextOfClient - returns the XpContextPtr to the context + * associated with the specified client, or NULL if the client + * does not currently have a context set. + */ +XpContextPtr +XpContextOfClient(ClientPtr client) +{ + return (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr; +} + + +/******************************************************************************* + * + * Swap-request functions + * + ******************************************************************************/ + +static int +SProcXpCreateContext(ClientPtr client) +{ + int i; + long n; + + REQUEST(xPrintCreateContextReq); + + swaps(&stuff->length, i); + swapl(&stuff->contextID, n); + swapl(&stuff->printerNameLen, n); + swapl(&stuff->localeLen, n); + return ProcXpCreateContext(client); +} + +static int +SProcXpGetPrinterList(ClientPtr client) +{ + int i; + long n; + + REQUEST(xPrintGetPrinterListReq); + + swaps(&stuff->length, i); + swapl(&stuff->printerNameLen, n); + swapl(&stuff->localeLen, n); + return ProcXpGetPrinterList(client); +} + +static int +SProcXpRehashPrinterList(ClientPtr client) +{ + int i; + + REQUEST(xPrintRehashPrinterListReq); + swaps(&stuff->length, i); + return ProcXpRehashPrinterList(client); +} + +static int +SProcXpSetContext(ClientPtr client) +{ + int i; + + REQUEST(xPrintSetContextReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, i); + return ProcXpSetContext(client); +} + +static int +SProcXpGetContext(ClientPtr client) +{ + int i; + + REQUEST(xPrintGetContextReq); + swaps(&stuff->length, i); + return ProcXpGetContext(client); +} + +static int +SProcXpDestroyContext(ClientPtr client) +{ + int i; + long n; + + REQUEST(xPrintDestroyContextReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpDestroyContext(client); +} + +static int +SProcXpGetContextScreen(ClientPtr client) +{ + int i; + long n; + + REQUEST(xPrintGetContextScreenReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetContextScreen(client); +} + +static int +SProcXpInputSelected(ClientPtr client) +{ + int i; + long n; + + REQUEST(xPrintInputSelectedReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpInputSelected(client); +} + +static int +SProcXpStartJob(ClientPtr client) +{ + int i; + + REQUEST(xPrintStartJobReq); + swaps(&stuff->length, i); + return ProcXpStartJob(client); +} + +static int +SProcXpEndJob(ClientPtr client) +{ + int i; + + REQUEST(xPrintEndJobReq); + swaps(&stuff->length, i); + return ProcXpEndJob(client); +} + +static int +SProcXpStartDoc(ClientPtr client) +{ + int i; + + REQUEST(xPrintStartDocReq); + swaps(&stuff->length, i); + return ProcXpStartDoc(client); +} + +static int +SProcXpEndDoc(ClientPtr client) +{ + int i; + + REQUEST(xPrintEndDocReq); + swaps(&stuff->length, i); + return ProcXpEndDoc(client); +} + +static int +SProcXpStartPage(ClientPtr client) +{ + int i; + long n; + + REQUEST(xPrintStartPageReq); + swaps(&stuff->length, i); + swapl(&stuff->window, n); + return ProcXpStartPage(client); +} + +static int +SProcXpEndPage(ClientPtr client) +{ + int i; + + REQUEST(xPrintEndPageReq); + swaps(&stuff->length, i); + return ProcXpEndPage(client); +} + +static int +SProcXpPutDocumentData(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintPutDocumentDataReq); + swaps(&stuff->length, i); + swapl(&stuff->drawable, n); + swapl(&stuff->len_data, n); + swaps(&stuff->len_fmt, i); + swaps(&stuff->len_options, i); + return ProcXpPutDocumentData(client); +} + +static int +SProcXpGetDocumentData(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintGetDocumentDataReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->maxBufferSize, n); + return ProcXpGetDocumentData(client); +} + +static int +SProcXpGetAttributes(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintGetAttributesReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetAttributes(client); +} + +static int +SProcXpSetAttributes(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintSetAttributesReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->stringLen, n); + return ProcXpSetAttributes(client); +} + +static int +SProcXpGetOneAttribute(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintGetOneAttributeReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->nameLen, n); + return ProcXpGetOneAttribute(client); +} + +static int +SProcXpSelectInput(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintSelectInputReq); + swaps(&stuff->length, i); + swapl(&stuff->eventMask, n); + swapl(&stuff->printContext, n); + return ProcXpSelectInput(client); +} + +static int +SProcXpGetPageDimensions(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintGetPageDimensionsReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetPageDimensions(client); +} + +static int +SProcXpSetImageResolution(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintSetImageResolutionReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swaps(&stuff->imageRes, i); + return ProcXpSetImageResolution(client); +} + +static int +SProcXpGetImageResolution(ClientPtr client) +{ + long n; + int i; + + REQUEST(xPrintGetImageResolutionReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetImageResolution(client); +} + +static void +SwapXpNotifyEvent(xPrintPrintEvent *src, xPrintPrintEvent *dst) +{ + /* + * Swap the sequence number and context fields. + */ + cpswaps(src->sequenceNumber, dst->sequenceNumber); + cpswapl(src->printContext, dst->printContext); + + /* + * Copy the byte-long fields. + */ + dst->type = src->type; + dst->detail = src->detail; + dst->cancel = src->cancel; +} + +static void +SwapXpAttributeEvent(xPrintAttributeEvent *src, xPrintAttributeEvent *dst) +{ + /* + * Swap the sequence number and context fields. + */ + cpswaps(src->sequenceNumber, dst->sequenceNumber); + cpswapl(src->printContext, dst->printContext); + + /* + * Copy the byte-long fields. + */ + dst->type = src->type; + dst->detail = src->detail; +} diff --git a/nx-X11/programs/Xserver/Xext/xres.c b/nx-X11/programs/Xserver/Xext/xres.c new file mode 100644 index 000000000..d13d3368b --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xres.c @@ -0,0 +1,339 @@ +/* + Copyright (c) 2002 XFree86 Inc +*/ +/* $XFree86: xc/programs/Xserver/Xext/xres.c,v 1.7tsi Exp $ */ +/* $XdotOrg: xc/programs/Xserver/Xext/xres.c,v 1.7 2005/07/03 08:53:36 daniels Exp $ */ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "swaprep.h" +#include <X11/extensions/XResproto.h> +#include "pixmapstr.h" +#include "modinit.h" + +static int +ProcXResQueryVersion (ClientPtr client) +{ + REQUEST(xXResQueryVersionReq); + xXResQueryVersionReply rep; + CARD16 client_major, client_minor; /* not used */ + + REQUEST_SIZE_MATCH (xXResQueryVersionReq); + + client_major = stuff->client_major; + client_minor = stuff->client_minor; + (void) client_major; + (void) client_minor; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.server_major = XRES_MAJOR_VERSION; + rep.server_minor = XRES_MINOR_VERSION; + if (client->swapped) { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.server_major, n); + swaps(&rep.server_minor, n); + } + WriteToClient(client, sizeof (xXResQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXResQueryClients (ClientPtr client) +{ + /* REQUEST(xXResQueryClientsReq); */ + xXResQueryClientsReply rep; + int *current_clients; + int i, num_clients; + + REQUEST_SIZE_MATCH(xXResQueryClientsReq); + + current_clients = ALLOCATE_LOCAL((currentMaxClients - 1) * sizeof(int)); + + num_clients = 0; + for(i = 1; i < currentMaxClients; i++) { + if(clients[i]) { + current_clients[num_clients] = i; + num_clients++; + } + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_clients = num_clients; + rep.length = rep.num_clients * sz_xXResClient >> 2; + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.num_clients, n); + } + WriteToClient (client, sizeof (xXResQueryClientsReply), (char *) &rep); + + if(num_clients) { + xXResClient scratch; + + for(i = 0; i < num_clients; i++) { + scratch.resource_base = clients[current_clients[i]]->clientAsMask; + scratch.resource_mask = RESOURCE_ID_MASK; + + if(client->swapped) { + register int n; + swapl (&scratch.resource_base, n); + swapl (&scratch.resource_mask, n); + } + WriteToClient (client, sz_xXResClient, (char *) &scratch); + } + } + + DEALLOCATE_LOCAL(current_clients); + + return (client->noClientException); +} + + +static void +ResFindAllRes (pointer value, XID id, RESTYPE type, pointer cdata) +{ + int *counts = (int *)cdata; + + counts[(type & TypeMask) - 1]++; +} + +static int +ProcXResQueryClientResources (ClientPtr client) +{ + REQUEST(xXResQueryClientResourcesReq); + xXResQueryClientResourcesReply rep; + int i, clientID, num_types; + int *counts; + + REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); + + clientID = CLIENT_ID(stuff->xid); + + /* we could remove the (clientID == 0) check if we wanted to allow + probing the X-server's resource usage */ + if(!clientID || (clientID >= currentMaxClients) || !clients[clientID]) { + client->errorValue = stuff->xid; + return BadValue; + } + + counts = ALLOCATE_LOCAL((lastResourceType + 1) * sizeof(int)); + + memset(counts, 0, (lastResourceType + 1) * sizeof(int)); + + FindAllClientResources(clients[clientID], ResFindAllRes, counts); + + num_types = 0; + + for(i = 0; i <= lastResourceType; i++) { + if(counts[i]) num_types++; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_types = num_types; + rep.length = rep.num_types * sz_xXResType >> 2; + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.num_types, n); + } + WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep); + + if(num_types) { + xXResType scratch; + + for(i = 0; i < lastResourceType; i++) { + if(!counts[i]) continue; + + if(!ResourceNames[i + 1]) { + char buf[40]; + snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1); + RegisterResourceName(i + 1, buf); + } + + scratch.resource_type = ResourceNames[i + 1]; + scratch.count = counts[i]; + + if(client->swapped) { + register int n; + swapl (&scratch.resource_type, n); + swapl (&scratch.count, n); + } + WriteToClient (client, sz_xXResType, (char *) &scratch); + } + } + + DEALLOCATE_LOCAL(counts); + + return (client->noClientException); +} + +static void +ResFindPixmaps (pointer value, XID id, pointer cdata) +{ + unsigned long *bytes = (unsigned long *)cdata; + PixmapPtr pix = (PixmapPtr)value; + + *bytes += (pix->devKind * pix->drawable.height); +} + +static int +ProcXResQueryClientPixmapBytes (ClientPtr client) +{ + REQUEST(xXResQueryClientPixmapBytesReq); + xXResQueryClientPixmapBytesReply rep; + int clientID; + unsigned long bytes; + + REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); + + clientID = CLIENT_ID(stuff->xid); + + /* we could remove the (clientID == 0) check if we wanted to allow + probing the X-server's resource usage */ + if(!clientID || (clientID >= currentMaxClients) || !clients[clientID]) { + client->errorValue = stuff->xid; + return BadValue; + } + + bytes = 0; + + FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps, + (pointer)(&bytes)); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.bytes = bytes; +#ifdef XSERVER64 + rep.bytes_overflow = bytes >> 32; +#else + rep.bytes_overflow = 0; +#endif + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.bytes, n); + swapl (&rep.bytes_overflow, n); + } + WriteToClient (client,sizeof(xXResQueryClientPixmapBytesReply),(char*)&rep); + + return (client->noClientException); +} + + +static void +ResResetProc (ExtensionEntry *extEntry) { } + +static int +ProcResDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XResQueryVersion: + return ProcXResQueryVersion(client); + case X_XResQueryClients: + return ProcXResQueryClients(client); + case X_XResQueryClientResources: + return ProcXResQueryClientResources(client); + case X_XResQueryClientPixmapBytes: + return ProcXResQueryClientPixmapBytes(client); + default: break; + } + + return BadRequest; +} + +static int +SProcXResQueryVersion (ClientPtr client) +{ + REQUEST(xXResQueryVersionReq); + int n; + + REQUEST_SIZE_MATCH (xXResQueryVersionReq); + swaps(&stuff->client_major,n); + swaps(&stuff->client_minor,n); + return ProcXResQueryVersion(client); +} + +static int +SProcXResQueryClientResources (ClientPtr client) +{ + REQUEST(xXResQueryClientResourcesReq); + int n; + + REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq); + swaps(&stuff->xid,n); + return ProcXResQueryClientResources(client); +} + +static int +SProcXResQueryClientPixmapBytes (ClientPtr client) +{ + REQUEST(xXResQueryClientPixmapBytesReq); + int n; + + REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq); + swaps(&stuff->xid,n); + return ProcXResQueryClientPixmapBytes(client); +} + +static int +SProcResDispatch (ClientPtr client) +{ + REQUEST(xReq); + int n; + + swaps(&stuff->length,n); + + switch (stuff->data) { + case X_XResQueryVersion: + return SProcXResQueryVersion(client); + case X_XResQueryClients: /* nothing to swap */ + return ProcXResQueryClients(client); + case X_XResQueryClientResources: + return SProcXResQueryClientResources(client); + case X_XResQueryClientPixmapBytes: + return SProcXResQueryClientPixmapBytes(client); + default: break; + } + + return BadRequest; +} + +void +ResExtensionInit(INITARGS) +{ + (void) AddExtension(XRES_NAME, 0, 0, + ProcResDispatch, SProcResDispatch, + ResResetProc, StandardMinorOpcode); + + RegisterResourceName(RT_NONE, "NONE"); + RegisterResourceName(RT_WINDOW, "WINDOW"); + RegisterResourceName(RT_PIXMAP, "PIXMAP"); + RegisterResourceName(RT_GC, "GC"); + RegisterResourceName(RT_FONT, "FONT"); + RegisterResourceName(RT_CURSOR, "CURSOR"); + RegisterResourceName(RT_COLORMAP, "COLORMAP"); + RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY"); + RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT"); + RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB"); +} diff --git a/nx-X11/programs/Xserver/Xext/xtest.c b/nx-X11/programs/Xserver/Xext/xtest.c new file mode 100644 index 000000000..994b0c502 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xtest.c @@ -0,0 +1,608 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/xtest.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */ +/* $Xorg: xtest.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. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/xtest.c,v 3.10 2003/10/28 23:08:44 tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#define NEED_EVENTS +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "dixevents.h" +#include "sleepuntil.h" +#define _XTEST_SERVER_ +#include <X11/extensions/XTest.h> +#include <X11/extensions/xteststr.h> +#ifdef XINPUT +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#define EXTENSION_EVENT_BASE 64 +#include "extinit.h" /* LookupDeviceIntRec */ +#endif /* XINPUT */ +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#include "modinit.h" + +#if 0 +static unsigned char XTestReqCode; +#endif + +#ifdef XINPUT +extern int DeviceValuator; +#endif /* XINPUT */ + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +static void XTestResetProc( + ExtensionEntry * /* extEntry */ +); +static int XTestSwapFakeInput( + ClientPtr /* client */, + xReq * /* req */ +); + +static DISPATCH_PROC(ProcXTestCompareCursor); +static DISPATCH_PROC(ProcXTestDispatch); +static DISPATCH_PROC(ProcXTestFakeInput); +static DISPATCH_PROC(ProcXTestGetVersion); +static DISPATCH_PROC(ProcXTestGrabControl); +static DISPATCH_PROC(SProcXTestCompareCursor); +static DISPATCH_PROC(SProcXTestDispatch); +static DISPATCH_PROC(SProcXTestFakeInput); +static DISPATCH_PROC(SProcXTestGetVersion); +static DISPATCH_PROC(SProcXTestGrabControl); + +void +XTestExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XTestExtensionName, 0, 0, + ProcXTestDispatch, SProcXTestDispatch, + XTestResetProc, StandardMinorOpcode)) != 0) + XTestReqCode = (unsigned char)extEntry->base; +#else + (void) AddExtension(XTestExtensionName, 0, 0, + ProcXTestDispatch, SProcXTestDispatch, + XTestResetProc, StandardMinorOpcode); +#endif +} + +/*ARGSUSED*/ +static void +XTestResetProc (extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcXTestGetVersion(client) + register ClientPtr client; +{ + xXTestGetVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XTestMajorVersion; + rep.minorVersion = XTestMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXTestCompareCursor(client) + register ClientPtr client; +{ + REQUEST(xXTestCompareCursorReq); + xXTestCompareCursorReply rep; + WindowPtr pWin; + CursorPtr pCursor; + register int n; + + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + pWin = (WindowPtr)LookupWindow(stuff->window, client); + if (!pWin) + return(BadWindow); + if (stuff->cursor == None) + pCursor = NullCursor; + else if (stuff->cursor == XTestCurrentCursor) + pCursor = GetSpriteCursor(); + else { + pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR); + if (!pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.same = (wCursor(pWin) == pCursor); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep); + return(client->noClientException); +} + +static int +ProcXTestFakeInput(client) + register ClientPtr client; +{ + REQUEST(xXTestFakeInputReq); + int nev; + int n; + xEvent *ev; + DeviceIntPtr dev = NULL; + WindowPtr root; + int type; +#ifdef XINPUT + Bool extension = FALSE; + deviceValuator *dv = NULL; + int base; + int *values; +#endif /* XINPUT */ + + nev = (stuff->length << 2) - sizeof(xReq); + if ((nev % sizeof(xEvent)) || !nev) + return BadLength; + nev /= sizeof(xEvent); + UpdateCurrentTime(); + ev = (xEvent *)&((xReq *)stuff)[1]; + type = ev->u.u.type & 0177; +#ifdef XINPUT + if (type >= EXTENSION_EVENT_BASE) + { + type -= DeviceValuator; + switch (type) { + case XI_DeviceKeyPress: + case XI_DeviceKeyRelease: + case XI_DeviceButtonPress: + case XI_DeviceButtonRelease: + case XI_DeviceMotionNotify: + case XI_ProximityIn: + case XI_ProximityOut: + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + if (nev == 1 && type == XI_DeviceMotionNotify) + return BadLength; + if (type == XI_DeviceMotionNotify) + base = ((deviceValuator *)(ev+1))->first_valuator; + else + base = 0; + for (n = 1; n < nev; n++) + { + dv = (deviceValuator *)(ev + n); + if (dv->type != DeviceValuator) + { + client->errorValue = dv->type; + return BadValue; + } + if (dv->first_valuator != base) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + if (!dv->num_valuators || dv->num_valuators > 6) + { + client->errorValue = dv->num_valuators; + return BadValue; + } + base += dv->num_valuators; + } + type = type - XI_DeviceKeyPress + KeyPress; + extension = TRUE; + } + else +#endif /* XINPUT */ + { + if (nev != 1) + return BadLength; + switch (type) + { + case KeyPress: + case KeyRelease: + case MotionNotify: + case ButtonPress: + case ButtonRelease: + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + } + if (ev->u.keyButtonPointer.time) + { + TimeStamp activateTime; + CARD32 ms; + + activateTime = currentTime; + ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; + if (ms < activateTime.milliseconds) + activateTime.months++; + activateTime.milliseconds = ms; + ev->u.keyButtonPointer.time = 0; + + /* see mbuf.c:QueueDisplayRequest for code similar to this */ + + if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) + { + return BadAlloc; + } + /* swap the request back so we can simply re-execute it */ + if (client->swapped) + { + (void) XTestSwapFakeInput(client, (xReq *)stuff); + swaps(&stuff->length, n); + } + ResetCurrentRequest (client); + client->sequence--; + return Success; + } +#ifdef XINPUT + if (extension) + { + dev = LookupDeviceIntRec(stuff->deviceid & 0177); + if (!dev) + { + client->errorValue = stuff->deviceid & 0177; + return BadValue; + } + if (nev > 1) + { + dv = (deviceValuator *)(ev + 1); + if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + if (dv->first_valuator + dv->num_valuators > + dev->valuator->numAxes) + { + client->errorValue = dv->num_valuators; + return BadValue; + } + } + } +#endif /* XINPUT */ + switch (type) + { + case KeyPress: + case KeyRelease: +#ifdef XINPUT + if (!extension) +#endif /* XINPUT */ + dev = (DeviceIntPtr)LookupKeyboardDevice(); + if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode || + ev->u.u.detail > dev->key->curKeySyms.maxKeyCode) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + case MotionNotify: +#ifdef XINPUT + if (extension) + { + if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute) + { + values = dev->valuator->axisVal + dv->first_valuator; + for (n = 1; n < nev; n++) + { + dv = (deviceValuator *)(ev + n); + switch (dv->num_valuators) + { + case 6: + dv->valuator5 += values[5]; + case 5: + dv->valuator4 += values[4]; + case 4: + dv->valuator3 += values[3]; + case 3: + dv->valuator2 += values[2]; + case 2: + dv->valuator1 += values[1]; + case 1: + dv->valuator0 += values[0]; + } + values += 6; + } + } + break; + } +#endif /* XINPUT */ + dev = (DeviceIntPtr)LookupPointerDevice(); + if (ev->u.keyButtonPointer.root == None) + root = GetCurrentRootWindow(); + else + { + root = LookupWindow(ev->u.keyButtonPointer.root, client); + if (!root) + return BadWindow; + if (root->parent) + { + client->errorValue = ev->u.keyButtonPointer.root; + return BadValue; + } + } + if (ev->u.u.detail == xTrue) + { + int x, y; + GetSpritePosition(&x, &y); + ev->u.keyButtonPointer.rootX += x; + ev->u.keyButtonPointer.rootY += y; + } + else if (ev->u.u.detail != xFalse) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + ScreenPtr pScreen = root->drawable.pScreen; + BoxRec box; + int i; + int x = ev->u.keyButtonPointer.rootX + panoramiXdataPtr[0].x; + int y = ev->u.keyButtonPointer.rootY + panoramiXdataPtr[0].y; + if (!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) { + FOR_NSCREENS(i) { + if (i == pScreen->myNum) continue; + if (POINT_IN_REGION(pScreen, + &XineramaScreenRegions[i], + x, y, &box)) { + root = WindowTable[i]; + x -= panoramiXdataPtr[i].x; + y -= panoramiXdataPtr[i].y; + ev->u.keyButtonPointer.rootX = x; + ev->u.keyButtonPointer.rootY = y; + break; + } + } + } + } +#endif + + if (ev->u.keyButtonPointer.rootX < 0) + ev->u.keyButtonPointer.rootX = 0; + else if (ev->u.keyButtonPointer.rootX >= root->drawable.width) + ev->u.keyButtonPointer.rootX = root->drawable.width - 1; + if (ev->u.keyButtonPointer.rootY < 0) + ev->u.keyButtonPointer.rootY = 0; + else if (ev->u.keyButtonPointer.rootY >= root->drawable.height) + ev->u.keyButtonPointer.rootY = root->drawable.height - 1; + +#ifdef PANORAMIX + if ((!noPanoramiXExtension + && root->drawable.pScreen->myNum != XineramaGetCursorScreen()) + || (noPanoramiXExtension && root != GetCurrentRootWindow())) + +#else + if (root != GetCurrentRootWindow()) +#endif + { + NewCurrentScreen(root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, + ev->u.keyButtonPointer.rootY); + return client->noClientException; + } + (*root->drawable.pScreen->SetCursorPosition) + (root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, + ev->u.keyButtonPointer.rootY, FALSE); + break; + case ButtonPress: + case ButtonRelease: +#ifdef XINPUT + if (!extension) +#endif /* XINPUT */ + dev = (DeviceIntPtr)LookupPointerDevice(); + if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + } + if (screenIsSaved == SCREEN_SAVER_ON) + SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset); + ev->u.keyButtonPointer.time = currentTime.milliseconds; + (*dev->public.processInputProc)(ev, dev, nev); + return client->noClientException; +} + +static int +ProcXTestGrabControl(client) + register ClientPtr client; +{ + REQUEST(xXTestGrabControlReq); + + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) + { + client->errorValue = stuff->impervious; + return(BadValue); + } + if (stuff->impervious) + MakeClientGrabImpervious(client); + else + MakeClientGrabPervious(client); + return(client->noClientException); +} + +static int +ProcXTestDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return ProcXTestGetVersion(client); + case X_XTestCompareCursor: + return ProcXTestCompareCursor(client); + case X_XTestFakeInput: + return ProcXTestFakeInput(client); + case X_XTestGrabControl: + return ProcXTestGrabControl(client); + default: + return BadRequest; + } +} + +static int +SProcXTestGetVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXTestGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + swaps(&stuff->minorVersion, n); + return ProcXTestGetVersion(client); +} + +static int +SProcXTestCompareCursor(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXTestCompareCursorReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + swapl(&stuff->window, n); + swapl(&stuff->cursor, n); + return ProcXTestCompareCursor(client); +} + +static int +XTestSwapFakeInput(client, req) + register ClientPtr client; + xReq *req; +{ + register int nev; + register xEvent *ev; + xEvent sev; + EventSwapPtr proc; + + nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); + for (ev = (xEvent *)&req[1]; --nev >= 0; ev++) + { + /* Swap event */ + proc = EventSwapVector[ev->u.u.type & 0177]; + /* no swapping proc; invalid event type? */ + if (!proc || proc == NotImplemented) { + client->errorValue = ev->u.u.type; + return BadValue; + } + (*proc)(ev, &sev); + *ev = sev; + } + return Success; +} + +static int +SProcXTestFakeInput(client) + register ClientPtr client; +{ + register int n; + REQUEST(xReq); + + swaps(&stuff->length, n); + n = XTestSwapFakeInput(client, stuff); + if (n != Success) + return n; + return ProcXTestFakeInput(client); +} + +static int +SProcXTestGrabControl(client) + register ClientPtr client; +{ + register int n; + REQUEST(xXTestGrabControlReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + return ProcXTestGrabControl(client); +} + +static int +SProcXTestDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return SProcXTestGetVersion(client); + case X_XTestCompareCursor: + return SProcXTestCompareCursor(client); + case X_XTestFakeInput: + return SProcXTestFakeInput(client); + case X_XTestGrabControl: + return SProcXTestGrabControl(client); + default: + return BadRequest; + } +} diff --git a/nx-X11/programs/Xserver/Xext/xtest1.frags b/nx-X11/programs/Xserver/Xext/xtest1.frags new file mode 100644 index 000000000..bdf7943b7 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xtest1.frags @@ -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/nx-X11/programs/Xserver/Xext/xtest1dd.c b/nx-X11/programs/Xserver/Xext/xtest1dd.c new file mode 100644 index 000000000..81d283c36 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xtest1dd.c @@ -0,0 +1,1617 @@ +/* $Xorg: xtest1dd.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + * File: xtest1dd.c + * + * This file contains the device dependent parts of the input + * synthesis extension. + */ + +/* + + +Copyright 1986, 1987, 1988, 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 1986, 1987, 1988 by Hewlett-Packard Corporation + +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 Hewlett-Packard not be used in +advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +Hewlett-Packard makes no representations about the +suitability of this software for any purpose. It is provided +"as is" without express or implied warranty. + +This software is not subject to any license of the American +Telephone and Telegraph Company or of the Regents of the +University of California. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/xtest1dd.c,v 3.6 2003/10/28 23:08:44 tsi Exp $ */ + +/*************************************************************** + * include files + ***************************************************************/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/Xos.h> +#include <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#define XTestSERVER_SIDE +#include <X11/extensions/xtestext1.h> + +#include "xtest1dd.h" + +/*************************************************************** + * defines + ***************************************************************/ + +/* + * the size of the fake input action array + */ +#define ACTION_ARRAY_SIZE 100 + +/*************************************************************** + * externals + ***************************************************************/ + +/* + * Holds the xTestInputAction event type code. + * This is defined in xtestext1di.c. + */ +extern int XTestInputActionType; +/* + * Holds the xTestFakeAck event type code. + * This is defined in xtestext1di.c. + */ +extern int XTestFakeAckType; +/* + * used in the WriteReplyToClient macro + */ +extern int exclusive_steal; + +/*************************************************************** + * variables + ***************************************************************/ + +/* + * array to hold fake input actions + */ +struct { + /* + * holds the action type, one of: XTestDELAY_ACTION, + * XTestKEY_ACTION, XTestMOTION_ACTION, XTestJUMP_ACTION + */ + CARD8 type; + /* + * holds the device type, in the range 0 to 15 + */ + CARD8 device; + /* + * for XTestKEY_ACTION type, holds the keycode + */ + CARD8 keycode; + /* + * for XTestKEY_ACTION type, holds the key up/down state + */ + CARD8 keystate; + /* + * for XTestMOTION_ACTION and XTestJUMP_ACTION types, + * holds the x and y coordinates to move the mouse to + */ + int x; + int y; + /* + * holds the time to delay (in milliseconds) before performing + * the action + */ + CARD32 delay_time; +}action_array[ACTION_ARRAY_SIZE]; + +/* + * write index for input action array + */ +static int write_index = 0; +/* + * read index for input action array + */ +static int read_index = 0; +/* + * this is where the input actions are accumulated until they are sent + * to a client (in a wire event) + */ +static xTestInputActionEvent input_action_packet; +/* + * holds the index (in bytes) into the input actions buffer in the + * current input action event + */ +static int packet_index; +/* + * logical x position of the mouse during input action gathering + */ +short xtest_mousex; +/* + * logical y position of the mouse during input action gathering + */ +short xtest_mousey; +/* + * logical x position of the mouse while we are reading fake input actions + * from the client and putting them into the fake input action array + */ +static short pmousex; +/* + * logical y position of the mouse while we are reading fake input actions + * from the client and putting them into the fake input action array + */ +static short pmousey; +/* + * The playback_on flag is set to 1 while there are input actions in the + * input action array. It is set to 0 when the server has received all of + * the user actions. + */ +int playback_on = 0; +/* + * identity of the client using XTestGetInput to get user input actions + */ +ClientPtr current_xtest_client; +/* + * if 1 send multiple input actions per XTestInputAction event; + * if 0 send one input action per XTestInputAction event + */ +static char packed_mode; +/* + * identity of the client using the XTestFakeInput function to send some + * fake input actions to the server + */ +ClientPtr playback_client = NULL; +/* + * Set to 1 when the XTestFAKE_ACK_REQUEST flag is set in a XTestFakeInput + * request. Set back to 0 when all of the input actions have been sent + * to the server. + */ +static int acknowledge = 0; +/* + * The server's idea of the current time is saved in these variables when + * a XTestFakeInput request is received. It is restored when all fake input + * actions are sent to the server or when the playback client disconnects. + */ +static int saved_sec; +static int saved_usec; +/* + * Set to 1 when there is a valid time in saved_sec and saved_usec. + */ +static int time_saved = 0; +/* + * holds the extension's notion of what the current time is while it is + * sending input actions to a client + */ +static struct timeval current_time; +/* + * holds the time when the extension should place the next fake input action + * into the server's normal events queue + */ +static struct timeval play_time; +/* + * set to 1 when play_time is first set, cleared to 0 when the + * client using the extension disconnects, or when XTestReset is called + */ +static char play_clock = 0; +/* + * holds the amount of time left until the next input action from the + * input action array can be sent to the server + */ +static struct timeval rtime; +/* + * Set to 1 after the extension is done waiting for the correct time delay + * for an input action to be sent to the server. Remains a 1 until the time + * delay for the next input action is computed. Then set to 0 if the + * extension has to wait for the correct time delay. + */ +static int go_for_next = 1; +/* + * needed to restore waitime if playback is to be aborted + */ +static struct timeval *restorewait; +/* + * tmon special command key + * + * To use the test monitor program (called tmon) efficiently, it is + * desirable to have the extension be able to recognize a special "trigger" + * key. If the extension did not do this, tmon would have to have the + * extension send all keyboard user input actions exclusively to tmon, + * only to have tmon send them right back if they were not the command key. + * + * If the extension can recognize the command key, then tmon can let the + * extension handle keyboard user input actions normally until the command + * key is pressed (and released), and only then have the extension start + * sending keyboard user input actions exclusively to tmon. + * + * Any key on the keyboard can be used for this command key. It is most + * convenient if it is a low-frequency key. If you want to generate a + * normal occurrance of this key to a client, just hit it twice. Tmon + * will recognize the first occurrance of the key, take control of the input + * actions, and wait for certain keys. If it sees another occurrance of the + * command key, it will send one occurrance of the command key to the + * extension, and go back to waiting. + * + * set and also referenced in device layer + * XXX there should be a way to set this through the protocol + */ +KeyCode xtest_command_key = 0; + +/*************************************************************** + * function declarations + ***************************************************************/ + +static void parse_key_fake( + XTestKeyInfo * /* fkey */ + ); +static void parse_motion_fake( + XTestMotionInfo * /* fmotion */ + ); +static void parse_jump_fake( + XTestJumpInfo * /* fjump */ + ); +static void parse_delay_fake( + XTestDelayInfo * /* tevent */ + ); +static void send_ack( + ClientPtr /* client */ + ); +static void start_play_clock( + void + ); +static void compute_action_time( + struct timeval * /* rtime */ + ); +static int find_residual_time( + struct timeval * /* rtime */ + ); + +static CARD16 check_time_event( + void + ); +static CARD32 current_ms( + struct timeval * /* otime */ + ); +static int there_is_room( + int /* actsize */ + ); + +/****************************************************************************** + * + * stop_stealing_input + * + * Stop stealing input actions. + */ +void +stop_stealing_input() +{ +/* + * put any code that you might need to stop stealing input actions here + */ + if (packet_index != 0) + { + /* + * if there is a partially full input action event waiting + * when this function is called, send it to the client + */ + flush_input_actions(); + } +} + +/****************************************************************************** + * + * steal_input + * + * Start stealing input actions and sending them to the passed-in client. + */ +void +steal_input(client, mode) +/* + * which client is to receive the input action events + */ +ClientPtr client; +/* + * what input action packing mode to use. one of 0, XTestPACKED_MOTION, + * or XTestPACKED_ACTIONS; optionally 'or'ed with XTestEXCLUSIVE, + */ +CARD32 mode; +{ + if (packet_index != 0) + { + /* + * if there is a partially full input action event waiting + * when this function is called, send it to the client + */ + flush_input_actions(); + } + else + { + /* + * otherwise, set up a new input action event + */ + input_action_packet.type = XTestInputActionType; + packet_index = 0; + } + /* + * set up the new input action packing mode + */ + packed_mode = mode & ~(XTestEXCLUSIVE); + /* + * keep track of where the mouse is + */ + XTestGetPointerPos(&xtest_mousex, &xtest_mousey); + /* + * keep track of which client is getting input actions + */ + current_xtest_client = client; + /* + * find out what time it is + */ + X_GETTIMEOFDAY(¤t_time); + /* + * jump to the initial position of the mouse, using a device type of 0. + */ + XTestStealJumpData(xtest_mousex, xtest_mousey, 0); +} + +/****************************************************************************** + * + * flush_input_actions + * + * Write the input actions event to the current requesting client + * and re-initialize the input action event. + */ +void +flush_input_actions() +{ + /* + * pointer to the input action event + */ + char *rep; + /* + * loop index + */ + int i; + + if (packet_index == 0) + { + /* + * empty input actions event + */ + return; + } + else if (packet_index < XTestACTIONS_SIZE) + { + /* + * fill to the end of the input actions event with 0's + */ + for (i = packet_index; i <XTestACTIONS_SIZE; i++) + { + input_action_packet.actions[i] = 0; + } + } + rep = (char *) (&input_action_packet); + + /* + * set the serial number of the input action event + */ + input_action_packet.sequenceNumber = current_xtest_client->sequence; + /* + * send the input action event to the client + */ + WriteEventsToClient(current_xtest_client, 1, (xEvent *) rep); + /* + * re-initialize the input action event + */ + input_action_packet.type = XTestInputActionType; + packet_index = 0; +} + +/****************************************************************************** + * + * XTestStealJumpData + * + * Create one or more input actions and put them in the input action + * event. The input actions will be an (maybe) XTestDELAY_ACTION + * and an XTestJUMP_ACTION. + */ +void +XTestStealJumpData(jx, jy, dev_type) +/* + * the x and y coordinates to jump to + */ +int jx; +int jy; +/* + * which device caused the jump + */ +int dev_type; +{ + XTestJumpInfo *jmp_ptr; + /* + * time delta (in ms) from previous event + */ + CARD16 tchar; + + /* + * Get the time delta from the previous event. If needed, + * the check_time_event routine will put an XTestDELAY_ACTION + * type action in the input action event. + */ + tchar = check_time_event(); + if (!there_is_room(sizeof(XTestJumpInfo))) + { + /* + * If there isn't room in the input action event for + * an XTestJUMP_ACTION, then send that event to the + * client and start filling an empty one. + */ + flush_input_actions(); + } + /* + * update the logical mouse position + */ + xtest_mousex = jx; + xtest_mousey = jy; + /* + * point jmp_ptr to the correct place in the input action event + */ + jmp_ptr = (XTestJumpInfo *) + &(input_action_packet.actions[packet_index]); + /* + * compute the input action header + */ + jmp_ptr->header = (XTestPackDeviceID(dev_type) | XTestJUMP_ACTION); + /* + * set the x and y coordinates to jump to in the input action + */ + jmp_ptr->jumpx = jx; + jmp_ptr->jumpy = jy; + /* + * set the delay time in the input action + */ + jmp_ptr->delay_time = tchar; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + sizeof(XTestJumpInfo); + if (packed_mode == 0) + { + /* + * if input actions are not packed, send the input + * action event to the client + */ + flush_input_actions(); + } +} + +/****************************************************************************** + * + * current_ms + * + * Returns the number of milliseconds from the passed-in time to the + * current time, and then updates the passed-in time to the current time. + */ +static CARD32 +current_ms(otime) +struct timeval *otime; +{ + struct timeval tval; + unsigned long the_ms; + unsigned long sec; + unsigned long usec; + + /* + * get the current time + */ + X_GETTIMEOFDAY(&tval); + if (tval.tv_usec < otime->tv_usec) + { + /* + * borrow a second's worth of microseconds if needed + */ + usec = tval.tv_usec - otime->tv_usec + 1000000; + sec = tval.tv_sec - 1 - otime->tv_sec; + } + else + { + usec = tval.tv_usec - otime->tv_usec; + sec = tval.tv_sec - otime->tv_sec; + } + /* + * update the passed-in time to the new time + */ + *otime = tval; + /* + * compute the number of milliseconds contained in + * 'sec' seconds and 'usec' microseconds + */ + the_ms = (sec * 1000000L + usec) / 1000L; + return (the_ms); +} + +/****************************************************************************** + * + * check_time_event + * + * If time delta is > XTestSHORT_DELAY_TIME then insert a time event + * and return 0; else return the delay time. + */ +static CARD16 +check_time_event() +{ + CARD32 tstamp; + CARD16 tchar; + XTestDelayInfo *tptr; + + /* + * get the number of milliseconds between input actions + */ + tstamp = current_ms(¤t_time); + /* + * if the number of milliseconds is too large to fit in a CARD16, + * then add a XTestDELAY_ACTION to the input action event. + */ + if (tstamp > XTestSHORT_DELAY_TIME) + { + /* + * If there isn't room in the input action event for + * an XTestDELAY_ACTION, then send that event to the + * client and start filling an empty one. + */ + if (!there_is_room(sizeof(XTestDelayInfo))) + { + flush_input_actions(); + } + /* + * point tptr to the correct place in the input action event + */ + tptr = (XTestDelayInfo *) + (&(input_action_packet.actions[packet_index])); + /* + * compute the input action header + */ + tptr->header = XTestPackDeviceID(XTestDELAY_DEVICE_ID) | + XTestDELAY_ACTION; + /* + * set the delay time in the input action + */ + tptr->delay_time = tstamp; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + (sizeof(XTestDelayInfo)); + if (packed_mode != XTestPACKED_ACTIONS) + { + /* + * if input actions are not packed, send the input + * action event to the client + */ + flush_input_actions(); + } + /* + * set the returned delay time to 0 + */ + tchar = 0; + } + else + { + /* + * set the returned delay time to the computed delay time + */ + tchar = tstamp; + } + return(tchar); +} + +/****************************************************************************** + * + * there_is_room + * + * Checks if there is room in the input_action_packet for an input action + * of the size actsize bytes. Returns 1 if there is space, 0 otherwise. + * + */ +static int +there_is_room(actsize) +/* + * the number of bytes of space needed + */ +int actsize; +{ + if ((packet_index + actsize) > XTestACTIONS_SIZE) + { + return(0); + } + else + { + return(1); + } +} + +/****************************************************************************** + * + * XTestStealMotionData + * + * Put motion information from the locator into an input action. + * + * called from x_hil.c + */ +void +XTestStealMotionData(dx, dy, dev_type, mx, my) +/* + * the x and y delta motion of the locator + */ +int dx; +int dy; +/* + * which locator did the moving + */ +int dev_type; +/* + * the x and y position of the locator before the delta motion + */ +int mx; +int my; +{ + /* + * pointer to a XTestMOTION_ACTION input action + */ + XTestMotionInfo *fm; + /* + * time delta from previous event + */ + CARD16 tchar; + + /* + * if the current position of the locator is not the same as + * the logical position, then update the logical position + */ + if ((mx != xtest_mousex) || (my != xtest_mousey)) + { + XTestStealJumpData(mx, my, dev_type); + } + /* + * if the delta motion is outside the range that can + * be held in a motion input action, use a jump input action + */ + if ((dx > XTestMOTION_MAX) || (dx < XTestMOTION_MIN) || + (dy > XTestMOTION_MAX) || (dy < XTestMOTION_MIN)) + { + XTestStealJumpData((xtest_mousex + dx), + (xtest_mousey + dy), dev_type); + } + else + { + /* + * compute the new logical position of the mouse + */ + xtest_mousex += dx; + xtest_mousey += dy; + /* + * Get the time delta from the previous event. If needed, + * the check_time_event routine will put an XTestDELAY_ACTION + * type action in the input action event. + */ + tchar = check_time_event(); + /* + * If there isn't room in the input action event for + * an XTestDELAY_ACTION, then send that event to the + * client and start filling an empty one. + */ + if (!there_is_room(sizeof(XTestMotionInfo))) + { + flush_input_actions(); + /* + * point fm to the correct place in the input action event + */ + } + fm = (XTestMotionInfo *) + &(input_action_packet.actions[packet_index]); + /* + * compute the input action header + */ + fm->header = XTestMOTION_ACTION; + if (dx < 0) + { + fm->header |= XTestX_NEGATIVE; + dx = abs(dx); + } + if (dy < 0) + { + fm->header |= XTestY_NEGATIVE; + dy = abs(dy); + } + fm->header |= XTestPackDeviceID(dev_type); + /* + * compute the motion data byte + */ + fm->motion_data = XTestPackYMotionValue(dy); + fm->motion_data |= XTestPackXMotionValue(dx); + /* + * set the delay time in the input action + */ + fm->delay_time = tchar; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + sizeof(XTestMotionInfo); + if (packed_mode == 0) + { + /* + * if input actions are not packed, send the input + * action event to the client + */ + flush_input_actions(); + } + + } +} + +/****************************************************************************** + * + * XTestStealKeyData + * + * Place this key data in the input_action_packet. + * + */ +Bool +XTestStealKeyData(keycode, keystate, dev_type, locx, locy) +/* + * which key/button moved + */ +unsigned keycode; +/* + * whether the key/button was pressed or released + */ +int keystate; +/* + * which device caused the input action + */ +int dev_type; +/* + * the x and y coordinates of the locator when the action happenned + */ +int locx; +int locy; +{ + /* + * pointer to key/button motion input action + */ + XTestKeyInfo *kp; + /* + * time delta from previous event + */ + CARD16 tchar; + char keytrans = 0; + + /* + * update the logical position of the locator if the physical position + * of the locator is not the same as the logical position. + */ + if ((locx != xtest_mousex) || (locy != xtest_mousey)) + { + XTestStealJumpData(locx, locy, dev_type); + } + /* + * Get the time delta from the previous event. If needed, + * the check_time_event routine will put an XTestDELAY_ACTION + * type action in the input action event. + */ + tchar = check_time_event(); + if (!there_is_room(sizeof(XTestKeyInfo))) + { + /* + * If there isn't room in the input action event for + * an XTestDELAY_ACTION, then send that event to the + * client and start filling an empty one. + */ + flush_input_actions(); + } + /* + * point kp to the correct place in the input action event + */ + kp = (XTestKeyInfo *) + (&(input_action_packet.actions[packet_index])); + /* + * compute the input action header + */ + kp->header = XTestPackDeviceID(dev_type); + if ((keystate == KeyRelease) || (keystate == ButtonRelease)) + { + keytrans = XTestKEY_UP; + } + else if ((keystate == KeyPress) || (keystate == ButtonPress)) + { + keytrans = XTestKEY_DOWN; + } + else + { + printf("%s: invalid key/button state %d.\n", + XTestEXTENSION_NAME, + keystate); + } + kp->header = kp->header | keytrans | XTestKEY_ACTION; + /* + * set the keycode in the input action + */ + kp->keycode = keycode; + /* + * set the delay time in the input action + */ + kp->delay_time = tchar; + /* + * increment the packet index by the size of the input action + */ + packet_index = packet_index + sizeof(XTestKeyInfo); + /* + * if the command key has been released or input actions are not + * packed, send the input action event to the client + */ + if(((keycode == xtest_command_key) && (keystate == KeyRelease)) || + (packed_mode != XTestPACKED_ACTIONS)) + { + flush_input_actions(); + } + /* return TRUE if the event should be passed on to DIX */ + if (exclusive_steal) + return ((keystate == KeyRelease) && + (keycode == xtest_command_key)); + else + return ((keystate != KeyRelease) || + (keycode != xtest_command_key)); +} + +/****************************************************************************** + * + * parse_fake_input + * + * Parsing routine for a XTestFakeInput request. It will take a request + * and parse its contents into the input action array. Eventually the + * XTestProcessInputAction routine will be called to take input actions + * from the input action array and send them to the server to be handled. + */ +void +parse_fake_input(client, req) +/* + * which client did the XTestFakeInput request + */ +ClientPtr client; +/* + * a pointer to the xTestFakeInputReq structure sent by the client + */ +char *req; +{ + /* + * if set to 1, done processing input actions from the request + */ + int done = 0; + /* + * type of input action + */ + CARD8 action_type; + /* + * device type + */ + CARD8 dev_type; + /* + * pointer to an xTestFakeInputReq structure + */ + xTestFakeInputReq *request; + /* + * holds the index into the action list in the request + */ + int parse_index; + + /* + * get a correct-type pointer to the client-supplied request data + */ + request = (xTestFakeInputReq *) req; + /* + * save the acknowledge requested state for use in + * XTestProcessInputAction + */ + acknowledge = request->ack; + /* + * set up an index into the action list in the request + */ + parse_index = 0; + if (write_index >= ACTION_ARRAY_SIZE) + { + /* + * if the input action array is full, don't add any more + */ + done = 1; + } + while (!done) + { + /* + * get the type of input action in the list + */ + action_type = (request->action_list[parse_index]) + & XTestACTION_TYPE_MASK; + /* + * get the type of device in the list + */ + dev_type = XTestUnpackDeviceID(request->action_list[parse_index]); + /* + * process the input action appropriately + */ + switch (action_type) + { + case XTestKEY_ACTION: + parse_key_fake((XTestKeyInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + sizeof(XTestKeyInfo); + break; + case XTestMOTION_ACTION: + parse_motion_fake((XTestMotionInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + sizeof(XTestMotionInfo); + break; + case XTestJUMP_ACTION: + parse_jump_fake((XTestJumpInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + sizeof(XTestJumpInfo); + break; + case XTestDELAY_ACTION: + if (dev_type == XTestDELAY_DEVICE_ID) + { + parse_delay_fake((XTestDelayInfo *) + &(request->action_list[parse_index])); + parse_index = parse_index + + sizeof(XTestDelayInfo); + } + else + { + /* + * An invalid input action header byte has + * been detected, so there are no more + * input actions in this request. + * The intended invalid action header byte + * for this case should have a value of 0. + */ + done = 1; + } + break; + } + if (parse_index >= XTestMAX_ACTION_LIST_SIZE) + { + /* + * entire XTestFakeInput request has been processed + */ + done = 1; + } + if (write_index >= ACTION_ARRAY_SIZE) + { + /* + * no room in the input actions array + */ + done = 1; + } + } + if (write_index > read_index) + { + /* + * there are fake input actions in the input action array + * to be given to the server + */ + playback_on = 1; + playback_client = client; + } +} + +/****************************************************************************** + * + * parse_key_fake + * + * Called from parse_fake_input. + * + * Copy the fake key input action from its packed form into the array of + * pending input events. + */ +static void +parse_key_fake(fkey) +XTestKeyInfo *fkey; +{ + action_array[write_index].type = XTestKEY_ACTION; + action_array[write_index].device = XTestUnpackDeviceID(fkey->header); + action_array[write_index].keycode = fkey->keycode; + action_array[write_index].keystate = fkey->header & XTestKEY_STATE_MASK; + action_array[write_index].delay_time = fkey->delay_time; + write_index++; +} + +/****************************************************************************** + * + * parse_motion_fake + * + * Called from parse_fake_input. + * + * Copy the fake motion input action from its packed form into the array of + * pending input events. + */ +static void +parse_motion_fake(fmotion) +XTestMotionInfo *fmotion; +{ + int dx; + int dy; + + dx = (XTestUnpackXMotionValue(fmotion->motion_data)); + dy = (XTestUnpackYMotionValue(fmotion->motion_data)); + if (((fmotion->header) & XTestX_SIGN_BIT_MASK) == XTestX_NEGATIVE) + { + pmousex -= dx; + } + else + { + pmousex += dx; + } + if (((fmotion->header) & XTestY_SIGN_BIT_MASK) == XTestY_NEGATIVE) + { + pmousey -= dy; + } + else + { + pmousey += dy; + } + action_array[write_index].type = XTestJUMP_ACTION; + action_array[write_index].device = XTestUnpackDeviceID(fmotion->header); + action_array[write_index].x = pmousex; + action_array[write_index].y = pmousey; + action_array[write_index].delay_time = fmotion->delay_time; + write_index++; +} + +/****************************************************************************** + * + * parse_jump_fake + * + * Called from parse_fake_input. + * + * Copy the fake jump input action from its packed form into the array of + * pending input events. + */ +static void +parse_jump_fake(fjump) +XTestJumpInfo *fjump; +{ + pmousex = fjump->jumpx; + pmousey = fjump->jumpy; + action_array[write_index].type = XTestJUMP_ACTION; + action_array[write_index].device = XTestUnpackDeviceID(fjump->header); + action_array[write_index].x = pmousex; + action_array[write_index].y = pmousey; + action_array[write_index].delay_time = fjump->delay_time; + write_index++; +} + +/****************************************************************************** + * + * parse_delay_fake + * + * Called from parse_fake_input. + * + * Copy the fake delay input action from its packed form into the array of + * pending input events. + */ +static void +parse_delay_fake(tevent) +XTestDelayInfo *tevent; +{ + action_array[write_index].type = XTestDELAY_ACTION; + action_array[write_index].delay_time = tevent->delay_time; + write_index++; +} + +/****************************************************************************** + * + * XTestComputeWaitTime + * + * Compute the amount of time the server should wait before sending the + * next monitor event in playback mode. + */ +void +XTestComputeWaitTime(waittime) +struct timeval *waittime; +{ + /* + * The playback_on flag is set to 1 in parse_fake_input. It is set to + * 0 in XTestProcessInputAction if the server has replayed all input + * actions. + */ + if (playback_on) + { + if (!play_clock) + { + /* + * if the playback clock has never been set, + * then do it now + */ + start_play_clock(); + } + /* + * We need to save the waittime the first time through. This + * is a value the server uses, and we have to restore it when + * all of the input actions are processed by the server. + */ + if (!time_saved) + { + saved_sec = waittime->tv_sec; + saved_usec = waittime->tv_usec; + time_saved = 1; + } + if (go_for_next) + { + /* + * if we just processed an input action, figure out + * how long to wait for the next input action + */ + compute_action_time(&rtime); + } + else + { + /* + * else just find out how much more time to wait + * on the current input action + */ + (void)find_residual_time(&rtime); + } + waittime->tv_sec = rtime.tv_sec; + waittime->tv_usec = rtime.tv_usec; + } +} + +/****************************************************************************** + * + * XTestProcessInputAction + * + * If there are any input actions in the input action array, + * then take one out and process it. + * + */ +int +XTestProcessInputAction(readable, waittime) +/* + * This is the value that a 'select' function returned just before this + * routine was called. If the select timed out, this value will be 0. + * + * This extension modifies the select call's timeout value to cause the + * select to time out when the next input action is ready to given to + * the server. This routine is called immediately after the select, to + * give it a chance to process an input action. If we have an input action + * to process and the only reason that the select returned was because it + * timed out, then we change the select value to 1 and return 1 instead of 0. + */ +int readable; +/* + * this is the timeout value that the select was called with + */ +struct timeval *waittime; +{ +int mousex, mousey; + /* + * if playback_on is 0, then the input action array is empty + */ + if (playback_on) + { + restorewait = waittime; + /* + * figure out if we need to wait for the next input action + */ + if (find_residual_time(&rtime) > 0) + { + /* + * still have to wait before processing the current + * input action + */ + go_for_next = 0; + } + else + { + /* + * don't have to wait any longer before processing + * the current input action + */ + go_for_next = 1; + } + /* + * if we have an input action to process and the only reason + * that the select returned was because it timed out, then we + * change the select value to 1 and return 1 instead of 0 + */ + if (readable == 0) + { + readable++; + } + /* + * if we don't need to wait, then get an input action from + * the input action array and process it + */ + if (go_for_next) + { + /* + * There are three possible types of input actions in + * the input action array (motion input actions are + * converted to jump input actions before being put + * into the input action array). Delay input actions + * are processed by the compute_action_time function + * which is called from XTestComputeWaitTime. The + * other two types of input actions are processed here. + */ + if (action_array[read_index].type == XTestJUMP_ACTION) + { + XTestJumpPointer( + action_array[read_index].x, + action_array[read_index].y, + action_array[read_index].device); + } + if (action_array[read_index].type == XTestKEY_ACTION) + { + GetSpritePosition(&mousex, &mousey); + XTestGenerateEvent( + action_array[read_index].device, + action_array[read_index].keycode, + action_array[read_index].keystate, + mousex, + mousey); + } + read_index++; + /* + * if all input actions are processed, then restore + * the server state + */ + if (read_index >= write_index) + { + waittime->tv_sec = saved_sec; + waittime->tv_usec = saved_usec; + time_saved = 0; + playback_on = 0; + if (acknowledge) + { + /* + * if the playback client is waiting + * for an xTestFakeAck event, send + * it to him + */ + send_ack(playback_client); + acknowledge = 0; + } + write_index = 0; + read_index = 0; + playback_client = (ClientPtr) NULL; + play_clock = 0; + } + } + } + return(readable); +} + +/****************************************************************************** + * + * send_ack + * + * send an xTestFakeAck event to the client + */ +static void +send_ack(client) +ClientPtr client; +{ + xTestFakeAckEvent rep; + + /* + * set the serial number of the xTestFakeAck event + */ + rep.sequenceNumber = client->sequence; + rep.type = XTestFakeAckType; + WriteEventsToClient(client, 1, (xEvent *) &rep); +} + +/****************************************************************************** + * + * start_play_clock + * + * start the clock for play back. + */ +static void +start_play_clock() +{ + X_GETTIMEOFDAY(&play_time); + /* + * flag that play_time is valid + */ + play_clock = 1; +} + +/****************************************************************************** + * + * compute_action_time + * + * Set the play clock to the time when the next input action should be put + * into the server's input queue. Fill the rtime structure with values + * for the delta until the time for the next input action. + */ +static void +compute_action_time(rtime) +struct timeval *rtime; +{ + /* + * holds the delay time in milliseconds + */ + unsigned long dtime; + /* + * holds the number of microseconds in the sum of the dtime value + * and the play_time value + */ + unsigned long tot_usec; + /* + * holds the number of seconds and microseconds in the + * dtime value + */ + unsigned long sec; + unsigned long usec; + /* + * holds the current time + */ + struct timeval btime; + + /* + * Put the time from the current input action in dtime + */ + dtime = action_array[read_index].delay_time; + /* + * If the current input action is a delay input action, + * add in the time from the following input action. + */ + if ((action_array[read_index].type == XTestDELAY_ACTION) && + ((read_index + 1) < write_index)) + { + read_index++; + dtime = dtime + action_array[read_index].delay_time; + } + /* + * compute the number of seconds and microseconds in the + * dtime value + */ + sec = dtime / 1000; + usec = (dtime % 1000) * 1000; + /* + * get the current time in btime + */ + X_GETTIMEOFDAY(&btime); + /* + * compute the number of microseconds in the sum of the dtime value + * and the current usec value + */ + tot_usec = btime.tv_usec + usec; + /* + * if it is greater than one second's worth, adjust the seconds + */ + if (tot_usec >= 1000000) + { + tot_usec -= 1000000; + sec++; + } + play_time.tv_usec = tot_usec; + play_time.tv_sec = btime.tv_sec + sec; + /* + * put the time until the next input action in rtime + */ + rtime->tv_sec = sec; + rtime->tv_usec = usec; +} + +/****************************************************************************** + * + * find_residual_time + * + * Find the time interval from the current time to the value in play_time. + * This is the time to wait till putting the next input action into the + * server's input queue. If the time is already up, reset play_time to + * the current time. + */ +static int +find_residual_time(the_residual) +struct timeval *the_residual; +{ + /* + * if > 0, there is time to wait. If < 0, then don't wait + */ + int wait = 1; + /* + * holds the current time + */ + struct timeval btime; + /* + * holds the current time in seconds and microseconds + */ + unsigned long bsec; + unsigned long busec; + /* + * holds the playback time in seconds and microseconds + */ + unsigned long psec; + unsigned long pusec; + + /* + * get the current time in btime + */ + X_GETTIMEOFDAY(&btime); + /* + * get the current time in seconds and microseconds + */ + bsec = btime.tv_sec; + busec = btime.tv_usec; + /* + * get the playback time in seconds and microseconds + */ + psec = play_time.tv_sec; + pusec = play_time.tv_usec; + /* + * if the current time is already later than the playback time, + * we don't need to wait + */ + if (bsec > psec) + { + wait = -1; + } + else + { + if (bsec == psec) + { + /* + * if the current and playback times have the same + * second value, then compare the microsecond values + */ + if ( busec >= pusec) + { + /* + * if the current time is already later than + * the playback time, we don't need to wait + */ + wait = -1; + } + else + { + the_residual->tv_usec = pusec - busec; + the_residual->tv_sec = 0; + } + } + else + { + if (busec > pusec) + { + /* + * 'borrow' a second's worth of microseconds + * from the seconds left to wait + */ + the_residual->tv_usec = 1000000 - busec + pusec; + psec--; + the_residual->tv_sec = psec - bsec; + } + else + { + the_residual->tv_sec = psec - bsec; + the_residual->tv_usec = pusec - busec; + } + } + } + if (wait < 0) + { + /* + * if don't need to wait, set the playback time + * to the current time + */ + X_GETTIMEOFDAY(&play_time); + /* + * set the time to wait to 0 + */ + the_residual->tv_sec = 0; + the_residual->tv_usec = 0; + } + return(wait); +} + +/****************************************************************************** + * + * abort_play_back + */ +void +abort_play_back() +{ + /* + * If we were playing back input actions at the time of the abort, + * restore the original wait time for the select in the main wait + * loop of the server + */ + if (playback_on) + { + restorewait->tv_sec = saved_sec; + restorewait->tv_usec = saved_usec; + } + /* + * make the input action array empty + */ + read_index = 0; + write_index = 0; + /* + * we are no longer playing back anything + */ + playback_on = 0; + play_clock = 0; + go_for_next = 1; + /* + * there is no valid wait time saved any more + */ + time_saved = 0; + /* + * there are no valid clients using this extension + */ + playback_client = (ClientPtr) NULL; + current_xtest_client = (ClientPtr) NULL; +} + +/****************************************************************************** + * + * return_input_array_size + * + * Return the number of input actions in the input action array. + */ +void +return_input_array_size(client) +/* + * which client to send the reply to + */ +ClientPtr client; +{ + xTestQueryInputSizeReply rep; + + rep.type = X_Reply; + /* + * set the serial number of the reply + */ + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.size_return = ACTION_ARRAY_SIZE; + WriteReplyToClient(client, + sizeof(xTestQueryInputSizeReply), + (pointer) &rep); +} diff --git a/nx-X11/programs/Xserver/Xext/xtest1dd.h b/nx-X11/programs/Xserver/Xext/xtest1dd.h new file mode 100644 index 000000000..3130c7075 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xtest1dd.h @@ -0,0 +1,127 @@ +/* $XFree86: xc/programs/Xserver/Xext/xtest1dd.h,v 3.2 2001/08/01 00:44:44 tsi Exp $ */ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey <dickey@clark.net> + + 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 name of the above listed +copyright holder(s) not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef XTEST1DD_H +#define XTEST1DD_H 1 + +extern short xtest_mousex; +extern short xtest_mousey; +extern int playback_on; +extern ClientPtr current_xtest_client; +extern ClientPtr playback_client; +extern KeyCode xtest_command_key; + +extern void stop_stealing_input( + void +); + +extern void +steal_input( + ClientPtr /* client */, + CARD32 /* mode */ +); + +extern void +flush_input_actions( + void +); + +extern void +XTestStealJumpData( + int /* jx */, + int /* jy */, + int /* dev_type */ +); + +extern void +XTestStealMotionData( + int /* dx */, + int /* dy */, + int /* dev_type */, + int /* mx */, + int /* my */ +); + +extern Bool +XTestStealKeyData( + unsigned /* keycode */, + int /* keystate */, + int /* dev_type */, + int /* locx */, + int /* locy */ +); + +extern void +parse_fake_input( + ClientPtr /* client */, + char * /* req */ +); + +extern void +XTestComputeWaitTime( + struct timeval * /* waittime */ +); + +extern int +XTestProcessInputAction( + int /* readable */, + struct timeval * /* waittime */ +); + +extern void +abort_play_back( + void +); + +extern void +return_input_array_size( + ClientPtr /* client */ +); + +extern void XTestGenerateEvent( + int /* dev_type */, + int /* keycode */, + int /* keystate */, + int /* mousex */, + int /* mousey */ +); + +extern void XTestGetPointerPos( + short * /* fmousex */, + short * /* fmousey */ +); + +extern void XTestJumpPointer( + int /* jx */, + int /* jy */, + int /* dev_type */ +); + +#endif /* XTEST1DD_H */ diff --git a/nx-X11/programs/Xserver/Xext/xtest1di.c b/nx-X11/programs/Xserver/Xext/xtest1di.c new file mode 100644 index 000000000..d95b30612 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xtest1di.c @@ -0,0 +1,954 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/xtest1di.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */ +/* $Xorg: xtest1di.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ +/* + * File: xtest1di.c + * + * This file contains the device independent parts of the input + * synthesis extension. + */ + +/* + + +Copyright 1986, 1987, 1988, 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 1986, 1987, 1988 by Hewlett-Packard Corporation + +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 Hewlett-Packard not be used in +advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +Hewlett-Packard makes no representations about the +suitability of this software for any purpose. It is provided +"as is" without express or implied warranty. + +This software is not subject to any license of the American +Telephone and Telegraph Company or of the Regents of the +University of California. + +*/ +/* $XFree86: xc/programs/Xserver/Xext/xtest1di.c,v 3.5 2003/09/13 21:33:03 dawes Exp $ */ + +/***************************************************************************** + * include files + ****************************************************************************/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "opaque.h" +#define XTestSERVER_SIDE +#include <X11/extensions/xtestext1.h> +#include "modinit.h" + +#include "xtest1dd.h" + +/***************************************************************************** + * defines + ****************************************************************************/ + +/***************************************************************************** + * variables + ****************************************************************************/ + +/* + * Holds the request type code for this extension. The request type code + * for this extension may vary depending on how many extensions are installed + * already, so the initial value given below will be added to the base request + * code that is aquired when this extension is installed. + */ +static int XTestReqCode = 0; +/* + * Holds the two event type codes for this extension. The event type codes + * for this extension may vary depending on how many extensions are installed + * already, so the initial values given below will be added to the base event + * code that is aquired when this extension is installed. + */ +int XTestInputActionType = 0; +int XTestFakeAckType = 1; +/* + * true => monitor stealing input + */ +int on_steal_input = FALSE; +/* + * true => monitor alone getting input + */ +int exclusive_steal = FALSE; +/* + * holds the resource type assigned to this extension + */ +static RESTYPE XTestType; +/* + * holds the resource ID for the client currently using XTestGetInput + */ +static XID current_client_id; + +/***************************************************************************** + * function declarations + ****************************************************************************/ + +static DISPATCH_PROC(ProcXTestDispatch); +static DISPATCH_PROC(SProcXTestDispatch); +static DISPATCH_PROC(ProcTestFakeInput); +static DISPATCH_PROC(SProcTestFakeInput); +static DISPATCH_PROC(ProcTestGetInput); +static DISPATCH_PROC(SProcTestGetInput); +static DISPATCH_PROC(ProcTestStopInput); +static DISPATCH_PROC(SProcTestStopInput); +static DISPATCH_PROC(ProcTestReset); +static DISPATCH_PROC(SProcTestReset); +static DISPATCH_PROC(ProcTestQueryInputSize); +static DISPATCH_PROC(SProcTestQueryInputSize); + +static void XTestResetProc( + ExtensionEntry * /* unused */ + ); +static void SReplyXTestDispatch( + ClientPtr /* client_ptr */, + int /* size */, + char * /* reply_ptr */ + ); +static void SEventXTestDispatch( + xEvent * /* from */, + xEvent * /* to */ + ); + +static int XTestCurrentClientGone( + pointer /* value */, + XID /* id */ + ); + +/***************************************************************************** + * + * XTestExtension1Init + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + * XTestExtension1Init has no events or errors + * (other than the core errors). + */ +void +XTestExtension1Init(INITARGS) +{ + /* + * holds the pointer to the extension entry structure + */ + ExtensionEntry *extEntry; + + extEntry = AddExtension(XTestEXTENSION_NAME, + XTestEVENT_COUNT, + 0, + ProcXTestDispatch, + SProcXTestDispatch, + XTestResetProc, + StandardMinorOpcode); + if (extEntry) + { + /* + * remember the request code assigned to this extension + */ + XTestReqCode = extEntry->base; + /* + * make an atom saying that this extension is present + */ + (void) MakeAtom(XTestEXTENSION_NAME, + strlen(XTestEXTENSION_NAME), + TRUE); + /* + * remember the event codes assigned to this extension + */ + XTestInputActionType += extEntry->eventBase; + XTestFakeAckType += extEntry->eventBase; + /* + * install the routine to handle byte-swapping the replies + * for this extension in the ReplySwapVector table + */ + ReplySwapVector[XTestReqCode] = (ReplySwapPtr) SReplyXTestDispatch; + /* + * install the routine to handle byte-swapping the events + * for this extension in the EventSwapVector table + */ + EventSwapVector[XTestInputActionType] = SEventXTestDispatch; + EventSwapVector[XTestFakeAckType] = SEventXTestDispatch; + /* + * get the resource type for this extension + */ + XTestType = CreateNewResourceType(XTestCurrentClientGone); + if (XTestType == 0) + { + FatalError("XTestExtension1Init: CreateNewResourceType failed\n"); + } + } + else + { + FatalError("XTestExtension1Init: AddExtensions failed\n"); + } +} + +/***************************************************************************** + * + * ProcXTestDispatch + * + * + */ +static int +ProcXTestDispatch(client) + register ClientPtr client; +{ + REQUEST(xReq); + if (stuff->data == X_TestFakeInput) + { + return(ProcTestFakeInput(client)); + } + else if (stuff->data == X_TestGetInput) + { + return(ProcTestGetInput(client)); + } + else if (stuff->data == X_TestStopInput) + { + return(ProcTestStopInput(client)); + } + else if (stuff->data == X_TestReset) + { + return(ProcTestReset(client)); + } + else if (stuff->data == X_TestQueryInputSize) + { + return(ProcTestQueryInputSize(client)); + } + else + { + SendErrorToClient(client, + XTestReqCode, + stuff->data, + None, + BadRequest); + return(BadRequest); + } +} + +/***************************************************************************** + * + * SProcXTestDispatch + * + * + */ +static int +SProcXTestDispatch(client) + register ClientPtr client; +{ + REQUEST(xReq); + if (stuff->data == X_TestFakeInput) + { + return(SProcTestFakeInput(client)); + } + else if (stuff->data == X_TestGetInput) + { + return(SProcTestGetInput(client)); + } + else if (stuff->data == X_TestStopInput) + { + return(SProcTestStopInput(client)); + } + else if (stuff->data == X_TestReset) + { + return(SProcTestReset(client)); + } + else if (stuff->data == X_TestQueryInputSize) + { + return(SProcTestQueryInputSize(client)); + } + else + { + SendErrorToClient(client, + XTestReqCode, + stuff->data, + None, + BadRequest); + return(BadRequest); + } +} + +/***************************************************************************** + * + * SProcTestFakeInput + * + * + */ +static int +SProcTestFakeInput(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + /* + * index counter + */ + int i; + /* + * pointer to the next input action in the request + */ + CARD8 *input_action_ptr; + /* + * holds the type of the next input action in the request + */ + int input_action_type; + + REQUEST(xTestFakeInputReq); + /* + * byte-swap the fields in the request + */ + swaps(&stuff->length, n); + swapl(&stuff->ack, n); + /* + * have to parse and then byte-swap the input action list here + */ + for (i = 0; i < XTestMAX_ACTION_LIST_SIZE;) + { + /* + * point to the next input action in the request + */ + input_action_ptr = &(((xTestFakeInputReq *) stuff)->action_list[i]); + /* + * figure out what type of input action it is + */ + input_action_type = (*input_action_ptr) & XTestACTION_TYPE_MASK; + /* + * byte-swap the input action according to it's type + */ + switch (input_action_type) + { + case XTestKEY_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestKeyInfo); + break; + case XTestMOTION_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestMotionInfo); + break; + case XTestJUMP_ACTION: + /* + * byte-swap the jumpx field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n); + /* + * byte-swap the jumpy field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n); + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestJumpInfo); + break; + default: + /* + * if this is a delay input action, then byte-swap it, + * otherwise we have reached the end of the input + * actions in this request + */ + if (XTestUnpackDeviceID(*input_action_ptr) == + XTestDELAY_DEVICE_ID) + { + /* + * byte-swap the delay_time field + */ + swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestDelayInfo); + } + else + { + /* + * if the input action header byte is 0 or + * ill-formed, then there are no more input + * actions in this request + */ + i = XTestMAX_ACTION_LIST_SIZE; + } + break; + } + } + return(ProcTestFakeInput(client)); +} + +/***************************************************************************** + * + * SProcTestGetInput + * + * + */ +static int +SProcTestGetInput(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestGetInputReq); + /* + * byte-swap the fields in the request + */ + swaps(&stuff->length, n); + swapl(&stuff->mode, n); + return(ProcTestGetInput(client)); +} + +/***************************************************************************** + * + * SProcTestStopInput + * + * + */ +static int +SProcTestStopInput(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestStopInputReq); + /* + * byte-swap the length field in the request + */ + swaps(&stuff->length, n); + return(ProcTestStopInput(client)); +} + +/***************************************************************************** + * + * SProcTestReset + * + * + */ +static int +SProcTestReset(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestResetReq); + /* + * byte-swap the length field in the request + */ + swaps(&stuff->length, n); + return(ProcTestReset(client)); +} + +/***************************************************************************** + * + * SProcTestQueryInputSize + * + * + */ +static int +SProcTestQueryInputSize(client) + register ClientPtr client; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + + REQUEST(xTestQueryInputSizeReq); + /* + * byte-swap the length field in the request + */ + swaps(&stuff->length, n); + return(ProcTestQueryInputSize(client)); +} + +/***************************************************************************** + * + * ProcTestFakeInput + * + * + */ +static int +ProcTestFakeInput(client) + register ClientPtr client; +{ + REQUEST(xTestFakeInputReq); + REQUEST_SIZE_MATCH(xTestFakeInputReq); + + if (playback_client == NULL) + { + playback_client = client; + current_client_id = FakeClientID(client->index); + AddResource(current_client_id, + XTestType, + 0); + MakeClientGrabImpervious(client); + } + if (playback_client == client) + { + /* + * This extension does not need to clean up any + * server state when a client using this function + * "goes away". The server will just process any + * input actions that have already been sent to it, + * and will then reset its association with a client. + */ + parse_fake_input(client, (char *)stuff); + return(Success); + } + else + { + /* + * this is a request by another client to send fake + * input while the server is still being used + */ + SendErrorToClient(client, + XTestReqCode, + X_TestFakeInput, + None, + BadAccess); + return(BadAccess); + } +} + +/***************************************************************************** + * + * ProcTestGetInput + * + * + */ +static int +ProcTestGetInput(client) + register ClientPtr client; +{ + REQUEST(xTestGetInputReq); + REQUEST_SIZE_MATCH(xTestGetInputReq); + if (on_steal_input) + { + /* + * this is a request by another client to get fake input + * while the server is still sending input to the first client + */ + SendErrorToClient(client, + XTestReqCode, + X_TestGetInput, + None, + BadAccess); + return(BadAccess); + } + else + { + /* + * Set up a resource associated with the client using this + * function so that this extension gets called when the + * client "goes away". This allows this extension to + * clean up the server state. + */ + current_client_id = FakeClientID(client->index); + AddResource(current_client_id, + XTestType, + 0); + /* + * indicate that a client is stealing input + */ + on_steal_input = TRUE; + if ((stuff->mode & XTestEXCLUSIVE) == 0) + { + exclusive_steal = FALSE; + } + else + { + exclusive_steal = TRUE; + } + steal_input(client, stuff->mode); + return(Success); + } +} + +/***************************************************************************** + * + * ProcTestStopInput + * + * + */ +static int +ProcTestStopInput(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xTestStopInputReq); + if (on_steal_input && (current_xtest_client == client)) + { + on_steal_input = FALSE; + exclusive_steal = FALSE; + stop_stealing_input(); + /* + * remove the resource associated with this client + */ + FreeResource(current_client_id, RT_NONE); + return(Success); + } + else + { + /* + * this is a request to stop fake input when fake input has + * never been started or from a client that hasn't started + * fake input + */ + SendErrorToClient(client, + XTestReqCode, + X_TestStopInput, + None, + BadAccess); + return(BadAccess); + } +} + +/***************************************************************************** + * + * ProcTestReset + * + * + */ +static int +ProcTestReset(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xTestResetReq); + on_steal_input = FALSE; + exclusive_steal = FALSE; + /* + * defined in xtest1dd.c + */ + stop_stealing_input(); + /* + * defined in xtest1dd.c + */ + abort_play_back(); + return(Success); +} + +/***************************************************************************** + * + * ProcTestQueryInputSize + * + * + */ +static int +ProcTestQueryInputSize(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xTestQueryInputSizeReq); + /* + * defined in xtest1dd.c + */ + return_input_array_size(client); + return(Success); +} + +/***************************************************************************** + * + * XTestResetProc + * + * This function is called by the server when the server has no clients + * connected to it. It must put eveything back the way it was before + * this extension was installed. + */ +/*ARGSUSED*/ +static void +XTestResetProc(unused) + ExtensionEntry * unused; +{ + /* + * remove the routine to handle byte-swapping the replies + * for this extension in the ReplySwapVector table + */ + ReplySwapVector[XTestReqCode] = ReplyNotSwappd; + /* + * remove the routine to handle byte-swapping the events + * for this extension in the EventSwapVector table + */ + EventSwapVector[XTestInputActionType] = NotImplemented; + EventSwapVector[XTestFakeAckType] = NotImplemented; + /* + * reset the variables initialized just once at load time + */ + XTestReqCode = 0; + XTestInputActionType = 0; + XTestFakeAckType = 1; + on_steal_input = FALSE; + exclusive_steal = FALSE; + playback_client = 0; /* Don't really need this but it looks nice */ +} + +/***************************************************************************** + * + * PXTestCurrentClientGone + * + * This routine is called when a client that has asked for input actions + * to be sent to it "goes away". This routine must clean up the + * server state. + */ +/*ARGSUSED*/ +static int +XTestCurrentClientGone(value, id) + pointer value; + XID id; +{ + /* + * defined in xtest1dd.c + */ + on_steal_input = FALSE; + exclusive_steal = FALSE; + /* + * defined in xtestdd.c + */ + playback_client = 0; + abort_play_back(); + return TRUE; +} + +/***************************************************************************** + * + * SReplyXTestDispatch + * + * Swap any replies defined in this extension. + */ +static void +SReplyXTestDispatch(client_ptr, size, reply_ptr) + ClientPtr client_ptr; + int size; + char *reply_ptr; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + /* + * pointer to xTestQueryInputSizeReply + */ + xTestQueryInputSizeReply *rep_ptr; + + /* + * there is only one reply in this extension, so byte-swap it + */ + rep_ptr = (xTestQueryInputSizeReply *) reply_ptr; + swaps(&(rep_ptr->sequenceNumber), n); + swapl(&(rep_ptr->length), n); + swapl(&(rep_ptr->size_return), n); + /* + * now write the swapped reply to the client + */ + WriteToClient(client_ptr, size, reply_ptr); +} + +/***************************************************************************** + * + * SEventXTestDispatch + * + * Swap any events defined in this extension. + */ +static void +SEventXTestDispatch(from, to) + xEvent *from; + xEvent *to; +{ + /* + * used in the swaps and swapl macros for temporary storage space + */ + register char n; + /* + * index counter + */ + int i; + /* + * pointer to the next input action in the event + */ + CARD8 *input_action_ptr; + /* + * holds the type of the next input action in the event + */ + int input_action_type; + + + /* + * copy the type information from the "from" event to the "to" event + */ + ((xTestInputActionEvent *) to)->type = + ((xTestInputActionEvent *) from)->type; + /* + * copy the sequence number information from the "from" event to the + * "to" event + */ + ((xTestInputActionEvent *) to)->sequenceNumber = + ((xTestInputActionEvent *) from)->sequenceNumber; + /* + * byte-swap the sequence number in the "to" event + */ + swaps(&(((xTestInputActionEvent *) to)->sequenceNumber), n); + /* + * If the event is an xTestInputActionEvent, then it needs more + * processing. Otherwise, it is an xTestFakeAckEvent, which + * has no other information in it. + */ + if ((((xTestInputActionEvent *) to)->type & 0x7f) == + XTestInputActionType) + { + /* + * copy the input actions from the "from" event + * to the "to" event + */ + for (i = 0; i < XTestACTIONS_SIZE; i++) + { + ((xTestInputActionEvent *) to)->actions[i] = + ((xTestInputActionEvent *) from)->actions[i]; + } + /* + * byte-swap the input actions in the "to" event + */ + for (i = 0; i < XTestACTIONS_SIZE; i++) + { + /* + * point to the next input action in the event + */ + input_action_ptr = &(((xTestInputActionEvent *) to)->actions[i]); + /* + * figure out what type of input action it is + */ + input_action_type = (*input_action_ptr) & + XTestACTION_TYPE_MASK; + /* + * byte-swap the input action according to it's type + */ + switch (input_action_type) + { + case XTestKEY_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestKeyInfo); + break; + case XTestMOTION_ACTION: + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestMotionInfo); + break; + case XTestJUMP_ACTION: + /* + * byte-swap the jumpx field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n); + /* + * byte-swap the jumpy field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n); + /* + * byte-swap the delay_time field + */ + swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestJumpInfo); + break; + default: + /* + * if this is a delay input action, then + * byte-swap it, otherwise we have reached the + * end of the input actions in this event + */ + if (XTestUnpackDeviceID(*input_action_ptr) == + XTestDELAY_DEVICE_ID) + { + /* + * byte-swap the delay_time field + */ + swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n); + /* + * advance to the next input action + */ + i += sizeof(XTestDelayInfo); + } + else + { + /* + * if the input action header byte is 0 + * or ill-formed, then there are no + * more input actions in this event + */ + i = XTestACTIONS_SIZE; + } + break; + } + } + } +} diff --git a/nx-X11/programs/Xserver/Xext/xvdisp.c b/nx-X11/programs/Xserver/Xext/xvdisp.c new file mode 100644 index 000000000..21ab0b6a0 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvdisp.c @@ -0,0 +1,2217 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/xvdisp.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + 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 MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdisp.c,v 1.27 2003/07/16 01:38:31 dawes Exp $ */ + +/* +** File: +** +** xvdisp.c --- Xv server extension dispatch module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include "xvdix.h" +#ifdef MITSHM +#define _XSHM_SERVER_ +#include <X11/extensions/shmstr.h> +#endif + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#include "xvdisp.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; + +#ifdef MITSHM +static int XineramaXvShmPutImage(ClientPtr); +#endif +static int XineramaXvPutImage(ClientPtr); +static int XineramaXvPutVideo(ClientPtr); +static int XineramaXvPutStill(ClientPtr); +static int XineramaXvSetPortAttribute(ClientPtr); +static int XineramaXvStopVideo(ClientPtr); +#endif + +/* INTERNAL */ + +static int ProcXvQueryExtension(ClientPtr); +static int ProcXvQueryAdaptors(ClientPtr); +static int ProcXvQueryEncodings(ClientPtr); +static int ProcXvPutVideo(ClientPtr); +static int ProcXvPutStill(ClientPtr); +static int ProcXvGetVideo(ClientPtr); +static int ProcXvGetStill(ClientPtr); +static int ProcXvGrabPort(ClientPtr); +static int ProcXvUngrabPort(ClientPtr); +static int ProcXvSelectVideoNotify(ClientPtr); +static int ProcXvSelectPortNotify(ClientPtr); +static int ProcXvStopVideo(ClientPtr); +static int ProcXvSetPortAttribute(ClientPtr); +static int ProcXvGetPortAttribute(ClientPtr); +static int ProcXvQueryBestSize(ClientPtr); +static int ProcXvQueryPortAttributes(ClientPtr); +static int ProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int ProcXvShmPutImage(ClientPtr); +#endif +static int ProcXvQueryImageAttributes(ClientPtr); +static int ProcXvListImageFormats(ClientPtr); + +static int SProcXvQueryExtension(ClientPtr); +static int SProcXvQueryAdaptors(ClientPtr); +static int SProcXvQueryEncodings(ClientPtr); +static int SProcXvPutVideo(ClientPtr); +static int SProcXvPutStill(ClientPtr); +static int SProcXvGetVideo(ClientPtr); +static int SProcXvGetStill(ClientPtr); +static int SProcXvGrabPort(ClientPtr); +static int SProcXvUngrabPort(ClientPtr); +static int SProcXvSelectVideoNotify(ClientPtr); +static int SProcXvSelectPortNotify(ClientPtr); +static int SProcXvStopVideo(ClientPtr); +static int SProcXvSetPortAttribute(ClientPtr); +static int SProcXvGetPortAttribute(ClientPtr); +static int SProcXvQueryBestSize(ClientPtr); +static int SProcXvQueryPortAttributes(ClientPtr); +static int SProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int SProcXvShmPutImage(ClientPtr); +#endif +static int SProcXvQueryImageAttributes(ClientPtr); +static int SProcXvListImageFormats(ClientPtr); + +static int SWriteQueryAdaptorsReply(ClientPtr, xvQueryAdaptorsReply *); +static int SWriteQueryExtensionReply(ClientPtr, xvQueryExtensionReply *); +static int SWriteQueryEncodingsReply(ClientPtr, xvQueryEncodingsReply *); +static int SWriteAdaptorInfo(ClientPtr, xvAdaptorInfo *); +static int SWriteEncodingInfo(ClientPtr, xvEncodingInfo *); +static int SWriteFormat(ClientPtr, xvFormat *); +static int SWriteAttributeInfo(ClientPtr, xvAttributeInfo *); +static int SWriteGrabPortReply(ClientPtr, xvGrabPortReply *); +static int SWriteGetPortAttributeReply(ClientPtr, xvGetPortAttributeReply *); +static int SWriteQueryBestSizeReply(ClientPtr, xvQueryBestSizeReply *); +static int SWriteQueryPortAttributesReply( + ClientPtr, xvQueryPortAttributesReply *); +static int SWriteQueryImageAttributesReply( + ClientPtr, xvQueryImageAttributesReply*); +static int SWriteListImageFormatsReply(ClientPtr, xvListImageFormatsReply*); +static int SWriteImageFormatInfo(ClientPtr, xvImageFormatInfo*); + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +/* +** ProcXvDispatch +** +** +** +*/ + +int +ProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + switch (stuff->data) + { + case xv_QueryExtension: return(ProcXvQueryExtension(client)); + case xv_QueryAdaptors: return(ProcXvQueryAdaptors(client)); + case xv_QueryEncodings: return(ProcXvQueryEncodings(client)); + case xv_PutVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutVideo(client)); + else +#endif + return(ProcXvPutVideo(client)); + case xv_PutStill: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutStill(client)); + else +#endif + return(ProcXvPutStill(client)); + case xv_GetVideo: return(ProcXvGetVideo(client)); + case xv_GetStill: return(ProcXvGetStill(client)); + case xv_GrabPort: return(ProcXvGrabPort(client)); + case xv_UngrabPort: return(ProcXvUngrabPort(client)); + case xv_SelectVideoNotify: return(ProcXvSelectVideoNotify(client)); + case xv_SelectPortNotify: return(ProcXvSelectPortNotify(client)); + case xv_StopVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvStopVideo(client)); + else +#endif + return(ProcXvStopVideo(client)); + case xv_SetPortAttribute: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvSetPortAttribute(client)); + else +#endif + return(ProcXvSetPortAttribute(client)); + case xv_GetPortAttribute: return(ProcXvGetPortAttribute(client)); + case xv_QueryBestSize: return(ProcXvQueryBestSize(client)); + case xv_QueryPortAttributes: return(ProcXvQueryPortAttributes(client)); + case xv_PutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutImage(client)); + else +#endif + return(ProcXvPutImage(client)); +#ifdef MITSHM + case xv_ShmPutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvShmPutImage(client)); + else +#endif + return(ProcXvShmPutImage(client)); +#endif + case xv_QueryImageAttributes: return(ProcXvQueryImageAttributes(client)); + case xv_ListImageFormats: return(ProcXvListImageFormats(client)); + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + return(BadImplementation); + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + } +} + +int +SProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + switch (stuff->data) + { + case xv_QueryExtension: return(SProcXvQueryExtension(client)); + case xv_QueryAdaptors: return(SProcXvQueryAdaptors(client)); + case xv_QueryEncodings: return(SProcXvQueryEncodings(client)); + case xv_PutVideo: return(SProcXvPutVideo(client)); + case xv_PutStill: return(SProcXvPutStill(client)); + case xv_GetVideo: return(SProcXvGetVideo(client)); + case xv_GetStill: return(SProcXvGetStill(client)); + case xv_GrabPort: return(SProcXvGrabPort(client)); + case xv_UngrabPort: return(SProcXvUngrabPort(client)); + case xv_SelectVideoNotify: return(SProcXvSelectVideoNotify(client)); + case xv_SelectPortNotify: return(SProcXvSelectPortNotify(client)); + case xv_StopVideo: return(SProcXvStopVideo(client)); + case xv_SetPortAttribute: return(SProcXvSetPortAttribute(client)); + case xv_GetPortAttribute: return(SProcXvGetPortAttribute(client)); + case xv_QueryBestSize: return(SProcXvQueryBestSize(client)); + case xv_QueryPortAttributes: return(SProcXvQueryPortAttributes(client)); + case xv_PutImage: return(SProcXvPutImage(client)); +#ifdef MITSHM + case xv_ShmPutImage: return(SProcXvShmPutImage(client)); +#endif + case xv_QueryImageAttributes: return(SProcXvQueryImageAttributes(client)); + case xv_ListImageFormats: return(SProcXvListImageFormats(client)); + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + return(BadImplementation); + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + } +} + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; + +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize; + int na; + XvAdaptorPtr pa; + int nf; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + if(!(pWin = (WindowPtr)LookupWindow(stuff->window, client) )) + { + client->errorValue = stuff->window; + return (BadWindow); + } + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += (strlen(pa->name) + 3) & ~3; + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = totalSize >> 2; + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, ainfo.name_size, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return (client->noClientException); + +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += (strlen(pe->name) + 3) & ~3; + pe++; + } + + rep.length = totalSize >> 2; + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, einfo.name_size, pe->name); + pe++; + } + + return (client->noClientException); + +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvPutStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + register DrawablePtr pDraw; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + if(!(pDraw = (DrawablePtr)LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadWindow); + } + + return XVCALL(diSelectVideoNotify)(client, pDraw, stuff->onoff); + +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diSelectPortNotify)(client, pPort, stuff->onoff); + +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XVCALL(diGrabPort)(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; + +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diUngrabPort)(client, pPort, stuff->time); + +} + + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status; + register DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadDrawable); + } + + return XVCALL(diStopVideo)(client, pPort, pDraw); + +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diSetPortAttribute)(client, pPort, + stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diGetPortAttribute)(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L; + } + + rep.length = (rep.num_attributes * sz_xvAttributeInfo) + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = (size + 3) & ~3L; + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + + + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = (size + 3) >> 2; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, + pImage, (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + if(!(shmdesc = (ShmDescPtr)LookupIDByType(stuff->shmseg, ShmSegType))) + { + client->errorValue = stuff->shmseg; + return BadShmSegCode; + } + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#endif + +#ifdef XvMCExtension +#include "xvmcext.h" +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = xalloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, rep.length); + WriteToClient(client, rep.length << 2, (char*)offsets); + + xfree(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = rep.num_formats * sz_xvImageFormatInfo >> 2; + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < rep.num_formats; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + + + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + register char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return ProcXvQueryExtension(client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + register char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcXvQueryAdaptors(client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + register char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryEncodings(client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvGrabPort(client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvUngrabPort(client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + register char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutVideo(client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + register char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutStill(client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + register char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetVideo(client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + register char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetStill(client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvPutImage(client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->offset, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvShmPutImage(client); +} +#endif + + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return ProcXvSelectVideoNotify(client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvSelectPortNotify(client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + register char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return ProcXvStopVideo(client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvSetPortAttribute(client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvGetPortAttribute(client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + register char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvQueryBestSize(client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryPortAttributes(client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->width, n); + return ProcXvQueryImageAttributes(client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + register char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvListImageFormats(client); +} + + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)&rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + register char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + register char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + register char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + register char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + register char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + + + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)&rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)&rep); + + return Success; +} + + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)&rep); + + return Success; +} + + +#ifdef PANORAMIX + + + + +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result = Success, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result = Success, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + + +void XineramifyXv(void) +{ + ScreenPtr pScreen, screen0 = screenInfo.screens[0]; + XvScreenPtr xvsp0 = (XvScreenPtr)screen0->devPrivates[XvScreenIndex].ptr; + XvAdaptorPtr refAdapt, pAdapt; + XvAttributePtr pAttr; + XvScreenPtr xvsp; + Bool isOverlay, hasOverlay; + PanoramiXRes *port; + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k, l; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource); + + if(!xvsp0) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + refAdapt = xvsp0->pAdaptors + i; + + bzero(MatchingAdaptors, sizeof(XvAdaptorPtr) * MAXSCREENS); + + MatchingAdaptors[0] = refAdapt; + + if(!(refAdapt->type & XvInputMask)) continue; + + isOverlay = FALSE; + for(j = 0; j < refAdapt->nAttributes; j++) { + pAttr = refAdapt->pAttributes + j; + if(!strcmp(pAttr->name, "XV_COLORKEY")) { + isOverlay = TRUE; + break; + } + } + + for(j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + xvsp = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* Do not try to go on if xv is not supported on this screen */ + if (xvsp==NULL) continue ; + + /* if the adaptor has the same name it's a perfect match */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if(!strcmp(refAdapt->name, pAdapt->name)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + if(MatchingAdaptors[j]) continue; /* found it */ + + /* otherwise we only look for XvImage adaptors */ + if(!(refAdapt->type & XvImageMask)) continue; + if(refAdapt->nImages <= 0) continue; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + hasOverlay = FALSE; + for(l = 0; l < pAdapt->nAttributes; l++) { + if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + hasOverlay = TRUE; + break; + } + } + if(isOverlay && hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + else if(!isOverlay && !hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + if(MatchingAdaptors[j]) continue; /* found it */ + + /* but we'll take any XvImage pairing if we can get it */ + + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + if(!(port = xalloc(sizeof(PanoramiXRes)))) + break; + port->info[0].id = MatchingAdaptors[0]->base_id + j; + AddResource(port->info[0].id, XvXRTPort, port); + + for(k = 1; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + } + } +} + +#endif diff --git a/nx-X11/programs/Xserver/Xext/xvdisp.h b/nx-X11/programs/Xserver/Xext/xvdisp.h new file mode 100644 index 000000000..00af9858b --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvdisp.h @@ -0,0 +1,3 @@ +/* $XFree86$ */ + +extern void XineramifyXv(void); diff --git a/nx-X11/programs/Xserver/Xext/xvdix.h b/nx-X11/programs/Xserver/Xext/xvdix.h new file mode 100644 index 000000000..99d918406 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvdix.h @@ -0,0 +1,291 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + 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 MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdix.h,v 1.7 2001/05/07 21:37:51 tsi Exp $ */ + +#ifndef XVDIX_H +#define XVDIX_H +/* +** File: +** +** xvdix.h --- Xv device independent header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 29.08.91 Carver +** - removed UnrealizeWindow wrapper unrealizing windows no longer +** preempts video +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include "scrnintstr.h" +#include <X11/extensions/Xvproto.h> + +extern int XvScreenIndex; +extern unsigned long XvExtensionGeneration; +extern unsigned long XvScreenGeneration; +extern unsigned long XvResourceGeneration; + +extern int XvReqCode; +extern int XvEventBase; +extern int XvErrorBase; + +extern unsigned long XvRTPort; +extern unsigned long XvRTEncoding; +extern unsigned long XvRTGrab; +extern unsigned long XvRTVideoNotify; +extern unsigned long XvRTVideoNotifyList; +extern unsigned long XvRTPortNotify; + +typedef struct { + int numerator; + int denominator; +} XvRationalRec, *XvRationalPtr; + +typedef struct { + char depth; + unsigned long visual; +} XvFormatRec, *XvFormatPtr; + +typedef struct { + unsigned long id; + ClientPtr client; +} XvGrabRec, *XvGrabPtr; + +typedef struct _XvVideoNotifyRec { + struct _XvVideoNotifyRec *next; + ClientPtr client; + unsigned long id; + unsigned long mask; +} XvVideoNotifyRec, *XvVideoNotifyPtr; + +typedef struct _XvPortNotifyRec { + struct _XvPortNotifyRec *next; + ClientPtr client; + unsigned long id; +} XvPortNotifyRec, *XvPortNotifyPtr; + +typedef struct { + int id; + ScreenPtr pScreen; + char *name; + unsigned short width, height; + XvRationalRec rate; +} XvEncodingRec, *XvEncodingPtr; + +typedef struct _XvAttributeRec { + int flags; + int min_value; + int max_value; + char *name; +} XvAttributeRec, *XvAttributePtr; + +typedef struct { + int id; + int type; + int byte_order; + char guid[16]; + int bits_per_pixel; + int format; + int num_planes; + + /* for RGB formats only */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats only */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; + int scanline_order; +} XvImageRec, *XvImagePtr; + +typedef struct { + unsigned long base_id; + unsigned char type; + char *name; + int nEncodings; + XvEncodingPtr pEncodings; + int nFormats; + XvFormatPtr pFormats; + int nAttributes; + XvAttributePtr pAttributes; + int nImages; + XvImagePtr pImages; + int nPorts; + struct _XvPortRec *pPorts; + ScreenPtr pScreen; + int (* ddAllocatePort)(unsigned long, struct _XvPortRec*, + struct _XvPortRec**); + int (* ddFreePort)(struct _XvPortRec*); + int (* ddPutVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddPutStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddGetVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddGetStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddStopVideo)(ClientPtr, struct _XvPortRec*, DrawablePtr); + int (* ddSetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32); + int (* ddGetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32*); + int (* ddQueryBestSize)(ClientPtr, struct _XvPortRec*, CARD8, + CARD16, CARD16,CARD16, CARD16, + unsigned int*, unsigned int*); + int (* ddPutImage)(ClientPtr, DrawablePtr, struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); + int (* ddQueryImageAttributes)(ClientPtr, struct _XvPortRec*, XvImagePtr, + CARD16*, CARD16*, int*, int*); + DevUnion devPriv; +} XvAdaptorRec, *XvAdaptorPtr; + +typedef struct _XvPortRec { + unsigned long id; + XvAdaptorPtr pAdaptor; + XvPortNotifyPtr pNotify; + DrawablePtr pDraw; + ClientPtr client; + XvGrabRec grab; + TimeStamp time; + DevUnion devPriv; +} XvPortRec, *XvPortPtr; + +#define LOOKUP_PORT(_id, client)\ + ((XvPortPtr)LookupIDByType(_id, XvRTPort)) + +#define LOOKUP_ENCODING(_id, client)\ + ((XvEncodingPtr)LookupIDByType(_id, XvRTEncoding)) + +#define LOOKUP_VIDEONOTIFY_LIST(_id, client)\ + ((XvVideoNotifyPtr)LookupIDByType(_id, XvRTVideoNotifyList)) + +#define LOOKUP_PORTNOTIFY_LIST(_id, client)\ + ((XvPortNotifyPtr)LookupIDByType(_id, XvRTPortNotifyList)) + +typedef struct { + int version, revision; + int nAdaptors; + XvAdaptorPtr pAdaptors; + DestroyWindowProcPtr DestroyWindow; + DestroyPixmapProcPtr DestroyPixmap; + CloseScreenProcPtr CloseScreen; + Bool (* ddCloseScreen)(int, ScreenPtr); + int (* ddQueryAdaptors)(ScreenPtr, XvAdaptorPtr*, int*); + DevUnion devPriv; +} XvScreenRec, *XvScreenPtr; + +#define SCREEN_PROLOGUE(pScreen, field)\ + ((pScreen)->field = \ + ((XvScreenPtr) \ + (pScreen)->devPrivates[XvScreenIndex].ptr)->field) + +#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ + ((pScreen)->field = wrapper) + +/* Errors */ + +#define _XvBadPort (XvBadPort+XvErrorBase) +#define _XvBadEncoding (XvBadEncoding+XvErrorBase) + +extern int ProcXvDispatch(ClientPtr); +extern int SProcXvDispatch(ClientPtr); + +extern void XvExtensionInit(void); +extern int XvScreenInit(ScreenPtr); +extern int XvGetScreenIndex(void); +extern unsigned long XvGetRTPort(void); +extern int XvdiSendPortNotify(XvPortPtr, Atom, INT32); +extern int XvdiVideoStopped(XvPortPtr, int); + +extern int XvdiPutVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern int XvdiPutStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern int XvdiGetVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern int XvdiGetStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern int XvdiPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); +extern int XvdiSelectVideoNotify(ClientPtr, DrawablePtr, BOOL); +extern int XvdiSelectPortNotify(ClientPtr, XvPortPtr, BOOL); +extern int XvdiSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); +extern int XvdiGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); +extern int XvdiStopVideo(ClientPtr, XvPortPtr, DrawablePtr); +extern int XvdiPreemptVideo(ClientPtr, XvPortPtr, DrawablePtr); +extern int XvdiMatchPort(XvPortPtr, DrawablePtr); +extern int XvdiGrabPort(ClientPtr, XvPortPtr, Time, int *); +extern int XvdiUngrabPort( ClientPtr, XvPortPtr, Time); + + +#if !defined(UNIXCPP) + +#define XVCALL(name) Xv##name + +#else + +#define XVCALL(name) Xv/**/name + +#endif + + +#endif /* XVDIX_H */ + diff --git a/nx-X11/programs/Xserver/Xext/xvmain.c b/nx-X11/programs/Xserver/Xext/xvmain.c new file mode 100644 index 000000000..8934f77f2 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvmain.c @@ -0,0 +1,1203 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/xvmain.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + 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 MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvmain.c,v 1.15tsi Exp $ */ + +/* +** File: +** +** xvmain.c --- Xv server extension main device independent module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 04.09.91 Carver +** - change: stop video always generates an event even when video +** wasn't active +** +** 29.08.91 Carver +** - change: unrealizing windows no longer preempts video +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 28.05.91 Carver +** - fixed Put and Get requests to not preempt operations to same drawable +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 19.03.91 Carver +** - fixed Put and Get requests to honor grabbed ports. +** - fixed Video requests to update di structure with new drawable, and +** client after calling ddx. +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +** Notes: +** +** Port structures reference client structures in a two different +** ways: when grabs, or video is active. Each reference is encoded +** as fake client resources and thus when the client is goes away so +** does the reference (it is zeroed). No other action is taken, so +** video doesn't necessarily stop. It probably will as a result of +** other resources going away, but if a client starts video using +** none of its own resources, then the video will continue to play +** after the client disappears. +** +** +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gc.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "input.h" + +#define GLOBAL + +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include "xvdix.h" + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#include "xvdisp.h" +#endif + +int XvScreenIndex = -1; +unsigned long XvExtensionGeneration = 0; +unsigned long XvScreenGeneration = 0; +unsigned long XvResourceGeneration = 0; + +int XvReqCode; +int XvEventBase; +int XvErrorBase; + +unsigned long XvRTPort; +unsigned long XvRTEncoding; +unsigned long XvRTGrab; +unsigned long XvRTVideoNotify; +unsigned long XvRTVideoNotifyList; +unsigned long XvRTPortNotify; + + + +/* EXTERNAL */ + +extern XID clientErrorValue; + +static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *); +static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *); +static Bool CreateResourceTypes(void); + +static Bool XvCloseScreen(int, ScreenPtr); +static Bool XvDestroyPixmap(PixmapPtr); +static Bool XvDestroyWindow(WindowPtr); +static void XvResetProc(ExtensionEntry*); +static int XvdiDestroyGrab(pointer, XID); +static int XvdiDestroyEncoding(pointer, XID); +static int XvdiDestroyVideoNotify(pointer, XID); +static int XvdiDestroyPortNotify(pointer, XID); +static int XvdiDestroyVideoNotifyList(pointer, XID); +static int XvdiDestroyPort(pointer, XID); +static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int); + + + + +/* +** XvExtensionInit +** +** +*/ + +void +XvExtensionInit() +{ + ExtensionEntry *extEntry; + + /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN + INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */ + if (XvScreenGeneration != serverGeneration) + { + if (!CreateResourceTypes()) + { + ErrorF("XvExtensionInit: Unable to allocate resource types\n"); + return; + } + XvScreenIndex = AllocateScreenPrivateIndex (); + if (XvScreenIndex < 0) + { + ErrorF("XvExtensionInit: Unable to allocate screen private index\n"); + return; + } +#ifdef PANORAMIX + XineramaRegisterConnectionBlockCallback(XineramifyXv); +#endif + XvScreenGeneration = serverGeneration; + } + + if (XvExtensionGeneration != serverGeneration) + { + XvExtensionGeneration = serverGeneration; + + extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, + ProcXvDispatch, SProcXvDispatch, + XvResetProc, StandardMinorOpcode); + if (!extEntry) + { + FatalError("XvExtensionInit: AddExtensions failed\n"); + } + + XvReqCode = extEntry->base; + XvEventBase = extEntry->eventBase; + XvErrorBase = extEntry->errorBase; + + EventSwapVector[XvEventBase+XvVideoNotify] = + (EventSwapPtr)WriteSwappedVideoNotifyEvent; + EventSwapVector[XvEventBase+XvPortNotify] = + (EventSwapPtr)WriteSwappedPortNotifyEvent; + + (void)MakeAtom(XvName, strlen(XvName), xTrue); + + } +} + +static Bool +CreateResourceTypes() + +{ + + if (XvResourceGeneration == serverGeneration) return TRUE; + + XvResourceGeneration = serverGeneration; + + if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort))) + { + ErrorF("CreateResourceTypes: failed to allocate port resource.\n"); + return FALSE; + } + + if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab))) + { + ErrorF("CreateResourceTypes: failed to allocate grab resource.\n"); + return FALSE; + } + + if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding))) + { + ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n"); + return FALSE; + } + + if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify))) + { + ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n"); + return FALSE; + } + + if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList))) + { + ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n"); + return FALSE; + } + + if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify))) + { + ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n"); + return FALSE; + } + + return TRUE; + +} + +int +XvScreenInit(ScreenPtr pScreen) +{ + XvScreenPtr pxvs; + + if (XvScreenGeneration != serverGeneration) + { + if (!CreateResourceTypes()) + { + ErrorF("XvScreenInit: Unable to allocate resource types\n"); + return BadAlloc; + } + XvScreenIndex = AllocateScreenPrivateIndex (); + if (XvScreenIndex < 0) + { + ErrorF("XvScreenInit: Unable to allocate screen private index\n"); + return BadAlloc; + } +#ifdef PANORAMIX + XineramaRegisterConnectionBlockCallback(XineramifyXv); +#endif + XvScreenGeneration = serverGeneration; + } + + if (pScreen->devPrivates[XvScreenIndex].ptr) + { + ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n"); + } + + /* ALLOCATE SCREEN PRIVATE RECORD */ + + pxvs = (XvScreenPtr) xalloc (sizeof (XvScreenRec)); + if (!pxvs) + { + ErrorF("XvScreenInit: Unable to allocate screen private structure\n"); + return BadAlloc; + } + + pScreen->devPrivates[XvScreenIndex].ptr = (pointer)pxvs; + + + pxvs->DestroyPixmap = pScreen->DestroyPixmap; + pxvs->DestroyWindow = pScreen->DestroyWindow; + pxvs->CloseScreen = pScreen->CloseScreen; + + pScreen->DestroyPixmap = XvDestroyPixmap; + pScreen->DestroyWindow = XvDestroyWindow; + pScreen->CloseScreen = XvCloseScreen; + + return Success; +} + +static Bool +XvCloseScreen( + int ii, + ScreenPtr pScreen +){ + + XvScreenPtr pxvs; + + pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr; + + pScreen->DestroyPixmap = pxvs->DestroyPixmap; + pScreen->DestroyWindow = pxvs->DestroyWindow; + pScreen->CloseScreen = pxvs->CloseScreen; + + (* pxvs->ddCloseScreen)(ii, pScreen); + + xfree(pxvs); + + pScreen->devPrivates[XvScreenIndex].ptr = (pointer)NULL; + + return (*pScreen->CloseScreen)(ii, pScreen); + +} + +static void +XvResetProc(ExtensionEntry* extEntry) +{ +} + +int +XvGetScreenIndex() +{ + return XvScreenIndex; +} + +unsigned long +XvGetRTPort() +{ + return XvRTPort; +} + +static Bool +XvDestroyPixmap(PixmapPtr pPix) +{ + Bool status; + ScreenPtr pScreen; + XvScreenPtr pxvs; + XvAdaptorPtr pa; + int na; + XvPortPtr pp; + int np; + + pScreen = pPix->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, DestroyPixmap); + + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* CHECK TO SEE IF THIS PORT IS IN USE */ + + pa = pxvs->pAdaptors; + na = pxvs->nAdaptors; + while (na--) + { + np = pa->nPorts; + pp = pa->pPorts; + + while (np--) + { + if (pp->pDraw == (DrawablePtr)pPix) + { + XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); + + (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, + pp->pDraw); + + pp->pDraw = (DrawablePtr)NULL; + pp->client = (ClientPtr)NULL; + pp->time = currentTime; + } + pp++; + } + pa++; + } + + status = (* pScreen->DestroyPixmap)(pPix); + + SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap); + + return status; + +} + +static Bool +XvDestroyWindow(WindowPtr pWin) +{ + Bool status; + ScreenPtr pScreen; + XvScreenPtr pxvs; + XvAdaptorPtr pa; + int na; + XvPortPtr pp; + int np; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, DestroyWindow); + + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* CHECK TO SEE IF THIS PORT IS IN USE */ + + pa = pxvs->pAdaptors; + na = pxvs->nAdaptors; + while (na--) + { + np = pa->nPorts; + pp = pa->pPorts; + + while (np--) + { + if (pp->pDraw == (DrawablePtr)pWin) + { + XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); + + (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, + pp->pDraw); + + pp->pDraw = (DrawablePtr)NULL; + pp->client = (ClientPtr)NULL; + pp->time = currentTime; + } + pp++; + } + pa++; + } + + + status = (* pScreen->DestroyWindow)(pWin); + + SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow); + + return status; + +} + +/* The XvdiVideoStopped procedure is a hook for the device dependent layer. + It provides a way for the dd layer to inform the di layer that video has + stopped in a port for reasons that the di layer had no control over; note + that it doesn't call back into the dd layer */ + +int +XvdiVideoStopped(XvPortPtr pPort, int reason) +{ + + /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ + + if (!pPort->pDraw) return Success; + + XvdiSendVideoNotify(pPort, pPort->pDraw, reason); + + pPort->pDraw = (DrawablePtr)NULL; + pPort->client = (ClientPtr)NULL; + pPort->time = currentTime; + + return Success; + +} + +static int +XvdiDestroyPort(pointer pPort, XID id) +{ + return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort); +} + +static int +XvdiDestroyGrab(pointer pGrab, XID id) +{ + ((XvGrabPtr)pGrab)->client = (ClientPtr)NULL; + return Success; +} + +static int +XvdiDestroyVideoNotify(pointer pn, XID id) +{ + /* JUST CLEAR OUT THE client POINTER FIELD */ + + ((XvVideoNotifyPtr)pn)->client = (ClientPtr)NULL; + return Success; +} + +static int +XvdiDestroyPortNotify(pointer pn, XID id) +{ + /* JUST CLEAR OUT THE client POINTER FIELD */ + + ((XvPortNotifyPtr)pn)->client = (ClientPtr)NULL; + return Success; +} + +static int +XvdiDestroyVideoNotifyList(pointer pn, XID id) +{ + XvVideoNotifyPtr npn,cpn; + + /* ACTUALLY DESTROY THE NOTITY LIST */ + + cpn = (XvVideoNotifyPtr)pn; + + while (cpn) + { + npn = cpn->next; + if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify); + xfree(cpn); + cpn = npn; + } + return Success; +} + +static int +XvdiDestroyEncoding(pointer value, XID id) +{ + return Success; +} + +static int +XvdiSendVideoNotify(pPort, pDraw, reason) + +XvPortPtr pPort; +DrawablePtr pDraw; +int reason; + +{ + xvEvent event; + XvVideoNotifyPtr pn; + + pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList); + + while (pn) + { + if (pn->client) + { + event.u.u.type = XvEventBase + XvVideoNotify; + event.u.u.sequenceNumber = pn->client->sequence; + event.u.videoNotify.time = currentTime.milliseconds; + event.u.videoNotify.drawable = pDraw->id; + event.u.videoNotify.port = pPort->id; + event.u.videoNotify.reason = reason; + (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask, + NoEventMask, NullGrab); + } + pn = pn->next; + } + + return Success; + +} + + +int +XvdiSendPortNotify( + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + xvEvent event; + XvPortNotifyPtr pn; + + pn = pPort->pNotify; + + while (pn) + { + if (pn->client) + { + event.u.u.type = XvEventBase + XvPortNotify; + event.u.u.sequenceNumber = pn->client->sequence; + event.u.portNotify.time = currentTime.milliseconds; + event.u.portNotify.port = pPort->id; + event.u.portNotify.attribute = attribute; + event.u.portNotify.value = value; + (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask, + NoEventMask, NullGrab); + } + pn = pn->next; + } + + return Success; + +} + + +#define CHECK_SIZE(dw, dh, sw, sh) { \ + if(!dw || !dh || !sw || !sh) return Success; \ + /* The region code will break these if they are too large */ \ + if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \ + return BadValue; \ +} + + +int +XvdiPutVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + DrawablePtr pOldDraw; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED + EVENTS TO ANY CLIENTS WHO WANT THEM */ + + pOldDraw = pPort->pDraw; + if ((pOldDraw) && (pOldDraw != pDraw)) + { + XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); + } + + (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + if ((pPort->pDraw) && (pOldDraw != pDraw)) + { + pPort->client = client; + XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); + } + + pPort->time = currentTime; + + return (Success); + +} + +int +XvdiPutStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + int status; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + pPort->time = currentTime; + + status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + return status; + +} + +int +XvdiPutImage( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 src_x, INT16 src_y, + CARD16 src_w, CARD16 src_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h, + XvImagePtr image, + unsigned char* data, + Bool sync, + CARD16 width, CARD16 height +){ + CHECK_SIZE(drw_w, drw_h, src_w, src_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + pPort->time = currentTime; + + return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC, + src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h, + image, data, sync, width, height); +} + + +int +XvdiGetVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + DrawablePtr pOldDraw; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED + EVENTS TO ANY CLIENTS WHO WANT THEM */ + + pOldDraw = pPort->pDraw; + if ((pOldDraw) && (pOldDraw != pDraw)) + { + XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); + } + + (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + if ((pPort->pDraw) && (pOldDraw != pDraw)) + { + pPort->client = client; + XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); + } + + pPort->time = currentTime; + + return (Success); + +} + +int +XvdiGetStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + int status; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + pPort->time = currentTime; + + return status; + +} + +int +XvdiGrabPort( + ClientPtr client, + XvPortPtr pPort, + Time ctime, + int *p_result +){ + unsigned long id; + TimeStamp time; + + UpdateCurrentTime(); + time = ClientTimeToServerTime(ctime); + + if (pPort->grab.client && (client != pPort->grab.client)) + { + *p_result = XvAlreadyGrabbed; + return Success; + } + + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, pPort->time) == EARLIER)) + { + *p_result = XvInvalidTime; + return Success; + } + + if (client == pPort->grab.client) + { + *p_result = Success; + return Success; + } + + id = FakeClientID(client->index); + + if (!AddResource(id, XvRTGrab, &pPort->grab)) + { + return BadAlloc; + } + + /* IF THERE IS ACTIVE VIDEO THEN STOP IT */ + + if ((pPort->pDraw) && (client != pPort->client)) + { + XVCALL(diStopVideo)((ClientPtr)NULL, pPort, pPort->pDraw); + } + + pPort->grab.client = client; + pPort->grab.id = id; + + pPort->time = currentTime; + + *p_result = Success; + + return Success; + +} + +int +XvdiUngrabPort( + ClientPtr client, + XvPortPtr pPort, + Time ctime +){ + TimeStamp time; + + UpdateCurrentTime(); + time = ClientTimeToServerTime(ctime); + + if ((!pPort->grab.client) || (client != pPort->grab.client)) + { + return Success; + } + + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, pPort->time) == EARLIER)) + { + return Success; + } + + /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */ + + FreeResource(pPort->grab.id, XvRTGrab); + pPort->grab.client = (ClientPtr)NULL; + + pPort->time = currentTime; + + return Success; + +} + + +int +XvdiSelectVideoNotify( + ClientPtr client, + DrawablePtr pDraw, + BOOL onoff +){ + XvVideoNotifyPtr pn,tpn,fpn; + + /* FIND VideoNotify LIST */ + + pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList); + + /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */ + + if (!onoff && !pn) return Success; + + /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST + WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */ + + if (!pn) + { + if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec)))) + return BadAlloc; + tpn->next = (XvVideoNotifyPtr)NULL; + if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn)) + { + xfree(tpn); + return BadAlloc; + } + } + else + { + /* LOOK TO SEE IF ENTRY ALREADY EXISTS */ + + fpn = (XvVideoNotifyPtr)NULL; + tpn = pn; + while (tpn) + { + if (tpn->client == client) + { + if (!onoff) tpn->client = (ClientPtr)NULL; + return Success; + } + if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */ + tpn = tpn->next; + } + + /* IF TUNNING OFF, THEN JUST RETURN */ + + if (!onoff) return Success; + + /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */ + + if (fpn) + { + tpn = fpn; + } + else + { + if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec)))) + return BadAlloc; + tpn->next = pn->next; + pn->next = tpn; + } + } + + /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */ + /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */ + + tpn->client = (ClientPtr)NULL; + tpn->id = FakeClientID(client->index); + AddResource(tpn->id, XvRTVideoNotify, tpn); + + tpn->client = client; + return Success; + +} + +int +XvdiSelectPortNotify( + ClientPtr client, + XvPortPtr pPort, + BOOL onoff +){ + XvPortNotifyPtr pn,tpn; + + /* SEE IF CLIENT IS ALREADY IN LIST */ + + tpn = (XvPortNotifyPtr)NULL; + pn = pPort->pNotify; + while (pn) + { + if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */ + if (pn->client == client) break; + pn = pn->next; + } + + /* IS THE CLIENT ALREADY ON THE LIST? */ + + if (pn) + { + /* REMOVE IT? */ + + if (!onoff) + { + pn->client = (ClientPtr)NULL; + FreeResource(pn->id, XvRTPortNotify); + } + + return Success; + } + + /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE + CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */ + + if (!tpn) + { + if (!(tpn = (XvPortNotifyPtr)xalloc(sizeof(XvPortNotifyRec)))) + return BadAlloc; + tpn->next = pPort->pNotify; + pPort->pNotify = tpn; + } + + tpn->client = client; + tpn->id = FakeClientID(client->index); + AddResource(tpn->id, XvRTPortNotify, tpn); + + return Success; + +} + +int +XvdiStopVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + int status; + + /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ + + if (!pPort->pDraw || (pPort->pDraw != pDraw)) + { + XvdiSendVideoNotify(pPort, pDraw, XvStopped); + return Success; + } + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + XvdiSendVideoNotify(pPort, pDraw, XvStopped); + + status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw); + + pPort->pDraw = (DrawablePtr)NULL; + pPort->client = (ClientPtr)client; + pPort->time = currentTime; + + return status; + +} + +int +XvdiPreemptVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + int status; + + /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ + + if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success; + + XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); + + status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw); + + pPort->pDraw = (DrawablePtr)NULL; + pPort->client = (ClientPtr)client; + pPort->time = currentTime; + + return status; + +} + +int +XvdiMatchPort( + XvPortPtr pPort, + DrawablePtr pDraw +){ + + XvAdaptorPtr pa; + XvFormatPtr pf; + int nf; + + pa = pPort->pAdaptor; + + if (pa->pScreen != pDraw->pScreen) return BadMatch; + + nf = pa->nFormats; + pf = pa->pFormats; + + while (nf--) + { + if ((pf->depth == pDraw->depth) +#if 0 + && ((pDraw->type == DRAWABLE_PIXMAP) || + (wVisual(((WindowPtr)pDraw)) == pf->visual)) +#endif + ) + return Success; + pf++; + } + + return BadMatch; + +} + +int +XvdiSetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + + XvdiSendPortNotify(pPort, attribute, value); + + return + (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value); + +} + +int +XvdiGetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 *p_value +){ + + return + (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value); + +} + +static void +WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to) + +{ + + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.videoNotify.sequenceNumber, + to->u.videoNotify.sequenceNumber); + cpswapl(from->u.videoNotify.time, to->u.videoNotify.time); + cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable); + cpswapl(from->u.videoNotify.port, to->u.videoNotify.port); + +} + +static void +WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to) + +{ + + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber); + cpswapl(from->u.portNotify.time, to->u.portNotify.time); + cpswapl(from->u.portNotify.port, to->u.portNotify.port); + cpswapl(from->u.portNotify.value, to->u.portNotify.value); + +} diff --git a/nx-X11/programs/Xserver/Xext/xvmc.c b/nx-X11/programs/Xserver/Xext/xvmc.c new file mode 100644 index 000000000..37fb153ab --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvmc.c @@ -0,0 +1,796 @@ +/* $XFree86: xc/programs/Xserver/Xext/xvmc.c,v 1.8 2003/07/16 01:38:31 dawes Exp $ */ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include <X11/Xfuncproto.h> +#include "xvdix.h" +#include <X11/extensions/XvMC.h> +#include <X11/extensions/Xvproto.h> +#include <X11/extensions/XvMCproto.h> +#include "xvmcext.h" + +#ifdef HAS_XVMCSHM +#ifndef Lynx +#include <sys/ipc.h> +#include <sys/types.h> +#include <sys/shm.h> +#else +#include <ipc.h> +#include <shm.h> +#endif /* Lynx */ +#endif /* HAS_XVMCSHM */ + + + +#define DR_CLIENT_DRIVER_NAME_SIZE 48 +#define DR_BUSID_SIZE 48 + +int XvMCScreenIndex = -1; + +unsigned long XvMCGeneration = 0; + +int XvMCReqCode; +int XvMCEventBase; +int XvMCErrorBase; + +unsigned long XvMCRTContext; +unsigned long XvMCRTSurface; +unsigned long XvMCRTSubpicture; + +typedef struct { + int num_adaptors; + XvMCAdaptorPtr adaptors; + CloseScreenProcPtr CloseScreen; + char clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE]; + char busID[DR_BUSID_SIZE]; + int major; + int minor; + int patchLevel; +} XvMCScreenRec, *XvMCScreenPtr; + +#define XVMC_GET_PRIVATE(pScreen) \ + (XvMCScreenPtr)((pScreen)->devPrivates[XvMCScreenIndex].ptr) + + +static int +XvMCDestroyContextRes(pointer data, XID id) +{ + XvMCContextPtr pContext = (XvMCContextPtr)data; + + pContext->refcnt--; + + if(!pContext->refcnt) { + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + (*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext)(pContext); + xfree(pContext); + } + + return Success; +} + +static int +XvMCDestroySurfaceRes(pointer data, XID id) +{ + XvMCSurfacePtr pSurface = (XvMCSurfacePtr)data; + XvMCContextPtr pContext = pSurface->context; + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + (*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface)(pSurface); + xfree(pSurface); + + XvMCDestroyContextRes((pointer)pContext, pContext->context_id); + + return Success; +} + + +static int +XvMCDestroySubpictureRes(pointer data, XID id) +{ + XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr)data; + XvMCContextPtr pContext = pSubpict->context; + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + (*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture)(pSubpict); + xfree(pSubpict); + + XvMCDestroyContextRes((pointer)pContext, pContext->context_id); + + return Success; +} + +static void +XvMCResetProc (ExtensionEntry *extEntry) +{ +} + + +static int +ProcXvMCQueryVersion(ClientPtr client) +{ + xvmcQueryVersionReply rep; + /* REQUEST(xvmcQueryVersionReq); */ + REQUEST_SIZE_MATCH(xvmcQueryVersionReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.major = XvMCVersion; + rep.minor = XvMCRevision; + WriteToClient(client, sizeof(xvmcQueryVersionReply), (char*)&rep); + return Success; +} + + +static int +ProcXvMCListSurfaceTypes(ClientPtr client) +{ + XvPortPtr pPort; + int i; + XvMCScreenPtr pScreenPriv; + xvmcListSurfaceTypesReply rep; + xvmcSurfaceInfo info; + XvMCAdaptorPtr adaptor = NULL; + XvMCSurfaceInfoPtr surface; + REQUEST(xvmcListSurfaceTypesReq); + REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client))) { + client->errorValue = stuff->port; + return _XvBadPort; + } + + if(XvMCScreenIndex >= 0) { /* any adaptors at all */ + ScreenPtr pScreen = pPort->pAdaptor->pScreen; + if((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */ + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + break; + } + } + } + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num = (adaptor) ? adaptor->num_surfaces : 0; + rep.length = rep.num * sizeof(xvmcSurfaceInfo) >> 2; + + WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), (char*)&rep); + + for(i = 0; i < rep.num; i++) { + surface = adaptor->surfaces[i]; + info.surface_type_id = surface->surface_type_id; + info.chroma_format = surface->chroma_format; + info.max_width = surface->max_width; + info.max_height = surface->max_height; + info.subpicture_max_width = surface->subpicture_max_width; + info.subpicture_max_height = surface->subpicture_max_height; + info.mc_type = surface->mc_type; + info.flags = surface->flags; + WriteToClient(client, sizeof(xvmcSurfaceInfo), (char*)&info); + } + + return Success; +} + +static int +ProcXvMCCreateContext(ClientPtr client) +{ + XvPortPtr pPort; + CARD32 *data = NULL; + int dwords = 0; + int i, result, adapt_num = -1; + ScreenPtr pScreen; + XvMCContextPtr pContext; + XvMCScreenPtr pScreenPriv; + XvMCAdaptorPtr adaptor = NULL; + XvMCSurfaceInfoPtr surface = NULL; + xvmcCreateContextReply rep; + REQUEST(xvmcCreateContextReq); + REQUEST_SIZE_MATCH(xvmcCreateContextReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client))) { + client->errorValue = stuff->port; + return _XvBadPort; + } + + pScreen = pPort->pAdaptor->pScreen; + + if(XvMCScreenIndex < 0) /* no XvMC adaptors */ + return BadMatch; + + if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */ + return BadMatch; + + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + adapt_num = i; + break; + } + } + + if(adapt_num < 0) /* none this port */ + return BadMatch; + + for(i = 0; i < adaptor->num_surfaces; i++) { + if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { + surface = adaptor->surfaces[i]; + break; + } + } + + /* adaptor doesn't support this suface_type_id */ + if(!surface) return BadMatch; + + + if((stuff->width > surface->max_width) || + (stuff->height > surface->max_height)) + return BadValue; + + if(!(pContext = xalloc(sizeof(XvMCContextRec)))) { + return BadAlloc; + } + + + pContext->pScreen = pScreen; + pContext->adapt_num = adapt_num; + pContext->context_id = stuff->context_id; + pContext->surface_type_id = stuff->surface_type_id; + pContext->width = stuff->width; + pContext->height = stuff->height; + pContext->flags = stuff->flags; + pContext->refcnt = 1; + + result = (*adaptor->CreateContext)(pPort, pContext, &dwords, &data); + + if(result != Success) { + xfree(pContext); + return result; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.width_actual = pContext->width; + rep.height_actual = pContext->height; + rep.flags_return = pContext->flags; + rep.length = dwords; + + WriteToClient(client, sizeof(xvmcCreateContextReply), (char*)&rep); + if(dwords) + WriteToClient(client, dwords << 2, (char*)data); + AddResource(pContext->context_id, XvMCRTContext, pContext); + + if(data) + xfree(data); + + return Success; +} + +static int +ProcXvMCDestroyContext(ClientPtr client) +{ + REQUEST(xvmcDestroyContextReq); + REQUEST_SIZE_MATCH(xvmcDestroyContextReq); + + if(!LookupIDByType(stuff->context_id, XvMCRTContext)) + return (XvMCBadContext + XvMCErrorBase); + + FreeResource(stuff->context_id, RT_NONE); + + return Success; +} + +static int +ProcXvMCCreateSurface(ClientPtr client) +{ + CARD32 *data = NULL; + int dwords = 0; + int result; + XvMCContextPtr pContext; + XvMCSurfacePtr pSurface; + XvMCScreenPtr pScreenPriv; + xvmcCreateSurfaceReply rep; + REQUEST(xvmcCreateSurfaceReq); + REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq); + + if(!(pContext = LookupIDByType(stuff->context_id, XvMCRTContext))) + return (XvMCBadContext + XvMCErrorBase); + + pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + if(!(pSurface = xalloc(sizeof(XvMCSurfaceRec)))) + return BadAlloc; + + pSurface->surface_id = stuff->surface_id; + pSurface->surface_type_id = pContext->surface_type_id; + pSurface->context = pContext; + + result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface)( + pSurface, &dwords, &data); + + if(result != Success) { + xfree(pSurface); + return result; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = dwords; + + WriteToClient(client, sizeof(xvmcCreateSurfaceReply), (char*)&rep); + if(dwords) + WriteToClient(client, dwords << 2, (char*)data); + AddResource(pSurface->surface_id, XvMCRTSurface, pSurface); + + if(data) + xfree(data); + + pContext->refcnt++; + + return Success; +} + +static int +ProcXvMCDestroySurface(ClientPtr client) +{ + REQUEST(xvmcDestroySurfaceReq); + REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq); + + if(!LookupIDByType(stuff->surface_id, XvMCRTSurface)) + return (XvMCBadSurface + XvMCErrorBase); + + FreeResource(stuff->surface_id, RT_NONE); + + return Success; +} + +static int +ProcXvMCCreateSubpicture(ClientPtr client) +{ + Bool image_supported = FALSE; + CARD32 *data = NULL; + int i, result, dwords = 0; + XvMCContextPtr pContext; + XvMCSubpicturePtr pSubpicture; + XvMCScreenPtr pScreenPriv; + xvmcCreateSubpictureReply rep; + XvMCAdaptorPtr adaptor; + XvMCSurfaceInfoPtr surface = NULL; + REQUEST(xvmcCreateSubpictureReq); + REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq); + + if(!(pContext = LookupIDByType(stuff->context_id, XvMCRTContext))) + return (XvMCBadContext + XvMCErrorBase); + + pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]); + + /* find which surface this context supports */ + for(i = 0; i < adaptor->num_surfaces; i++) { + if(adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id){ + surface = adaptor->surfaces[i]; + break; + } + } + + if(!surface) return BadMatch; + + /* make sure this surface supports that xvimage format */ + if(!surface->compatible_subpictures) return BadMatch; + + for(i = 0; i < surface->compatible_subpictures->num_xvimages; i++) { + if(surface->compatible_subpictures->xvimage_ids[i] == stuff->xvimage_id) { + image_supported = TRUE; + break; + } + } + + if(!image_supported) return BadMatch; + + /* make sure the size is OK */ + if((stuff->width > surface->subpicture_max_width) || + (stuff->height > surface->subpicture_max_height)) + return BadValue; + + if(!(pSubpicture = xalloc(sizeof(XvMCSubpictureRec)))) + return BadAlloc; + + pSubpicture->subpicture_id = stuff->subpicture_id; + pSubpicture->xvimage_id = stuff->xvimage_id; + pSubpicture->width = stuff->width; + pSubpicture->height = stuff->height; + pSubpicture->num_palette_entries = 0; /* overwritten by DDX */ + pSubpicture->entry_bytes = 0; /* overwritten by DDX */ + pSubpicture->component_order[0] = 0; /* overwritten by DDX */ + pSubpicture->component_order[1] = 0; + pSubpicture->component_order[2] = 0; + pSubpicture->component_order[3] = 0; + pSubpicture->context = pContext; + + result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSubpicture)( + pSubpicture, &dwords, &data); + + if(result != Success) { + xfree(pSubpicture); + return result; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.width_actual = pSubpicture->width; + rep.height_actual = pSubpicture->height; + rep.num_palette_entries = pSubpicture->num_palette_entries; + rep.entry_bytes = pSubpicture->entry_bytes; + rep.component_order[0] = pSubpicture->component_order[0]; + rep.component_order[1] = pSubpicture->component_order[1]; + rep.component_order[2] = pSubpicture->component_order[2]; + rep.component_order[3] = pSubpicture->component_order[3]; + rep.length = dwords; + + WriteToClient(client, sizeof(xvmcCreateSubpictureReply), (char*)&rep); + if(dwords) + WriteToClient(client, dwords << 2, (char*)data); + AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture); + + if(data) + xfree(data); + + pContext->refcnt++; + + return Success; +} + +static int +ProcXvMCDestroySubpicture(ClientPtr client) +{ + REQUEST(xvmcDestroySubpictureReq); + REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq); + + if(!LookupIDByType(stuff->subpicture_id, XvMCRTSubpicture)) + return (XvMCBadSubpicture + XvMCErrorBase); + + FreeResource(stuff->subpicture_id, RT_NONE); + + return Success; +} + + +static int +ProcXvMCListSubpictureTypes(ClientPtr client) +{ + XvPortPtr pPort; + xvmcListSubpictureTypesReply rep; + XvMCScreenPtr pScreenPriv; + ScreenPtr pScreen; + XvMCAdaptorPtr adaptor = NULL; + XvMCSurfaceInfoPtr surface = NULL; + xvImageFormatInfo info; + XvImagePtr pImage; + int i, j; + REQUEST(xvmcListSubpictureTypesReq); + REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client))) { + client->errorValue = stuff->port; + return _XvBadPort; + } + + pScreen = pPort->pAdaptor->pScreen; + + if(XvMCScreenIndex < 0) /* No XvMC adaptors */ + return BadMatch; + + if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) + return BadMatch; /* None this screen */ + + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + break; + } + } + + if(!adaptor) return BadMatch; + + for(i = 0; i < adaptor->num_surfaces; i++) { + if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { + surface = adaptor->surfaces[i]; + break; + } + } + + if(!surface) return BadMatch; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num = 0; + if(surface->compatible_subpictures) + rep.num = surface->compatible_subpictures->num_xvimages; + + rep.length = rep.num * sizeof(xvImageFormatInfo) >> 2; + + WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), (char*)&rep); + + for(i = 0; i < rep.num; i++) { + pImage = NULL; + for(j = 0; j < adaptor->num_subpictures; j++) { + if(surface->compatible_subpictures->xvimage_ids[i] == + adaptor->subpictures[j]->id) + { + pImage = adaptor->subpictures[j]; + break; + } + } + if(!pImage) return BadImplementation; + + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + WriteToClient(client, sizeof(xvImageFormatInfo), (char*)&info); + } + + return Success; +} + +static int +ProcXvMCGetDRInfo(ClientPtr client) +{ + xvmcGetDRInfoReply rep; + XvPortPtr pPort; + ScreenPtr pScreen; + XvMCScreenPtr pScreenPriv; + +#ifdef HAS_XVMCSHM + volatile CARD32 *patternP; +#endif + + REQUEST(xvmcGetDRInfoReq); + REQUEST_SIZE_MATCH(xvmcGetDRInfoReq); + + + if(!(pPort = LOOKUP_PORT(stuff->port, client))) { + client->errorValue = stuff->port; + return _XvBadPort; + } + + pScreen = pPort->pAdaptor->pScreen; + pScreenPriv = XVMC_GET_PRIVATE(pScreen); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.major = pScreenPriv->major; + rep.minor = pScreenPriv->minor; + rep.patchLevel = pScreenPriv->patchLevel; + rep.nameLen = (strlen(pScreenPriv->clientDriverName) + 4) >> 2; + rep.busIDLen = (strlen(pScreenPriv->busID) + 4) >> 2; + + rep.length = rep.nameLen + rep.busIDLen; + rep.nameLen <<=2; + rep.busIDLen <<=2; + + /* + * Read back to the client what she has put in the shared memory + * segment she prepared for us. + */ + + rep.isLocal = 1; +#ifdef HAS_XVMCSHM + patternP = (CARD32 *)shmat( stuff->shmKey, NULL, SHM_RDONLY ); + if ( -1 != (long) patternP) { + register volatile CARD32 *patternC = patternP; + register int i; + CARD32 magic = stuff->magic; + + rep.isLocal = 1; + i = 1024 / sizeof(CARD32); + + while ( i-- ) { + if (*patternC++ != magic) { + rep.isLocal = 0; + break; + } + magic = ~magic; + } + shmdt( (char *)patternP ); + } +#endif /* HAS_XVMCSHM */ + + WriteToClient(client, sizeof(xvmcGetDRInfoReply), + (char*)&rep); + if (rep.length) { + WriteToClient(client, rep.nameLen, + pScreenPriv->clientDriverName); + WriteToClient(client, rep.busIDLen, + pScreenPriv->busID); + } + return Success; +} + + +int (*ProcXvMCVector[xvmcNumRequest])(ClientPtr) = { + ProcXvMCQueryVersion, + ProcXvMCListSurfaceTypes, + ProcXvMCCreateContext, + ProcXvMCDestroyContext, + ProcXvMCCreateSurface, + ProcXvMCDestroySurface, + ProcXvMCCreateSubpicture, + ProcXvMCDestroySubpicture, + ProcXvMCListSubpictureTypes, + ProcXvMCGetDRInfo +}; + +static int +ProcXvMCDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if(stuff->data < xvmcNumRequest) + return (*ProcXvMCVector[stuff->data])(client); + else + return BadRequest; +} + +static int +SProcXvMCDispatch (ClientPtr client) +{ + /* We only support local */ + return BadImplementation; +} + +void +XvMCExtensionInit() +{ + ExtensionEntry *extEntry; + + if(XvMCScreenIndex < 0) /* nobody supports it */ + return; + + if(!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes))) + return; + + if(!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes))) + return; + + if(!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes))) + return; + + extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors, + ProcXvMCDispatch, SProcXvMCDispatch, + XvMCResetProc, StandardMinorOpcode); + + if(!extEntry) return; + + XvMCReqCode = extEntry->base; + XvMCEventBase = extEntry->eventBase; + XvMCErrorBase = extEntry->errorBase; +} + +static Bool +XvMCCloseScreen (int i, ScreenPtr pScreen) +{ + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + + xfree(pScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} + + +int +XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt) +{ + XvMCScreenPtr pScreenPriv; + + if(XvMCGeneration != serverGeneration) { + if((XvMCScreenIndex = AllocateScreenPrivateIndex()) < 0) + return BadAlloc; + + XvMCGeneration = serverGeneration; + } + + if(!(pScreenPriv = (XvMCScreenPtr)xalloc(sizeof(XvMCScreenRec)))) + return BadAlloc; + + pScreen->devPrivates[XvMCScreenIndex].ptr = (pointer)pScreenPriv; + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = XvMCCloseScreen; + + pScreenPriv->num_adaptors = num; + pScreenPriv->adaptors = pAdapt; + pScreenPriv->clientDriverName[0] = 0; + pScreenPriv->busID[0] = 0; + pScreenPriv->major = 0; + pScreenPriv->minor = 0; + pScreenPriv->patchLevel = 0; + + return Success; +} + +XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id) +{ + XvImagePtr pImage = NULL; + ScreenPtr pScreen = pPort->pAdaptor->pScreen; + XvMCScreenPtr pScreenPriv; + XvMCAdaptorPtr adaptor = NULL; + int i; + + if(XvMCScreenIndex < 0) return NULL; + + if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) + return NULL; + + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + break; + } + } + + if(!adaptor) return NULL; + + for(i = 0; i < adaptor->num_subpictures; i++) { + if(adaptor->subpictures[i]->id == id) { + pImage = adaptor->subpictures[i]; + break; + } + } + + return pImage; +} + +int +xf86XvMCRegisterDRInfo(ScreenPtr pScreen, char *name, + char *busID, int major, int minor, + int patchLevel) +{ + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); + strncpy(pScreenPriv->clientDriverName, name, + DR_CLIENT_DRIVER_NAME_SIZE); + strncpy(pScreenPriv->busID, busID, DR_BUSID_SIZE); + pScreenPriv->major = major; + pScreenPriv->minor = minor; + pScreenPriv->patchLevel = patchLevel; + pScreenPriv->clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE-1] = 0; + pScreenPriv->busID[DR_BUSID_SIZE-1] = 0; + return Success; +} + diff --git a/nx-X11/programs/Xserver/Xext/xvmcext.h b/nx-X11/programs/Xserver/Xext/xvmcext.h new file mode 100644 index 000000000..c7eba30ad --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvmcext.h @@ -0,0 +1,116 @@ +/* $XFree86: xc/programs/Xserver/Xext/xvmcext.h,v 1.1 2001/04/07 11:04:21 alanh Exp $ */ + +#ifndef _XVMC_H +#define _XVMC_H +#include <X11/extensions/Xv.h> +#include "xvdix.h" + +typedef struct { + int num_xvimages; + int *xvimage_ids; +} XvMCImageIDList; + +typedef struct { + int surface_type_id; + int chroma_format; + int color_description; + unsigned short max_width; + unsigned short max_height; + unsigned short subpicture_max_width; + unsigned short subpicture_max_height; + int mc_type; + int flags; + XvMCImageIDList *compatible_subpictures; +} XvMCSurfaceInfoRec, *XvMCSurfaceInfoPtr; + +typedef struct { + XID context_id; + ScreenPtr pScreen; + int adapt_num; + int surface_type_id; + unsigned short width; + unsigned short height; + CARD32 flags; + int refcnt; + pointer port_priv; + pointer driver_priv; +} XvMCContextRec, *XvMCContextPtr; + +typedef struct { + XID surface_id; + int surface_type_id; + XvMCContextPtr context; + pointer driver_priv; +} XvMCSurfaceRec, *XvMCSurfacePtr; + + +typedef struct { + XID subpicture_id; + int xvimage_id; + unsigned short width; + unsigned short height; + int num_palette_entries; + int entry_bytes; + char component_order[4]; + XvMCContextPtr context; + pointer driver_priv; +} XvMCSubpictureRec, *XvMCSubpicturePtr; + +typedef int (*XvMCCreateContextProcPtr) ( + XvPortPtr port, + XvMCContextPtr context, + int *num_priv, + CARD32 **priv +); + +typedef void (*XvMCDestroyContextProcPtr) ( + XvMCContextPtr context +); + +typedef int (*XvMCCreateSurfaceProcPtr) ( + XvMCSurfacePtr surface, + int *num_priv, + CARD32 **priv +); + +typedef void (*XvMCDestroySurfaceProcPtr) ( + XvMCSurfacePtr surface +); + +typedef int (*XvMCCreateSubpictureProcPtr) ( + XvMCSubpicturePtr subpicture, + int *num_priv, + CARD32 **priv +); + +typedef void (*XvMCDestroySubpictureProcPtr) ( + XvMCSubpicturePtr subpicture +); + + +typedef struct { + XvAdaptorPtr xv_adaptor; + int num_surfaces; + XvMCSurfaceInfoPtr *surfaces; + int num_subpictures; + XvImagePtr *subpictures; + XvMCCreateContextProcPtr CreateContext; + XvMCDestroyContextProcPtr DestroyContext; + XvMCCreateSurfaceProcPtr CreateSurface; + XvMCDestroySurfaceProcPtr DestroySurface; + XvMCCreateSubpictureProcPtr CreateSubpicture; + XvMCDestroySubpictureProcPtr DestroySubpicture; +} XvMCAdaptorRec, *XvMCAdaptorPtr; + +void XvMCExtensionInit(void); + +int XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr adapt); + +XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id); + +int xf86XvMCRegisterDRInfo(ScreenPtr pScreen, char *name, + char *busID, int major, int minor, + int patchLevel); + + +#endif /* _XVMC_H */ diff --git a/nx-X11/programs/Xserver/Xext/xvmod.c b/nx-X11/programs/Xserver/Xext/xvmod.c new file mode 100644 index 000000000..7899f3a75 --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvmod.c @@ -0,0 +1,24 @@ +/* $XFree86: xc/programs/Xserver/Xext/xvmod.c,v 1.1 1998/08/13 14:45:36 dawes Exp $ */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "misc.h" +#include "scrnintstr.h" +#include "gc.h" +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include "xvdix.h" +#include "xvmodproc.h" + +void +XvRegister() +{ + XvScreenInitProc = XvScreenInit; + XvGetScreenIndexProc = XvGetScreenIndex; + XvGetRTPortProc = XvGetRTPort; + XvMCScreenInitProc = XvMCScreenInit; +} + diff --git a/nx-X11/programs/Xserver/Xext/xvmodproc.h b/nx-X11/programs/Xserver/Xext/xvmodproc.h new file mode 100644 index 000000000..b284e3f4e --- /dev/null +++ b/nx-X11/programs/Xserver/Xext/xvmodproc.h @@ -0,0 +1,14 @@ +/* $XFree86: xc/programs/Xserver/Xext/xvmodproc.h,v 1.2 2001/03/05 04:51:55 mvojkovi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xvmcext.h" + +extern int (*XvGetScreenIndexProc)(void); +extern unsigned long (*XvGetRTPortProc)(void); +extern int (*XvScreenInitProc)(ScreenPtr); +extern int (*XvMCScreenInitProc)(ScreenPtr, int, XvMCAdaptorPtr); + +extern void XvRegister(void); |